LocationContainerDistanceTolerance

This commit is contained in:
Mike Phares 2023-08-06 22:07:23 -07:00
parent a871868aaa
commit 6b940180fa
10 changed files with 130 additions and 48 deletions

View File

@ -4,10 +4,11 @@ using System.Text.Json;
using View_by_Distance.Distance.Models.Stateless; using View_by_Distance.Distance.Models.Stateless;
using View_by_Distance.FaceRecognitionDotNet; using View_by_Distance.FaceRecognitionDotNet;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Distance.Models; namespace View_by_Distance.Distance.Models;
public partial class E_Distance public partial class E_Distance : IDistance<MetadataExtractor.Directory>
{ {
private readonly List<string> _Moved; private readonly List<string> _Moved;
@ -411,7 +412,7 @@ public partial class E_Distance
}); });
} }
private static List<SortingContainer> GetSortingContainers(Map.Models.Configuration mapConfiguration, Shared.Models.Methods.IDistanceLimits distanceLimits, Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection) private static List<SortingContainer> GetSortingContainers(Map.Models.Configuration mapConfiguration, IDistanceLimits distanceLimits, Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection)
{ {
List<SortingContainer> results = new(); List<SortingContainer> results = new();
SortingContainer sortingContainer; SortingContainer sortingContainer;
@ -516,7 +517,7 @@ public partial class E_Distance
return results.ToArray(); 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<FaceDistance> faceDistanceEncodings, FaceDistanceContainer[] filteredFaceDistanceContainers) public static SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Map.Models.Configuration mapConfiguration, long ticks, Map.Models.MapLogic mapLogic, IDistanceLimits distanceLimits, List<FaceDistance> faceDistanceEncodings, FaceDistanceContainer[] filteredFaceDistanceContainers)
{ {
SortingContainer[] results; SortingContainer[] results;
List<SortingContainer> collection = new(); List<SortingContainer> collection = new();
@ -552,4 +553,65 @@ public partial class E_Distance
return results; return results;
} }
private static void ReviewLocationContainerDistanceTolerance(float locationContainerDistanceTolerance, DateTime dateTime, List<(string, FaceRecognitionDotNet.FaceEncoding)> collection)
{
List<string> files = new();
FaceDistance? faceDistanceEncoding = null;
List<FaceDistance> 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<FaceDistance> 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<MetadataExtractor.Directory>.ReviewLocationContainerDistanceTolerance(float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> 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<MetadataExtractor.Directory>? 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<Shared.Models.FaceEncoding>(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);
}
} }

View File

@ -307,7 +307,7 @@ public class D_Face
if (location is null) if (location is null)
continue; continue;
if (!results.Any(l => l.WholePercentages == locationContainer.WholePercentages)) 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) if (results.Count > 0)

View File

@ -265,6 +265,7 @@ public partial class DlibDotNet
configuration.DistanceRenameToMatch, configuration.DistanceRenameToMatch,
configuration.FaceConfidencePercent, configuration.FaceConfidencePercent,
configuration.FaceDistancePermyriad, configuration.FaceDistancePermyriad,
configuration.LocationContainerDistanceTolerance,
configuration.LocationDigits, configuration.LocationDigits,
configuration.MappingDefaultName, configuration.MappingDefaultName,
configuration.PersonBirthdayFirstYear, configuration.PersonBirthdayFirstYear,
@ -1103,7 +1104,7 @@ public partial class DlibDotNet
if (runToDoCollectionFirst) if (runToDoCollectionFirst)
mapLogic = null; mapLogic = null;
else 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) foreach (string outputResolution in _Configuration.OutputResolutions)
{ {
if (outputResolution.Any(l => char.IsNumber(l))) 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); fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = new() : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory);
B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory); 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); 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); FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, fileNameToCollection, mapLogic);
List<Item> distinctFilteredItems = Shared.Models.Stateless.Methods.IContainer.GetItems(_Configuration.PropertyConfiguration, containers, distinctItems: true, filterItems: true); List<Item> distinctFilteredItems = Shared.Models.Stateless.Methods.IContainer.GetItems(_Configuration.PropertyConfiguration, containers, distinctItems: true, filterItems: true);

