SaveMappedForOutputResolutions

This commit is contained in:
2023-09-03 17:30:39 -07:00
parent a9d0f67227
commit 600f6e7e2b
15 changed files with 437 additions and 163 deletions

View File

@ -1,80 +1,23 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Map.Models;
public class Configuration
{
public bool DeletePossibleDuplicates { get; internal set; }
public bool DistanceMoveUnableToMatch { init; get; }
public bool DistanceRenameToMatch { init; get; }
public int FaceConfidencePercent { init; get; }
public int FaceDistancePermyriad { init; get; }
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; }
public string PersonBirthdayFormat { init; get; }
public char[] PersonCharacters { init; get; }
public int RangeDaysDeltaTolerance { init; get; }
public double RangeDistanceTolerance { init; get; }
public bool SaveSortingWithoutPerson { init; get; }
public string[] SkipNotSkipDirectories { init; get; }
public int SortingMaximumPerKey { init; get; }
public int SortingMinimumToUseSigma { init; get; }
[JsonConstructor]
public Configuration(bool deletePossibleDuplicates,
bool distanceMoveUnableToMatch,
bool distanceRenameToMatch,
int faceConfidencePercent,
int faceDistancePermyriad,
float? locationContainerDistanceTolerance,
int locationDigits,
string mappingDefaultName,
int personBirthdayFirstYear,
string personBirthdayFormat,
char[] personCharacters,
int[] rangeDaysDeltaTolerance,
float[] rangeDistanceTolerance,
bool saveSortingWithoutPerson,
string[] skipNotSkipDirectories,
int sortingMaximumPerKey,
int sortingMinimumToUseSigma,
string facesFileNameExtension,
string facesHiddenFileNameExtension,
string facePartsFileNameExtension)
{
LocationDigits = locationDigits;
PersonCharacters = personCharacters;
MappingDefaultName = mappingDefaultName;
PersonBirthdayFormat = personBirthdayFormat;
SortingMaximumPerKey = sortingMaximumPerKey;
DistanceRenameToMatch = distanceRenameToMatch;
FaceConfidencePercent = faceConfidencePercent;
FaceDistancePermyriad = faceDistancePermyriad;
FacesFileNameExtension = facesFileNameExtension;
SkipNotSkipDirectories = skipNotSkipDirectories;
PersonBirthdayFirstYear = personBirthdayFirstYear;
RangeDistanceTolerance = rangeDistanceTolerance[1];
DeletePossibleDuplicates = deletePossibleDuplicates;
SaveSortingWithoutPerson = saveSortingWithoutPerson;
SortingMinimumToUseSigma = sortingMinimumToUseSigma;
RangeDaysDeltaTolerance = rangeDaysDeltaTolerance[1];
DistanceMoveUnableToMatch = distanceMoveUnableToMatch;
FacePartsFileNameExtension = facePartsFileNameExtension;
FacesHiddenFileNameExtension = facesHiddenFileNameExtension;
LocationContainerDistanceTolerance = locationContainerDistanceTolerance;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}
public record Configuration(bool DeletePossibleDuplicates,
bool DistanceMoveUnableToMatch,
bool DistanceRenameToMatch,
int FaceConfidencePercent,
int FaceDistancePermyriad,
float? LocationContainerDistanceTolerance,
int LocationDigits,
string MappingDefaultName,
int PersonBirthdayFirstYear,
string PersonBirthdayFormat,
char[] PersonCharacters,
int[] RangeDaysDeltaTolerance,
float[] RangeDistanceTolerance,
bool SaveMappedRelations,
bool SaveSortingWithoutPerson,
string[] SkipNotSkipDirectories,
int SortingMaximumPerKey,
int SortingMinimumToUseSigma,
string FacesFileNameExtension,
string FacesHiddenFileNameExtension,
string FacePartsFileNameExtension);

View File

