SaveMappedForOutputResolutions
This commit is contained in:
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user