View File

@ -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 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 PhotoPrism Locations"), Required] public bool? LoadPhotoPrismLocations { 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 Digits"), Required] public int? LocationDigits { get; set; }
[Display(Name = "Location Factor"), Required] public int? LocationFactor { get; set; } [Display(Name = "Location Factor"), Required] public int? LocationFactor { get; set; }
[Display(Name = "Look for Abandoned"), Required] public bool? LookForAbandoned { get; set; } [Display(Name = "Look for Abandoned"), Required] public bool? LookForAbandoned { get; set; }
@ -270,6 +271,7 @@ public class Configuration
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions,
configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions,
configuration.LoadPhotoPrismLocations.Value, configuration.LoadPhotoPrismLocations.Value,
configuration.LocationContainerDistanceTolerance,
configuration.LocationDigits.Value, configuration.LocationDigits.Value,
configuration.LocationFactor.Value, configuration.LocationFactor.Value,
configuration.LookForAbandoned.Value, configuration.LookForAbandoned.Value,

View File

@ -35,6 +35,7 @@ public class Configuration
public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; }
public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; }
public bool LoadPhotoPrismLocations { init; get; } public bool LoadPhotoPrismLocations { init; get; }
public float? LocationContainerDistanceTolerance { init; get; }
public int LocationDigits { init; get; } public int LocationDigits { init; get; }
public int LocationFactor { init; get; } public int LocationFactor { init; get; }
public bool LookForAbandoned { init; get; } public bool LookForAbandoned { init; get; }
@ -118,6 +119,7 @@ public class Configuration
string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions,
string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions,
bool loadPhotoPrismLocations, bool loadPhotoPrismLocations,
float? locationContainerDistanceTolerance,
int locationDigits, int locationDigits,
int locationFactor, int locationFactor,
bool lookForAbandoned, bool lookForAbandoned,
@ -199,6 +201,7 @@ public class Configuration
LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions;
LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions;
LoadPhotoPrismLocations = loadPhotoPrismLocations; LoadPhotoPrismLocations = loadPhotoPrismLocations;
LocationContainerDistanceTolerance = locationContainerDistanceTolerance;
LocationDigits = locationDigits; LocationDigits = locationDigits;
LocationFactor = locationFactor; LocationFactor = locationFactor;
LookForAbandoned = lookForAbandoned; LookForAbandoned = lookForAbandoned;

View File

@ -14,6 +14,7 @@ public class Configuration
public string FacePartsFileNameExtension { init; get; } public string FacePartsFileNameExtension { init; get; }
public string FacesFileNameExtension { init; get; } public string FacesFileNameExtension { init; get; }
public string FacesHiddenFileNameExtension { init; get; } public string FacesHiddenFileNameExtension { init; get; }
public float? LocationContainerDistanceTolerance { init; get; }
public int LocationDigits { init; get; } public int LocationDigits { init; get; }
public string MappingDefaultName { init; get; } public string MappingDefaultName { init; get; }
public int PersonBirthdayFirstYear { init; get; } public int PersonBirthdayFirstYear { init; get; }
@ -32,6 +33,7 @@ public class Configuration
bool distanceRenameToMatch, bool distanceRenameToMatch,
int faceConfidencePercent, int faceConfidencePercent,
int faceDistancePermyriad, int faceDistancePermyriad,
float? locationContainerDistanceTolerance,
int locationDigits, int locationDigits,
string mappingDefaultName, string mappingDefaultName,
int personBirthdayFirstYear, int personBirthdayFirstYear,
@ -62,10 +64,11 @@ public class Configuration
DeletePossibleDuplicates = deletePossibleDuplicates; DeletePossibleDuplicates = deletePossibleDuplicates;
SaveSortingWithoutPerson = saveSortingWithoutPerson; SaveSortingWithoutPerson = saveSortingWithoutPerson;
SortingMinimumToUseSigma = sortingMinimumToUseSigma; SortingMinimumToUseSigma = sortingMinimumToUseSigma;
DistanceMoveUnableToMatch = distanceMoveUnableToMatch;
RangeDaysDeltaTolerance = rangeDaysDeltaTolerance[1]; RangeDaysDeltaTolerance = rangeDaysDeltaTolerance[1];
DistanceMoveUnableToMatch = distanceMoveUnableToMatch;
FacePartsFileNameExtension = facePartsFileNameExtension; FacePartsFileNameExtension = facePartsFileNameExtension;
FacesHiddenFileNameExtension = facesHiddenFileNameExtension; FacesHiddenFileNameExtension = facesHiddenFileNameExtension;
LocationContainerDistanceTolerance = locationContainerDistanceTolerance;
} }
public override string ToString() public override string ToString()