@ -1,4 +1,4 @@
using Humanizer;
using Humanizer;
using ShellProgressBar;
using System.Collections.ObjectModel;
using System.Globalization;
@ -226,7 +226,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
private readonly ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> _IdToLocationContainers;
private readonly ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> _IdThenWholePercentagesToPersonContainers;
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)
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, Shared.Models.Methods.IDistance<MetadataExtractor.Directory> distance, ReadOnlyCollection<PersonContainer> personContainers, long ticks, string? a2PeopleContentDirectory, string a2PeopleSingletonDirectory, string eDistanceContentDirectory)
{
_Ticks = ticks;
_Configuration = configuration;
@ -240,7 +240,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
Dictionary<int, List<(string, int)>> skipNotSkipCollection = new();
List<LocationContainer<MetadataExtractor.Directory>> locationContainers = new();
string? rootDirectoryParent = Path.GetDirectoryName(propertyConfiguration.RootDirectory);
string eDistanceContentTicksDirectory = Path.Combine(eDistanceContentDirectory, $"({ticks})");
string eDistanceContentTicksDirectory = Path.Combine(eDistanceContentDirectory, ticks.ToString());
ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> idThenWholePercentagesToPersonContainers;
if (string.IsNullOrEmpty(rootDirectoryParent))
throw new NullReferenceException(nameof(rootDirectoryParent));
@ -270,13 +270,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
}
List<Stateless.MapLogic.Record> records = Stateless.MapLogic.DeleteEmptyDirectoriesAndGetCollection(configuration, ticks, eDistanceContentDirectory, readOnlyPersonKeyFormattedToNewestPersonKeyFormatted, readOnlyPersonKeyFormattedCollection);
ReadOnlyCollection<(Stateless.MapLogic.PersonKeyFormattedIdThenWholePercentages, PersonContainer)> readOnlyPossiblyNewPersonDisplayDirectoryNamesAndPersonContainer;
locationContainers.AddRange(Stateless.MapLogic.GetLocationContainers(distance, maxDegreeOfParallelism, configuration, ticks, personContainers, eDistanceContentDirectory, skipCollection, records));
int lossCount = records.Count - locationContainers.Count;
ReadOnlyCollection<Stateless.MapLogic.PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection = Stateless.MapLogic.GetPersonKeyFormattedIdThenWholePercentages(configuration, ticks, records);
int unableToMatchCount = records.Count - personKeyFormattedIdThenWholePercentagesCollection.Count;
if (lossCount != 0 || unableToMatchCount != 0)
if (lossCount != 0 || unableToMatchCount != 0)
{ }
//
{
Dictionary<long, int> personKeyToCount = new();
@ -314,6 +308,20 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
ticks,
personContainers,
readOnlyPersonKeyToCount));
locationContainers.AddRange(Stateless.MapLogic.GetLocationContainers(distance,
maxDegreeOfParallelism,
configuration,
ticks,
personContainers,
skipCollection,
records));
int lossCount = records.Count - locationContainers.Count;
int unableToMatchCount = records.Count - personKeyFormattedIdThenWholePercentagesCollection.Count;
if (lossCount != 0 || unableToMatchCount != 0)
if (lossCount != 0 || unableToMatchCount != 0)
{ }
if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && configuration.SaveMappedRelations)
Stateless.MapLogic.SaveMappedRelations(configuration, distance, a2PeopleContentDirectory, eDistanceContentDirectory, ticks, locationContainers, readOnlyPersonKeyFormattedToPersonContainer, readOnlyPersonKeyToPersonContainerCollection);
}
_PersonKeyToCount = readOnlyPersonKeyToCount;
_EDistanceContentTicksDirectory = eDistanceContentTicksDirectory;
@ -548,11 +556,11 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
(ticks, directory) = GetDirectory(_Configuration, saveIndividually, padLeft, mapping.SegmentC, by, mapping.MappingFromItem);
if (ticks is null || string.IsNullOrEmpty(directory))
continue;
personDirectory = Path.Combine(directory, $"X]{ticks}");
personDirectory = Path.Combine(directory, $"X+{ticks}");
if (saveIndividually)
{
directory = Path.Combine(directory, mapping.MappingFromItem.Id.ToString());
results.Add(new(Path.Combine(directory, $"X]{ticks}")));
results.Add(new(Path.Combine(directory, $"X+{ticks}")));
}
distinct.Add(mapping.MappingFromItem.Id);
distinct.Add(mapping.SortingContainer.Sorting.Id);
@ -686,6 +694,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
FaceDistance faceDistanceLength;
List<int>? wholePercentagesCollection;
bool skipNotSkipCollectionAny = _SkipNotSkipCollection.Count > 0;
float distanceTolerance = _Configuration.RangeDistanceTolerance[1];
for (int j = 0; j < faceDistanceLengths.Count; j++)
{
if (faceDistanceEncoding.WholePercentages is null)
@ -705,7 +714,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
throw new NotSupportedException();
if (faceDistanceLength.Length == 0)
continue;
sorting = ISorting.Get(_Configuration.FaceDistancePermyriad, _Configuration.RangeDistanceTolerance, faceDistanceEncoding, faceDistanceLength);
sorting = ISorting.Get(_Configuration.FaceDistancePermyriad, distanceTolerance, faceDistanceEncoding, faceDistanceLength);
if (sorting.DistancePermyriad == 0)
continue;
if (sorting.Id == faceDistanceEncoding.Id)

View File

@ -1,4 +1,4 @@
using Humanizer;
using Humanizer;
using ShellProgressBar;
using System.Collections.ObjectModel;
using System.Diagnostics;
@ -20,6 +20,12 @@ internal abstract class MapLogic
bool IsDefault,
string MappedFaceFile);
internal record MappedFile(long PersonKey,
string PersonKeyFormatted,
string PersonDisplayDirectoryName,
int? DirectoryNumber,
string File);
internal record Duplicate(long PersonKey,
int Id,
string File,
@ -227,10 +233,11 @@ internal abstract class MapLogic
}
}
private static List<(long, int?, string)> GetDisplayDirectoryAllFiles(string fileNameExtension, ReadOnlyCollection<PersonContainer> personContainers)
private static List<MappedFile> GetDisplayDirectoryAllFiles(string fileNameExtension, string personBirthdayFormat, ReadOnlyCollection<PersonContainer> personContainers)
{
List<(long, int?, string)> results = new();
List<MappedFile> results = new();
string fileName;
string personKeyFormatted;
List<string> distinct = new();
foreach (PersonContainer personContainer in personContainers)
{
@ -244,7 +251,8 @@ internal abstract class MapLogic
if (distinct.Contains(fileName))
continue;
distinct.Add(fileName);
results.Add(new(personContainer.Key.Value, null, personContainer.DisplayDirectoryAllFiles[i]));
personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personContainer.Key.Value);
results.Add(new(personContainer.Key.Value, personKeyFormatted, personContainer.DisplayDirectoryName, null, personContainer.DisplayDirectoryAllFiles[i]));
}
}
return results;
@ -280,11 +288,14 @@ internal abstract class MapLogic
{
List<TicksDirectory> results = new();
float? totalDays;
long? next = null;
string? checkDirectory;
string ticksDirectoryName;
DateTime directoryDateTime;
DirectoryInfo directoryInfo;
long? lastDirectoryTicks = null;
DateTime dateTime = DateTime.Now;
long month = dateTime.AddMonths(1).Ticks - dateTime.Ticks;
for (int i = 1; i < 5; i++)
_ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
if (!Directory.Exists(eDistanceContentDirectory))
@ -293,12 +304,20 @@ internal abstract class MapLogic
foreach (string ticksDirectory in ticksDirectories)
{
ticksDirectoryName = Path.GetFileName(ticksDirectory);
if (ticksDirectoryName.Length < 3 || ticksDirectoryName.First() != '(' || ticksDirectoryName[^1] != ')')
continue;
if (!long.TryParse(ticksDirectoryName[1..^1], out long directoryTicks))
if (!long.TryParse(ticksDirectoryName, out long directoryTicks))
throw new NotSupportedException();
if (next is null)
next = new DateTime(directoryTicks).Ticks;
else
{
if (!long.TryParse(ticksDirectoryName[1..^4], out directoryTicks))
throw new NotSupportedException();
next += month;
checkDirectory = Path.GetDirectoryName(ticksDirectory);
if (string.IsNullOrEmpty(checkDirectory))
{
if (!string.IsNullOrEmpty(checkDirectory))
Directory.Move(ticksDirectory, Path.Combine(checkDirectory, next.Value.ToString()));
continue;
}
}
directoryInfo = new(ticksDirectory);
directoryDateTime = new DateTime(directoryTicks);
@ -568,15 +587,15 @@ internal abstract class MapLogic
return result;
}
private static List<(long PersonKey, int? DirectoryNumber, string File)> GetCollection(Configuration configuration, ReadOnlyCollection<PersonContainer> personContainers, List<Record> records)
private static List<MappedFile> GetMappedFiles(Configuration configuration, ReadOnlyCollection<PersonContainer> personContainers, List<Record> records)
{
List<(long PersonKey, int? DirectoryNumber, string File)> results = new();
List<MappedFile> results = new();
string file;
long personKey;
string fileName;
List<string> distinct = new();
PersonBirthday? personBirthday;
results.AddRange(GetDisplayDirectoryAllFiles(configuration.FacesFileNameExtension, personContainers));
results.AddRange(GetDisplayDirectoryAllFiles(configuration.FacesFileNameExtension, configuration.PersonBirthdayFormat, personContainers));
foreach (Record record in records)
{
personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, record.PersonKeyFormatted);
@ -587,7 +606,7 @@ internal abstract class MapLogic
continue;
distinct.Add(fileName);
personKey = personBirthday.Value.Ticks;
results.Add(new(personKey, record.DirectoryNumber, record.MappedFaceFile));
results.Add(new(personKey, record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.DirectoryNumber, record.MappedFaceFile));
}
for (int i = results.Count - 1; i > -1; i--)
{
@ -602,24 +621,24 @@ internal abstract class MapLogic
if (!File.Exists(file))
continue;
File.Move(file, file[..^4]);
results[i] = new(results[i].PersonKey, results[i].DirectoryNumber, file[..^4]);
results[i] = new(results[i].PersonKey, results[i].PersonKeyFormatted, results[i].PersonDisplayDirectoryName, results[i].DirectoryNumber, file[..^4]);
}
return results;
}
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)
private static void ParallelFor(Configuration configuration, Dictionary<int, List<(string, int)>> skipCollection, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, MappedFile mappedFile)
{
string checkFile;
string[] fileMatches;
const string lnk = ".lnk";
int? id, wholePercentages;
const bool fromDistanceContent = true;
IReadOnlyList<MetadataExtractor.Directory> directories;
List<(string File, int WholePercentages)>? wholePercentagesCollection;
bool fromDistanceContent = !file.EndsWith(lnk) && file.Contains(eDistanceContentDirectory);
if (!file.EndsWith(lnk))
(id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, file);
if (!mappedFile.File.EndsWith(lnk))
(id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFile.File);
else
(id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, file[..^4]);
(id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFile.File[..^4]);
if (id is null || wholePercentages is null)
return;
if (skipCollection.TryGetValue(id.Value, out wholePercentagesCollection))
@ -636,13 +655,13 @@ internal abstract class MapLogic
continue;
}
}
if (file.EndsWith(lnk) || (!configuration.DistanceMoveUnableToMatch && !configuration.DistanceRenameToMatch) || !File.Exists(file))
if (mappedFile.File.EndsWith(lnk) || (!configuration.DistanceMoveUnableToMatch && !configuration.DistanceRenameToMatch) || !File.Exists(mappedFile.File))
directories = new List<MetadataExtractor.Directory>();
else
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file);
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mappedFile.File);
RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value);
lock (locationContainers)
locationContainers.Add(new(fromDistanceContent, directoryNumber, file, personKey, id.Value, wholePercentages.Value, directories, rectangle, null));
locationContainers.Add(new(fromDistanceContent, mappedFile.DirectoryNumber, mappedFile.File, mappedFile.PersonKey, mappedFile.PersonDisplayDirectoryName, id.Value, wholePercentages.Value, directories, rectangle, null));
}
private static void LookForPossibleDuplicates(Configuration configuration, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers)
@ -852,6 +871,7 @@ internal abstract class MapLogic
int? wholePercentages;
string? checkDirectory;
ProgressBar progressBar;
string? yearDirectoryName;
string[] yearDirectories;
string personKeyFormatted;
string? personFirstInitial;
@ -896,7 +916,7 @@ internal abstract class MapLogic
{
timeSpan = new TimeSpan(DateTime.Now.Ticks - ticksDirectory.DirectoryDateTime.Ticks);
if (timeSpan.TotalDays > 6)
throw new Exception($"{configuration.MappingDefaultName} are only allowed within x days!");
throw new Exception($"{configuration.MappingDefaultName} <{ticksDirectory.DirectoryDateTime}> are only allowed within x days!");
}
yearDirectories = Directory.GetDirectories(personKeyFormattedDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string yearDirectory in yearDirectories)
@ -907,6 +927,22 @@ internal abstract class MapLogic
personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
File.Delete(file);
yearDirectoryName = Path.GetFileName(yearDirectory);
if (!string.IsNullOrEmpty(yearDirectoryName) && yearDirectoryName.Length != 8)
{
checkDirectory = Path.Combine(personKeyFormattedDirectory, "abcdefgh");
if (Directory.Exists(checkDirectory))
{
MoveDirectory(personNameDirectories, checkDirectory);
if (!check)
check = true;
continue;
}
Directory.Move(yearDirectory, checkDirectory);
if (!check)
check = true;
continue;
}
foreach (string personNameDirectory in personNameDirectories)
{
directoryNumber++;
@ -916,7 +952,7 @@ internal abstract class MapLogic
{
if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length || !DateTime.TryParseExact(personKeyFormatted, configuration.PersonBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
continue;
checkDirectory = Path.Combine(yearDirectory, $"X]{dateTime.Ticks}");
checkDirectory = Path.Combine(yearDirectory, $"X+{dateTime.Ticks}");
if (Directory.Exists(checkDirectory))
{
Directory.Delete(yearDirectory, recursive: true);
@ -932,7 +968,7 @@ internal abstract class MapLogic
checkDirectory = Path.GetDirectoryName(ticksDirectory.Directory);
if (checkDirectory is null)
continue;
checkDirectory = Path.Combine(checkDirectory, $"({ticksDirectory.AlternateDirectoryDateTime.Ticks})");
checkDirectory = Path.Combine(checkDirectory, ticksDirectory.AlternateDirectoryDateTime.Ticks.ToString());
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
checkDirectory = Path.Combine(checkDirectory, personKeyFormatted);
@ -1034,6 +1070,33 @@ internal abstract class MapLogic
return results;
}
private static void MoveDirectory(string[] personNameDirectories, string destination)
{
string[] files;
string checkFile;
string checkDirectory;
string? personNameDirectoryName;
foreach (string personNameDirectory in personNameDirectories)
{
personNameDirectoryName = Path.GetFileName(personNameDirectory);
checkDirectory = Path.Combine(destination, personNameDirectoryName);
if (personNameDirectory == checkDirectory)
continue;
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
checkFile = Path.Combine(checkDirectory, Path.GetFileName(file));
if (checkFile == file)
continue;
if (File.Exists(checkFile))
continue;
File.Move(file, checkFile);
}
}
}
internal static void SetKeyValuePairsAndAddToCollections(Configuration configuration, ReadOnlyCollection<PersonContainer> personContainers, Dictionary<long, PersonContainer> personKeyToPersonContainer, ReadOnlyCollection<PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection, Dictionary<long, int> personKeyToCount, Dictionary<string, PersonContainer> personKeyFormattedToPersonContainer, Dictionary<long, List<PersonContainer>> personKeyToPersonContainerCollection, List<(PersonKeyFormattedIdThenWholePercentages, PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
{
PersonBirthday? personBirthday;
@ -1228,21 +1291,21 @@ internal abstract class MapLogic
}
}
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)
internal static List<LocationContainer<MetadataExtractor.Directory>> GetLocationContainers(Shared.Models.Methods.IDistance<MetadataExtractor.Directory> distance, int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, Dictionary<int, List<(string, int)>> skipCollection, List<Record> records)
{
List<LocationContainer<MetadataExtractor.Directory>> results = new();
List<(long PersonKey, int? DirectoryNumber, string File)> collection = GetCollection(configuration, personContainers, records);
if (collection.Count > 0 && (configuration.DistanceMoveUnableToMatch || configuration.DistanceRenameToMatch))
List<MappedFile> mappedFiles = GetMappedFiles(configuration, personContainers, records);
if (mappedFiles.Count > 0 && (configuration.DistanceMoveUnableToMatch || configuration.DistanceRenameToMatch))
{
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
string message = $") Building Mapped Face Files Collection - {totalSeconds} total second(s)";
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
using ProgressBar progressBar = new(collection.Count, message, options);
_ = Parallel.For(0, collection.Count, parallelOptions, (i, state) =>
using ProgressBar progressBar = new(mappedFiles.Count, message, options);
_ = Parallel.For(0, mappedFiles.Count, parallelOptions, (i, state) =>
{
progressBar.Tick();
ParallelFor(configuration, eDistanceContentDirectory, skipCollection, results, collection[i].PersonKey, collection[i].DirectoryNumber, collection[i].File);
ParallelFor(configuration, skipCollection, results, mappedFiles[i]);
});
}
ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers = new(results.OrderBy(l => l.DirectoryNumber).ToArray());
@ -1702,4 +1765,64 @@ internal abstract class MapLogic
}
}
private static ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> GetCollections(List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{
List<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> results = new();
List<LocationContainer<MetadataExtractor.Directory>>? collection;
Dictionary<long, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePairs = new();
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
{
if (!locationContainer.FromDistanceContent)
continue;
if (!keyValuePairs.TryGetValue(locationContainer.PersonKey, out collection))
{
keyValuePairs.Add(locationContainer.PersonKey, new());
if (!keyValuePairs.TryGetValue(locationContainer.PersonKey, out collection))
throw new Exception();
}
collection.Add(locationContainer);
}
foreach (KeyValuePair<long, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePair in keyValuePairs)
results.Add(new(keyValuePair.Value));
return new(results);
}
private static string? GetDisplayDirectoryName(ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, long personKey, string personKeyFormatted)
{
string? result;
PersonContainer? personContainer;
List<PersonContainer>? collection;
_ = readOnlyPersonKeyToPersonContainerCollection.TryGetValue(personKey, out collection);
if (collection is not null)
result = collection[0].DisplayDirectoryName;
else
{
if (!readOnlyPersonKeyFormattedToPersonContainer.TryGetValue(personKeyFormatted, out personContainer))
result = null;
else
result = personContainer.DisplayDirectoryName;
}
return result;
}
internal static void SaveMappedRelations(Configuration configuration, Shared.Models.Methods.IDistance<MetadataExtractor.Directory> distance, string a2PeopleContentDirectory, string eDistanceContentDirectory, long ticks, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection)
{
string personKeyFormatted;
string? displayDirectoryName;
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
string message = $") Save Mapped Relations - {totalSeconds} total second(s)";
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> collections = GetCollections(locationContainers);
using ProgressBar progressBar = new(collections.Count, message, options);
foreach (ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> collection in collections)
{
progressBar.Tick();
if (collection.Count == 0)
continue;
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, collection[0].PersonKey);
displayDirectoryName = GetDisplayDirectoryName(readOnlyPersonKeyToPersonContainerCollection, readOnlyPersonKeyFormattedToPersonContainer, collection[0].PersonKey, personKeyFormatted);
distance.SaveMappedForOutputResolutions(a2PeopleContentDirectory, eDistanceContentDirectory, configuration.RangeDistanceTolerance, collection, personKeyFormatted, displayDirectoryName);
}
}
}