View File

@ -26,7 +26,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
private readonly ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> _IdToLocationContainers; private readonly ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> _IdToLocationContainers;
private readonly ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> _IdThenWholePercentagesToPersonContainers; private readonly ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> _IdThenWholePercentagesToPersonContainers;
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, ReadOnlyCollection<PersonContainer> personContainers, long ticks, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, Shared.Models.Methods.IDistance<MetadataExtractor.Directory> distance, ReadOnlyCollection<PersonContainer> personContainers, long ticks, string a2PeopleSingletonDirectory, string eDistanceContentDirectory)
{ {
_Ticks = ticks; _Ticks = ticks;
_Configuration = configuration; _Configuration = configuration;
@ -58,7 +58,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection; ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection;
Stateless.MapLogic.SetSkipCollections(configuration, personContainers, a2PeopleSingletonDirectory, skipCollection, skipNotSkipCollection); Stateless.MapLogic.SetSkipCollections(configuration, personContainers, a2PeopleSingletonDirectory, skipCollection, skipNotSkipCollection);
List<Stateless.MapLogic.Record> records = Stateless.MapLogic.SetPersonCollectionsAndGetRecords(configuration, ticks, personContainers, eDistanceContentDirectory); List<Stateless.MapLogic.Record> 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; int lossCount = records.Count - locationContainers.Count;
ReadOnlyCollection<Stateless.MapLogic.PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection = Stateless.MapLogic.GetPersonKeyFormattedIdThenWholePercentages(configuration, ticks, records); ReadOnlyCollection<Stateless.MapLogic.PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection = Stateless.MapLogic.GetPersonKeyFormattedIdThenWholePercentages(configuration, ticks, records);
int unableToMatchCount = records.Count - personKeyFormattedIdThenWholePercentagesCollection.Count; int unableToMatchCount = records.Count - personKeyFormattedIdThenWholePercentagesCollection.Count;
@ -236,7 +236,8 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
result += UpdateMappingFromPerson(locationContainersFiles, mapping); result += UpdateMappingFromPerson(locationContainersFiles, mapping);
if (mapping.MappingFromPerson is null || mapping.MappingFromPerson.LocationContainersFiles.Count == 0) if (mapping.MappingFromPerson is null || mapping.MappingFromPerson.LocationContainersFiles.Count == 0)
continue; continue;
Stateless.MapLogic.MoveToDecade(propertyConfiguration, mapping.MappingFromItem, mapping.MappingFromPerson); if (_Configuration?.LocationContainerDistanceTolerance is null)
Stateless.MapLogic.MoveToDecade(propertyConfiguration, mapping.MappingFromItem, mapping.MappingFromPerson);
} }
return result; return result;
} }

View File

@ -15,9 +15,10 @@ internal abstract class MapLogic
{ {
internal record Record(string PersonKeyFormatted, internal record Record(string PersonKeyFormatted,
string[] PersonDisplayDirectoryNames, int DirectoryNumber,
bool IsDefault, string PersonDisplayDirectoryName,
string MappedFaceFile); bool IsDefault,
string MappedFaceFile);
internal record TicksDirectory(string Directory, internal record TicksDirectory(string Directory,
string DirectoryName, string DirectoryName,
@ -26,7 +27,7 @@ internal abstract class MapLogic
float? TotalDays); float? TotalDays);
internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted, internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted,
string[] PersonDisplayDirectoryNames, string PersonDisplayDirectoryName,
bool IsDefault, bool IsDefault,
string MappedFaceFile, string MappedFaceFile,
int Id, int Id,
@ -257,6 +258,7 @@ internal abstract class MapLogic
int totalSeconds; int totalSeconds;
DateTime dateTime; DateTime dateTime;
TimeSpan timeSpan; TimeSpan timeSpan;
int directoryNumber;
int? wholePercentages; int? wholePercentages;
string? checkDirectory; string? checkDirectory;
ProgressBar progressBar; ProgressBar progressBar;
@ -267,9 +269,9 @@ internal abstract class MapLogic
List<string> distinct = new(); List<string> distinct = new();
string[] personNameDirectories; string[] personNameDirectories;
string? newestPersonKeyFormatted; string? newestPersonKeyFormatted;
string personDisplayDirectoryName;
string[] personNameLinkDirectories; string[] personNameLinkDirectories;
string? personFirstInitialDirectory; string? personFirstInitialDirectory;
string[] personDisplayDirectoryNames;
List<TicksDirectory> ticksDirectories; List<TicksDirectory> ticksDirectories;
string[] personKeyFormattedDirectories; string[] personKeyFormattedDirectories;
string manualCopyHumanized = nameof(Shared.Models.Stateless.IMapLogic.ManualCopy).Humanize(LetterCasing.Title); string manualCopyHumanized = nameof(Shared.Models.Stateless.IMapLogic.ManualCopy).Humanize(LetterCasing.Title);
@ -280,6 +282,7 @@ internal abstract class MapLogic
check = false; check = false;
results.Clear(); results.Clear();
distinct.Clear(); distinct.Clear();
directoryNumber = 0;
ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(eDistanceContentDirectory); ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(eDistanceContentDirectory);
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); 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)"; 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); File.Delete(file);
foreach (string personNameDirectory in personNameDirectories) foreach (string personNameDirectory in personNameDirectories)
{ {
personDisplayDirectoryNames = IPath.GetDirectoryNames(personNameDirectory); directoryNumber++;
if (personDisplayDirectoryNames.Length == 0) personDisplayDirectoryName = Path.GetFileName(personNameDirectory);
continue; isDefault = personDisplayDirectoryName.First() == 'X' && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]);
isDefault = personDisplayDirectoryNames[^1].First() == 'X' && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]); if (isDefault && personDisplayDirectoryName.Length == 1)
if (isDefault && personDisplayDirectoryNames[^1].Length == 1)
{ {
if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length || !DateTime.TryParseExact(personKeyFormatted, configuration.PersonBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length || !DateTime.TryParseExact(personKeyFormatted, configuration.PersonBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
continue; continue;
@ -373,11 +375,11 @@ internal abstract class MapLogic
} }
if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length) if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length)
continue; continue;
if (personDisplayDirectoryNames[^1].Length == 1 || isDefault || !personKeyFormattedCollection.Contains(personKeyFormatted)) if (personDisplayDirectoryName.Length == 1 || isDefault || !personKeyFormattedCollection.Contains(personKeyFormatted))
personFirstInitialDirectory = personNameDirectory; personFirstInitialDirectory = personNameDirectory;
else else
{ {
personFirstInitial = personDisplayDirectoryNames[^1][..1]; personFirstInitial = personDisplayDirectoryName[..1];
if (personFirstInitial.All(l => char.IsDigit(l))) if (personFirstInitial.All(l => char.IsDigit(l)))
{ {
foreach (string file in files) foreach (string file in files)
@ -409,7 +411,7 @@ internal abstract class MapLogic
continue; continue;
} }
distinct.Add(fileName); distinct.Add(fileName);
results.Add(new(personKeyFormatted, personDisplayDirectoryNames, isDefault, mappedFaceFile)); results.Add(new(personKeyFormatted, directoryNumber, personDisplayDirectoryName, isDefault, mappedFaceFile));
} }
personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string personNameLinkDirectory in personNameLinkDirectories) foreach (string personNameLinkDirectory in personNameLinkDirectories)
@ -454,7 +456,6 @@ internal abstract class MapLogic
char status, sex, first; char status, sex, first;
PersonDirectory personDirectory; PersonDirectory personDirectory;
PersonContainer? personContainer; PersonContainer? personContainer;
string personDisplayDirectoryName;
foreach (PersonKeyFormattedIdThenWholePercentages personKeyFormattedIdThenWholePercentages in personKeyFormattedIdThenWholePercentagesCollection) foreach (PersonKeyFormattedIdThenWholePercentages personKeyFormattedIdThenWholePercentages in personKeyFormattedIdThenWholePercentagesCollection)
{ {
personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormattedIdThenWholePercentages.PersonKeyFormatted); personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormattedIdThenWholePercentages.PersonKeyFormatted);
@ -462,14 +463,13 @@ internal abstract class MapLogic
throw new Exception(); throw new Exception();
if (!personKeyFormattedToPersonContainer.TryGetValue(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, out personContainer)) if (!personKeyFormattedToPersonContainer.TryGetValue(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, out personContainer))
{ {
personDisplayDirectoryName = personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryNames[^1]; matches = configuration.PersonCharacters.Where(l => personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName.Contains(l)).ToArray();
matches = configuration.PersonCharacters.Where(l => personDisplayDirectoryName.Contains(l)).ToArray();
if (matches.Length == 0) if (matches.Length == 0)
throw new NotSupportedException(); throw new NotSupportedException();
group = IPerson.GetHourGroup(personDisplayDirectoryName, personBirthday.Value.Hour); group = IPerson.GetHourGroup(personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName, personBirthday.Value.Hour);
(status, sex, first) = IPerson.GetPersonHour(personDisplayDirectoryName, personBirthday.Value.Hour); (status, sex, first) = IPerson.GetPersonHour(personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName, personBirthday.Value.Hour);
personDirectory = new(matches.First(), group, status, sex, first); 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); personKeyFormattedToPersonContainer.Add(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, personContainer);
} }
if (personContainer.Key is null) if (personContainer.Key is null)
@ -588,7 +588,6 @@ internal abstract class MapLogic
List<PersonKeyFormattedIdThenWholePercentages> results = new(); List<PersonKeyFormattedIdThenWholePercentages> results = new();
int? id; int? id;
int? wholePercentages; int? wholePercentages;
string personDisplayDirectoryName;
List<int> wholePercentagesCollection; List<int> wholePercentagesCollection;
Dictionary<int, List<int>> idToWholePercentagesCollection = new(); Dictionary<int, List<int>> idToWholePercentagesCollection = new();
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); 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 = idToWholePercentagesCollection[id.Value];
wholePercentagesCollection.Add(wholePercentages.Value); wholePercentagesCollection.Add(wholePercentages.Value);
idToWholePercentagesCollection[id.Value].Add(wholePercentages.Value); idToWholePercentagesCollection[id.Value].Add(wholePercentages.Value);
personDisplayDirectoryName = record.PersonDisplayDirectoryNames[^1]; results.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.IsDefault, record.MappedFaceFile, id.Value, wholePercentages.Value));
if (string.IsNullOrEmpty(personDisplayDirectoryName))
continue;
results.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryNames, record.IsDefault, record.MappedFaceFile, id.Value, wholePercentages.Value));
} }
return new(results); return new(results);
} }
@ -821,9 +817,9 @@ internal abstract class MapLogic
return results; return results;
} }
private static List<(long, string)> GetDisplayDirectoryAllFiles(string fileNameExtension, ReadOnlyCollection<PersonContainer> personContainers) private static List<(long, int?, string)> GetDisplayDirectoryAllFiles(string fileNameExtension, ReadOnlyCollection<PersonContainer> personContainers)
{ {
List<(long, string)> results = new(); List<(long, int?, string)> results = new();
string fileName; string fileName;
List<string> distinct = new(); List<string> distinct = new();
foreach (PersonContainer personContainer in personContainers) foreach (PersonContainer personContainer in personContainers)
@ -838,15 +834,15 @@ internal abstract class MapLogic
if (distinct.Contains(fileName)) if (distinct.Contains(fileName))
continue; continue;
distinct.Add(fileName); distinct.Add(fileName);
results.Add(new(personContainer.Key.Value, displayDirectoryAllFile)); results.Add(new(personContainer.Key.Value, null, displayDirectoryAllFile));
} }
} }
return results; return results;
} }
private static List<(long PersonKey, string File)> GetCollection(Configuration configuration, ReadOnlyCollection<PersonContainer> personContainers, List<Record> records) private static List<(long PersonKey, int? DirectoryNumber, string File)> GetCollection(Configuration configuration, ReadOnlyCollection<PersonContainer> personContainers, List<Record> records)
{ {
List<(long PersonKey, string File)> results = new(); List<(long PersonKey, int? DirectoryNumber, string File)> results = new();
string file; string file;
long personKey; long personKey;
string fileName; string fileName;
@ -863,7 +859,7 @@ internal abstract class MapLogic
continue; continue;
distinct.Add(fileName); distinct.Add(fileName);
personKey = personBirthday.Value.Ticks; 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--) for (int i = results.Count - 1; i > -1; i--)
{ {
@ -878,12 +874,12 @@ internal abstract class MapLogic
if (!File.Exists(file)) if (!File.Exists(file))
continue; continue;
File.Move(file, file[..^4]); 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; return results;
} }
private static void ParallelFor(Configuration configuration, string eDistanceContentDirectory, Dictionary<int, List<(string, int)>> skipCollection, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, long personKey, string file) private static void ParallelFor(Configuration configuration, string eDistanceContentDirectory, Dictionary<int, List<(string, int)>> skipCollection, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, long personKey, int? directoryNumber, string file)
{ {
string[] fileMatches; string[] fileMatches;
const string lnk = ".lnk"; const string lnk = ".lnk";
@ -912,7 +908,7 @@ internal abstract class MapLogic
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file); directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file);
RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value); RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value);
lock (locationContainers) 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) private static void OpenPossibleDuplicates(Configuration configuration, List<(long, int, string, float?)> duplicates)
@ -987,10 +983,10 @@ internal abstract class MapLogic
} }
} }
internal static List<LocationContainer<MetadataExtractor.Directory>> GetLocationContainers(int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, string eDistanceContentDirectory, Dictionary<int, List<(string, int)>> skipCollection, List<Record> records) internal static List<LocationContainer<MetadataExtractor.Directory>> GetLocationContainers(Shared.Models.Methods.IDistance<MetadataExtractor.Directory> distance, int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, string eDistanceContentDirectory, Dictionary<int, List<(string, int)>> skipCollection, List<Record> records)
{ {
List<LocationContainer<MetadataExtractor.Directory>> results = new(); List<LocationContainer<MetadataExtractor.Directory>> 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)) if (collection.Count > 0 && (configuration.DistanceMoveUnableToMatch || configuration.DistanceRenameToMatch))
{ {
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); 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) => _ = Parallel.For(0, collection.Count, parallelOptions, (i, state) =>
{ {
progressBar.Tick(); 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<LocationContainer<MetadataExtractor.Directory>> 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; return results;
} }

View File

@ -2,5 +2,5 @@ using System.Drawing;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public record LocationContainer<T>(bool FromDistanceContent, string File, long PersonKey, int Id, int WholePercentages, IReadOnlyList<T> Directories, RectangleF? Rectangle, Location? Location) public record LocationContainer<T>(bool FromDistanceContent, int? DirectoryNumber, string File, long PersonKey, int Id, int WholePercentages, IReadOnlyList<T> Directories, RectangleF? Rectangle, Location? Location)
{ } { }

View File

@ -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<T>
{
void ReviewLocationContainerDistanceTolerance(float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer<T>> locationContainers);
}