Reuse count over t

FilePath over String
Support first run better
Bump
This commit is contained in:
Mike Phares 2024-07-20 10:48:26 -07:00
parent 5b9e748ba4
commit 9ebfdc8af2
10 changed files with 216 additions and 147 deletions

View File

@ -180,7 +180,8 @@ public class CopyDistinct
progressBar = new(count, message, options); progressBar = new(count, message, options);
string key = string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey) ? _PropertyConfiguration.ResultAllInOne : _AppSettings.ResultDirectoryKey; string key = string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey) ? _PropertyConfiguration.ResultAllInOne : _AppSettings.ResultDirectoryKey;
string[] directories = _FileGroups[key]; string[] directories = _FileGroups[key];
(distinctDirectories, toDoCollection) = IDirectory.GetToDoCollection(_PropertyConfiguration, _AppSettings.CopyDuplicates, _AppSettings.IfCanUseId, filesCollection, directories, () => progressBar.Tick()); ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollection);
(distinctDirectories, toDoCollection) = IDirectory.GetToDoCollection(_PropertyConfiguration, _AppSettings.CopyDuplicates, _AppSettings.IfCanUseId, filePathsCollection, directories, () => progressBar.Tick());
progressBar.Dispose(); progressBar.Dispose();
} }
foreach (string distinctDirectory in distinctDirectories) foreach (string distinctDirectory in distinctDirectories)

View File

@ -252,26 +252,26 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
throw new Exception("Configuration has SaveSortingWithoutPerson and FocusDirectory!"); throw new Exception("Configuration has SaveSortingWithoutPerson and FocusDirectory!");
} }
private ReadOnlyCollection<int> GetNotNineCollection(ReadOnlyCollection<string[]> filesCollection) private ReadOnlyCollection<int> GetNotNineCollection(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
List<int> results = []; List<int> results = [];
FileInfo fileInfo; FileInfo fileInfo;
FilePath filePath;
FileHolder fileHolder; FileHolder fileHolder;
foreach (string[] files in filesCollection) FilePath checkFilePath;
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
foreach (string file in files) foreach (FilePath filePath in filePaths)
{ {
if (!file.Contains(" !9")) if (!filePath.FullName.Contains(" !9"))
continue; continue;
fileInfo = new(file); fileInfo = new(filePath.FullName);
fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(fileInfo); fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(fileInfo);
if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden)) if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden))
File.SetAttributes(fileHolder.FullName, FileAttributes.Hidden); File.SetAttributes(fileHolder.FullName, FileAttributes.Hidden);
filePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: null); checkFilePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: null);
if (filePath.Id is null) if (checkFilePath.Id is null)
continue; continue;
results.Add(filePath.Id.Value); results.Add(checkFilePath.Id.Value);
} }
} }
return new(results); return new(results);
@ -320,10 +320,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
private void Search(long ticks, ReadOnlyCollection<PersonContainer> personContainers, string argZero, string propertyRoot) private void Search(long ticks, ReadOnlyCollection<PersonContainer> personContainers, string argZero, string propertyRoot)
{ {
int t;
string message; string message;
MapLogic? mapLogic; MapLogic? mapLogic;
Container[] containers;
A_Property propertyLogic; A_Property propertyLogic;
string eDistanceContentDirectory; string eDistanceContentDirectory;
string? a2PeopleContentDirectory; string? a2PeopleContentDirectory;
@ -337,11 +335,12 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
const string directorySearchFilter = "*"; const string directorySearchFilter = "*";
string? filesCollectionRootDirectory = null; string? filesCollectionRootDirectory = null;
bool configurationOutputResolutionsHas = false; bool configurationOutputResolutionsHas = false;
ReadOnlyCollection<Container> readOnlyContainers;
ReadOnlyCollection<int>? notNineCollection = null; ReadOnlyCollection<int>? notNineCollection = null;
ReadOnlyDictionary<long, List<int>> personKeyToIds; ReadOnlyDictionary<long, List<int>> personKeyToIds;
ReadOnlyCollection<string[]>? filesCollection = null; ReadOnlyCollection<ReadOnlyCollection<FilePath>>? filePathsCollection = null;
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(_Configuration, ticks);
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); (aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(_Configuration.PropertyConfiguration, ticks);
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory, ticks); Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory, ticks);
a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])"); a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])");
@ -359,8 +358,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
configurationOutputResolutionsHas = true; configurationOutputResolutionsHas = true;
if (!runToDoCollectionFirst) if (!runToDoCollectionFirst)
break; break;
(filesCollectionRootDirectory, filesCollection, filesCollectionCountIsOne) = GetFilesCollectionThenCopyOrMove(ticks, fileSearchFilter, directorySearchFilter, options, outputResolution); (filesCollectionRootDirectory, filePathsCollection, filesCollectionCountIsOne) = GetFilesCollectionThenCopyOrMove(ticks, fileSearchFilter, directorySearchFilter, options, outputResolution);
notNineCollection = GetNotNineCollection(filesCollection); notNineCollection = GetNotNineCollection(filePathsCollection);
break; break;
} }
fPhotoPrismContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), _Configuration.PropertyConfiguration.ResultContent); fPhotoPrismContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), _Configuration.PropertyConfiguration.ResultContent);
@ -368,8 +367,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory); propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory);
if (filesCollectionCountIsOne) if (filesCollectionCountIsOne)
{ {
if (filesCollection is null) if (filePathsCollection is null)
throw new NullReferenceException(nameof(filesCollection)); throw new NullReferenceException(nameof(filePathsCollection));
string resultsGroupDirectory; string resultsGroupDirectory;
a2PeopleContentDirectory = null; a2PeopleContentDirectory = null;
eDistanceContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", _Configuration.PropertyConfiguration.ResultContent); eDistanceContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", _Configuration.PropertyConfiguration.ResultContent);
@ -380,7 +379,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
resultsGroupDirectory = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true); resultsGroupDirectory = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true);
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(resultsGroupDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(resultsGroupDirectory);
} }
argZero = SaveUrlAndGetNewRootDirectory(filesCollection.First()); argZero = SaveUrlAndGetNewRootDirectory(filePathsCollection.First());
_Configuration.PropertyConfiguration.ChangeRootDirectory(argZero); _Configuration.PropertyConfiguration.ChangeRootDirectory(argZero);
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); (aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false); propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false);
@ -388,34 +387,32 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
if (configurationOutputResolutionsHas) if (configurationOutputResolutionsHas)
{ {
int count;
foreach (string outputResolution in _Configuration.OutputResolutions) foreach (string outputResolution in _Configuration.OutputResolutions)
{ {
if (outputResolution.Any(char.IsNumber)) if (outputResolution.Any(char.IsNumber))
continue; continue;
(cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution); (cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution);
filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent); filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
filesCollection = IDirectory.GetFilesCollection(filesCollectionRootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage: true); filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollectionRootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage: true);
count = filesCollection.Select(l => l.Length).Sum();
break; break;
} }
} }
if (filesCollectionRootDirectory is null || filesCollection is null) if (filesCollectionRootDirectory is null || filePathsCollection is null)
throw new NullReferenceException(nameof(filesCollection)); throw new NullReferenceException(nameof(filePathsCollection));
message = $") Building Container(s) - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton); string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton);
if (!Directory.Exists(aPropertySingletonDirectory)) if (!Directory.Exists(aPropertySingletonDirectory))
_ = Directory.CreateDirectory(aPropertySingletonDirectory); _ = Directory.CreateDirectory(aPropertySingletonDirectory);
_ProgressBar = new(short.MaxValue, message, options); int count = filePathsCollection.Select(l => l.Count).Sum();
(t, containers) = Shared.Models.Stateless.Methods.IContainer.GetContainers(this, _Configuration.PropertyConfiguration, aPropertySingletonDirectory, filesCollectionRootDirectory, filesCollection); SaveDistinctIds(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, filePathsCollection);
message = $") Building Container(s) - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
_ProgressBar = new(count, message, options);
readOnlyContainers = Shared.Models.Stateless.Methods.IContainer.GetContainers(this, _Configuration.PropertyConfiguration, aPropertySingletonDirectory, filesCollectionRootDirectory, filePathsCollection);
_ProgressBar.Dispose(); _ProgressBar.Dispose();
ReadOnlyCollection<Container> readOnlyContainers = new(containers);
SaveDistinctIds(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, readOnlyContainers);
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleContentDirectory, a2PeopleSingletonDirectory, eDistanceContentDirectory); mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleContentDirectory, a2PeopleSingletonDirectory, eDistanceContentDirectory);
DeleteContinueFiles(personContainers); DeleteContinueFiles(personContainers);
if (!runToDoCollectionFirst) if (!runToDoCollectionFirst)
MapFaceFileLogic(ticks, personContainers, mapLogic, a2PeopleContentDirectory, eDistanceContentDirectory, options); MapFaceFileLogic(ticks, personContainers, mapLogic, a2PeopleContentDirectory, eDistanceContentDirectory, options);
FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, fPhotoPrismSingletonDirectory, t, readOnlyContainers, propertyLogic, mapLogic); FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, fPhotoPrismSingletonDirectory, count, readOnlyContainers, propertyLogic, mapLogic);
ReadOnlyCollection<Item> distinctValidImageItems = Shared.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true); ReadOnlyCollection<Item> distinctValidImageItems = Shared.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true);
if (_Configuration.LookForAbandoned) if (_Configuration.LookForAbandoned)
{ {
@ -475,9 +472,11 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
} }
private bool GetRunToDoCollectionFirst(Property.Models.Configuration propertyConfiguration, long ticks) private bool GetRunToDoCollectionFirst(Models.Configuration configuration, long ticks)
{ {
bool result = !IId.IsOffsetDeterministicHashCode(propertyConfiguration); bool result = configuration.SaveSortingWithoutPerson;
if (!result)
result = !IId.IsOffsetDeterministicHashCode(configuration.PropertyConfiguration);
if (!result) if (!result)
{ {
string[] directories; string[] directories;
@ -530,12 +529,12 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
return result; return result;
} }
private string SaveUrlAndGetNewRootDirectory(string[] files) private string SaveUrlAndGetNewRootDirectory(ReadOnlyCollection<FilePath> filePaths)
{ {
string result; string result;
if (files.Length == 0) if (filePaths.Count == 0)
throw new NotSupportedException(); throw new NotSupportedException();
string? sourceDirectory = Path.GetDirectoryName(files.First()); string? sourceDirectory = filePaths[0].DirectoryName;
if (string.IsNullOrEmpty(sourceDirectory)) if (string.IsNullOrEmpty(sourceDirectory))
throw new NotSupportedException(); throw new NotSupportedException();
Uri uri; Uri uri;
@ -576,7 +575,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
return result; return result;
} }
private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string fPhotoPrismSingletonDirectory, int t, ReadOnlyCollection<Container> readOnlyContainers, A_Property propertyLogic, MapLogic mapLogic) private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string fPhotoPrismSingletonDirectory, int count, ReadOnlyCollection<Container> readOnlyContainers, A_Property propertyLogic, MapLogic mapLogic)
{ {
int total; int total;
int notMapped; int notMapped;
@ -620,7 +619,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
sourceDirectoryChanges.Clear(); sourceDirectoryChanges.Clear();
anyNullOrNoIsUniqueFileName = filteredItems.Any(l => !l.IsUniqueFileName); anyNullOrNoIsUniqueFileName = filteredItems.Any(l => !l.IsUniqueFileName);
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
message = $"{i + 1:000} [{filteredItems.Count:000}] / {containersLength:000} - {total} / {t} total - {totalSeconds} total second(s) - {outputResolution} - <{container.SourceDirectory}> - total not mapped {totalNotMapped:000000}"; message = $"{i + 1:000} [{filteredItems.Count:000}] / {containersLength:000} - {total} / {count} total - {totalSeconds} total second(s) - {outputResolution} - <{container.SourceDirectory}> - total not mapped {totalNotMapped:000000}";
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, container.SourceDirectory, anyNullOrNoIsUniqueFileName); propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, container.SourceDirectory, anyNullOrNoIsUniqueFileName);
if (outputResolutionHasNumber) if (outputResolutionHasNumber)
_Resize.SetAngleBracketCollection(cResultsFullGroupDirectory, container.SourceDirectory); _Resize.SetAngleBracketCollection(cResultsFullGroupDirectory, container.SourceDirectory);
@ -657,14 +656,14 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
total += container.Items.Count; total += container.Items.Count;
} }
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
message = $"### [###] / {containersLength:000} - {total} / {t} total - {totalSeconds} total second(s) - {outputResolution} - <> - total not mapped {totalNotMapped:000000}"; message = $"### [###] / {containersLength:000} - {total} / {count} total - {totalSeconds} total second(s) - {outputResolution} - <> - total not mapped {totalNotMapped:000000}";
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
using ProgressBar progressBar = new(1, message, options); using ProgressBar progressBar = new(1, message, options);
progressBar.Tick(); progressBar.Tick();
} }
} }
private static void SaveDistinctIds(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<Container> readOnlyContainers) private static void SaveDistinctIds(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
string paddedId; string paddedId;
List<int> distinct = []; List<int> distinct = [];
@ -672,21 +671,19 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
string bMetadataCollectionDirectory = Path.Combine(bResultsFullGroupDirectory, propertyConfiguration.ResultCollection); string bMetadataCollectionDirectory = Path.Combine(bResultsFullGroupDirectory, propertyConfiguration.ResultCollection);
if (!Directory.Exists(bMetadataCollectionDirectory)) if (!Directory.Exists(bMetadataCollectionDirectory))
_ = Directory.CreateDirectory(bMetadataCollectionDirectory); _ = Directory.CreateDirectory(bMetadataCollectionDirectory);
foreach (Container container in readOnlyContainers) foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
if (container.Items.Count == 0) if (filePaths.Count == 0)
continue; continue;
foreach (Item item in container.Items) foreach (FilePath filePath in filePaths)
{ {
if (item.Property?.Id is null) if (filePath.Id is null)
continue; continue;
if (item.Property.Id != item.FilePath.Id) if (distinct.Contains(filePath.Id.Value))
throw new NotSupportedException();
if (distinct.Contains(item.Property.Id.Value))
continue; continue;
distinct.Add(item.Property.Id.Value); distinct.Add(filePath.Id.Value);
paddedId = IId.GetPaddedId(propertyConfiguration, item.Property.Id.Value, item.FilePath.HasIgnoreKeyword, item.FilePath.HasDateTimeOriginal, index: null); paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal, index: null);
identifiers.Add(new(item.Property.Id.Value, paddedId)); identifiers.Add(new(filePath.Id.Value, paddedId));
} }
} }
string json = JsonSerializer.Serialize(identifiers.OrderBy(l => l.PaddedId).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray); string json = JsonSerializer.Serialize(identifiers.OrderBy(l => l.PaddedId).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
@ -1158,6 +1155,23 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
_ = _BlurHasher.EncodeAndSave(item.FilePath, resizedFileHolder); _ = _BlurHasher.EncodeAndSave(item.FilePath, resizedFileHolder);
} }
} }
bool? shouldIgnore = property is null || property.Keywords is null ? null : _Configuration.PropertyConfiguration.IgnoreRulesKeyWords.Any(l => property.Keywords.Contains(l));
if (shouldIgnore is not null)
{
if (shouldIgnore.Value)
{
FileInfo fileInfo = new(resizedFileHolder.FullName);
if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden))
File.SetAttributes(resizedFileHolder.FullName, FileAttributes.Hidden);
}
if (resizedFileHolder.Exists && item.FilePath.HasIgnoreKeyword is not null && item.FilePath.HasIgnoreKeyword.Value != shouldIgnore.Value)
{
if (item.FilePath.DirectoryName.Contains("Results") && item.FilePath.DirectoryName.Contains("Resize"))
File.Delete(resizedFileHolder.FullName);
else
throw new NotSupportedException($"Rename File! <{item.FilePath.FileNameFirstSegment}>");
}
}
if (property is null || item.Property is null) if (property is null || item.Property is null)
throw new NullReferenceException(nameof(property)); throw new NullReferenceException(nameof(property));
item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder); item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder);
@ -1187,7 +1201,12 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
Dictionary<string, int[]> outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem); Dictionary<string, int[]> outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem);
if (_Configuration.SaveResizedSubfiles) if (_Configuration.SaveResizedSubfiles)
_Resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize); {
if (shouldIgnore is not null && item.FilePath.HasIgnoreKeyword is not null && item.FilePath.HasIgnoreKeyword.Value != shouldIgnore.Value)
faces = [];
else
_Resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize);
}
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution))
faces = []; faces = [];
else if (!mappingFromItem.ResizedFileHolder.Exists && !File.Exists(mappingFromItem.ResizedFileHolder.FullName)) else if (!mappingFromItem.ResizedFileHolder.Exists && !File.Exists(mappingFromItem.ResizedFileHolder.FullName))
@ -1400,41 +1419,41 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
} }
private static void CheckForAllWindowsLinks(ReadOnlyCollection<string[]> filesCollection) private static void CheckForAllWindowsLinks(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
string fileFullPath; string fileFullPath;
WindowsShortcut windowsShortcut; WindowsShortcut windowsShortcut;
foreach (string[] files in filesCollection) foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
if (files.Length == 0) if (filePaths.Count == 0)
continue; continue;
if (files.All(l => l.EndsWith(".lnk"))) if (filePaths.All(l => l.ExtensionLowered == ".lnk"))
{ {
foreach (string file in files) foreach (FilePath filePath in filePaths)
{ {
windowsShortcut = WindowsShortcut.Load(file); windowsShortcut = WindowsShortcut.Load(filePath.FullName);
if (windowsShortcut.Path is null) if (windowsShortcut.Path is null)
{ {
File.Delete(file); File.Delete(filePath.FullName);
continue; continue;
} }
fileFullPath = windowsShortcut.Path; fileFullPath = windowsShortcut.Path;
windowsShortcut.Dispose(); windowsShortcut.Dispose();
File.WriteAllText(Path.ChangeExtension(file, ".url"), fileFullPath); File.WriteAllText(Path.ChangeExtension(filePath.FullName, ".url"), fileFullPath);
File.Delete(file); File.Delete(filePath.FullName);
} }
throw new NotSupportedException("All are Windows *.lnk files!"); throw new NotSupportedException("All are Windows *.lnk files!");
} }
} }
} }
private static bool IsFilesCollectionCountIsOne(ReadOnlyCollection<string[]> filesCollection) private static bool IsFilesCollectionCountIsOne(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
bool result = true; bool result = true;
int count = 0; int count = 0;
foreach (string[] files in filesCollection) foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
if (files.Length == 0) if (filePaths.Count == 0)
continue; continue;
count += 1; count += 1;
if (count > 1) if (count > 1)
@ -1444,22 +1463,22 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
} }
if (result) if (result)
CheckForAllWindowsLinks(filesCollection); CheckForAllWindowsLinks(filePathsCollection);
return result; return result;
} }
private (string, ReadOnlyCollection<string[]>, bool) GetFilesCollectionThenCopyOrMove(long ticks, string fileSearchFilter, string directorySearchFilter, ProgressBarOptions options, string outputResolution) private (string, ReadOnlyCollection<ReadOnlyCollection<FilePath>>, bool) GetFilesCollectionThenCopyOrMove(long ticks, string fileSearchFilter, string directorySearchFilter, ProgressBarOptions options, string outputResolution)
{ {
ProgressBar progressBar; ProgressBar progressBar;
string filesCollectionRootDirectory = _Configuration.PropertyConfiguration.RootDirectory; string filesCollectionRootDirectory = _Configuration.PropertyConfiguration.RootDirectory;
(string cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution); (string cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution);
IReadOnlyDictionary<string, string[]> fileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, [_Configuration.PropertyConfiguration.ResultContent]); IReadOnlyDictionary<string, string[]> fileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, [_Configuration.PropertyConfiguration.ResultContent]);
ReadOnlyCollection<string[]> filesCollection = IDirectory.GetFilesCollection(filesCollectionRootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage: false); ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollectionRootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage: false);
int count = filesCollection.Select(l => l.Length).Sum(); int count = filePathsCollection.Select(l => l.Count).Sum();
bool filesCollectionCountIsOne = IsFilesCollectionCountIsOne(filesCollection); bool filesCollectionCountIsOne = IsFilesCollectionCountIsOne(filePathsCollection);
string message = $") Selecting for ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)"; string message = $") Selecting for ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
progressBar = new(count, message, options); progressBar = new(count, message, options);
(string[] distinctDirectories, List<(FilePath, string)> toDoCollection) = IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, filesCollection, fileGroups[_Configuration.PropertyConfiguration.ResultContent], () => progressBar.Tick()); (string[] distinctDirectories, List<(FilePath, string)> toDoCollection) = IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, filePathsCollection, fileGroups[_Configuration.PropertyConfiguration.ResultContent], () => progressBar.Tick());
progressBar.Dispose(); progressBar.Dispose();
foreach (string distinctDirectory in distinctDirectories) foreach (string distinctDirectory in distinctDirectories)
{ {
@ -1470,7 +1489,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
progressBar = new(count, message, options); progressBar = new(count, message, options);
_ = IDirectory.CopyOrMove(toDoCollection, move: false, moveBack: false, () => progressBar.Tick()); _ = IDirectory.CopyOrMove(toDoCollection, move: false, moveBack: false, () => progressBar.Tick());
progressBar.Dispose(); progressBar.Dispose();
return (filesCollectionRootDirectory, new(filesCollection), filesCollectionCountIsOne); return (filesCollectionRootDirectory, filePathsCollection, filesCollectionCountIsOne);
} }
} }

View File

@ -829,18 +829,19 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
private string? GetDisplayDirectoryName(string? displayDirectoryName, LocationContainer locationContainer, ReadOnlyDictionary<long, PersonContainer> personKeyToPersonContainer) private string? GetDisplayDirectoryName(string? displayDirectoryName, LocationContainer locationContainer, ReadOnlyDictionary<long, PersonContainer> personKeyToPersonContainer)
{ {
string? result = displayDirectoryName; string? result = displayDirectoryName;
if (personKeyToPersonContainer.Count == 0) if (personKeyToPersonContainer.Count != 0)
throw new NotImplementedException(nameof(GetPersonKeyToPersonContainer));
ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers = GetWholePercentagesToPersonContainers(locationContainer.Id);
if (wholePercentagesToPersonContainers is not null)
{ {
foreach (KeyValuePair<int, ReadOnlyCollection<PersonContainer>> keyValuePair in wholePercentagesToPersonContainers) ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers = GetWholePercentagesToPersonContainers(locationContainer.Id);
if (wholePercentagesToPersonContainers is not null)
{ {
if (keyValuePair.Key != locationContainer.WholePercentages) foreach (KeyValuePair<int, ReadOnlyCollection<PersonContainer>> keyValuePair in wholePercentagesToPersonContainers)
continue; {
if (keyValuePair.Value.Count != 1) if (keyValuePair.Key != locationContainer.WholePercentages)
continue; continue;
result = keyValuePair.Value[0].DisplayDirectoryName; if (keyValuePair.Value.Count != 1)
continue;
result = keyValuePair.Value[0].DisplayDirectoryName;
}
} }
} }
return result; return result;

View File

@ -325,7 +325,7 @@ internal abstract class MapLogic
continue; continue;
} }
if (!personKeyFormattedToPersonContainer.TryGetValue(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, out personContainer)) if (!personKeyFormattedToPersonContainer.TryGetValue(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, out personContainer))
throw new Exception(); continue;
if (!results.TryGetValue(personKeyFormattedIdThenWholePercentages.Id, out idTo)) if (!results.TryGetValue(personKeyFormattedIdThenWholePercentages.Id, out idTo))
{ {
results.Add(personKeyFormattedIdThenWholePercentages.Id, []); results.Add(personKeyFormattedIdThenWholePercentages.Id, []);
@ -735,7 +735,7 @@ internal abstract class MapLogic
personDisplayDirectoryName = personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName; personDisplayDirectoryName = personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName;
matches = configuration.PersonCharacters.Where(l => personDisplayDirectoryName.Contains(l)).ToArray(); matches = configuration.PersonCharacters.Where(l => personDisplayDirectoryName.Contains(l)).ToArray();
if (matches.Length == 0) if (matches.Length == 0)
throw new NotSupportedException(); continue;
group = IPerson.GetHourGroup(personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName, personBirthday.Value.Hour); group = IPerson.GetHourGroup(personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName, personBirthday.Value.Hour);
(status, sex, first) = IPerson.GetPersonHour(personKeyFormattedIdThenWholePercentages.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);

View File

@ -29,22 +29,21 @@ internal abstract class Container
return container.Items.Count == results.Count ? container.Items : new(results); return container.Items.Count == results.Count ? container.Items : new(results);
} }
internal static List<Models.FilePair> GetFilePairs(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, ReadOnlyCollection<string[]> filesCollection) private static List<Models.FilePair> GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
int renamed; int renamed;
const bool useCeilingAverage = true; const bool useCeilingAverage = true;
List<Models.FilePair>? filePairs = null; List<Models.FilePair>? filePairs = null;
ReadOnlyCollection<string[]>? jsonFilesCollection = null; ReadOnlyCollection<string[]>? jsonFilesCollection = null;
IReadOnlyDictionary<string, List<string>>? compareFileNamesToFiles = null; IReadOnlyDictionary<string, List<string>>? compareFileNamesToFiles = null;
IReadOnlyDictionary<string, List<string>> fileNamesToFiles = XDirectory.GetFilesKeyValuePairs(filesCollection); IReadOnlyDictionary<string, List<string>> fileNamesToFiles = XDirectory.GetFilesKeyValuePairs(filePathsCollection);
for (int i = 0; i < short.MaxValue; i++) for (int i = 0; i < short.MaxValue; i++)
{ {
renamed = 0; renamed = 0;
dlibDotNet?.Tick();
jsonFilesCollection = IDirectory.GetFilesCollection(aPropertySingletonDirectory, directorySearchFilter, extension, useCeilingAverage); jsonFilesCollection = IDirectory.GetFilesCollection(aPropertySingletonDirectory, directorySearchFilter, extension, useCeilingAverage);
compareFileNamesToFiles = XDirectory.GetFilesKeyValuePairs(jsonFilesCollection); compareFileNamesToFiles = XDirectory.GetFilesKeyValuePairs(jsonFilesCollection);
renamed += XDirectory.LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension); renamed += XDirectory.LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension);
filePairs = XDirectory.GetFiles(propertyConfiguration, filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles); filePairs = XDirectory.GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, extension, compareFileNamesToFiles);
renamed += XDirectory.MaybeMove(propertyConfiguration, filePairs, aPropertySingletonDirectory, extension); renamed += XDirectory.MaybeMove(propertyConfiguration, filePairs, aPropertySingletonDirectory, extension);
if (renamed == 0) if (renamed == 0)
break; break;
@ -72,8 +71,9 @@ internal abstract class Container
return result; return result;
} }
private static void ParallelFor(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string extension, int rootDirectoryLength, Models.FilePair filePair, List<FilePair> results) private static void ParallelFor(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string extension, int rootDirectoryLength, Models.FilePair filePair, List<FilePair> results)
{ {
dlibDotNet?.Tick();
bool abandoned = false; bool abandoned = false;
Models.FileHolder sourceDirectoryFileHolder; Models.FileHolder sourceDirectoryFileHolder;
Models.Property? property = GetProperty(filePair); Models.Property? property = GetProperty(filePair);
@ -81,16 +81,16 @@ internal abstract class Container
FilePath filePath = FilePath.Get(propertyConfiguration, imageFileHolder, index: null); FilePath filePath = FilePath.Get(propertyConfiguration, imageFileHolder, index: null);
bool? fileSizeChanged = property is not null ? property.FileSize != filePath.Length : null; bool? fileSizeChanged = property is not null ? property.FileSize != filePath.Length : null;
bool isValidImageFormatExtension = propertyConfiguration.ValidImageFormatExtensions.Contains(filePath.ExtensionLowered); bool isValidImageFormatExtension = propertyConfiguration.ValidImageFormatExtensions.Contains(filePath.ExtensionLowered);
if (property is not null && property.Keywords is not null) bool? shouldIgnore = property is null || property.Keywords is null ? null : propertyConfiguration.IgnoreRulesKeyWords.Any(l => property.Keywords.Contains(l));
if (shouldIgnore is not null)
{ {
bool shouldIgnore = propertyConfiguration.IgnoreRulesKeyWords.Any(l => property.Keywords.Contains(l)); if (shouldIgnore.Value)
if (shouldIgnore)
{ {
FileInfo fileInfo = new(filePath.FullName); FileInfo fileInfo = new(filePath.FullName);
if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden)) if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden))
File.SetAttributes(imageFileHolder.FullName, FileAttributes.Hidden); File.SetAttributes(imageFileHolder.FullName, FileAttributes.Hidden);
} }
if (filePath.HasIgnoreKeyword is not null && filePath.HasIgnoreKeyword.Value != shouldIgnore) if (filePath.HasIgnoreKeyword is not null && filePath.HasIgnoreKeyword.Value != shouldIgnore.Value)
{ {
if (filePath.DirectoryName.Contains("Results") && filePath.DirectoryName.Contains("Resize")) if (filePath.DirectoryName.Contains("Results") && filePath.DirectoryName.Contains("Resize"))
File.Delete(filePath.FullName); File.Delete(filePath.FullName);
@ -120,31 +120,31 @@ internal abstract class Container
results.Add(new(filePair.IsUnique, filePair.Collection, filePath, item)); results.Add(new(filePair.IsUnique, filePair.Collection, filePath, item));
} }
private static List<FilePair> GetFilePairs(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection, string directorySearchFilter) private static List<FilePair> GetFilePairs(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
{ {
List<FilePair> results = []; List<FilePair> results = [];
const string extension = ".json"; const string extension = ".json";
int maxDegreeOfParallelism = Environment.ProcessorCount; int maxDegreeOfParallelism = Environment.ProcessorCount;
int filesCollectionDirectoryLength = filesCollectionDirectory.Length; int filesCollectionDirectoryLength = filesCollectionDirectory.Length;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
List<Models.FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filesCollection); List<Models.FilePair> filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filePathsCollection);
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(propertyConfiguration, aPropertySingletonDirectory, extension, filesCollectionDirectoryLength, filePairs[i], results)); _ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, extension, filesCollectionDirectoryLength, filePairs[i], results));
return results; return results;
} }
private static (int, Models.Container[]) GetContainers(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection, string directorySearchFilter) private static (int, Models.Container[]) GetContainers(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
{ {
List<Models.Container> results = []; List<Models.Container> results = [];
string? directory; string directory;
List<Models.Item>? items; List<Models.Item>? items;
Models.Container container; Models.Container container;
List<string> directories = []; List<string> directories = [];
Dictionary<string, List<Models.Item>> directoryToItems = []; Dictionary<string, List<Models.Item>> directoryToItems = [];
foreach (string[] files in filesCollection) foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
if (files.Length == 0) if (filePaths.Count == 0)
continue; continue;
directory = Path.GetDirectoryName(files.First()); directory = filePaths[0].DirectoryName;
if (directory is null) if (directory is null)
continue; continue;
if (!directories.Contains(directory)) if (!directories.Contains(directory))
@ -156,7 +156,7 @@ internal abstract class Container
throw new Exception(); throw new Exception();
} }
} }
List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection, directorySearchFilter); List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filePathsCollection, directorySearchFilter);
foreach (FilePair filePair in filePairs) foreach (FilePair filePair in filePairs)
{ {
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryName, out items)) if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryName, out items))
@ -177,13 +177,12 @@ internal abstract class Container
return (filePairs.Count, results.ToArray()); return (filePairs.Count, results.ToArray());
} }
internal static (int, Models.Container[]) GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) internal static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
int count;
Models.Container[] results; Models.Container[] results;
const string directorySearchFilter = "*"; const string directorySearchFilter = "*";
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection, directorySearchFilter); (_, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filePathsCollection, directorySearchFilter);
return (count, results); return new(results);
} }
internal static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) internal static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory)
@ -195,7 +194,8 @@ internal abstract class Container
const string fileSearchFilter = "*"; const string fileSearchFilter = "*";
const string directorySearchFilter = "*"; const string directorySearchFilter = "*";
ReadOnlyCollection<string[]> filesCollection = IDirectory.GetFilesCollection(propertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage); ReadOnlyCollection<string[]> filesCollection = IDirectory.GetFilesCollection(propertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, propertyConfiguration.RootDirectory, filesCollection, directorySearchFilter); ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, propertyConfiguration.RootDirectory, filePathsCollection, directorySearchFilter);
return (count, results); return (count, results);
} }

View File

@ -20,10 +20,10 @@ public interface IContainer
static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) => static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory); Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory);
(int, Models.Container[]) TestStatic_GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) => ReadOnlyCollection<Models.Container> TestStatic_GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection); GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filePathsCollection);
static (int, Models.Container[]) GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) => static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
Container.GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection); Container.GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filePathsCollection);
List<int> TestStatic_GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) => List<int> TestStatic_GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers); GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);

View File

@ -20,24 +20,34 @@ public interface IDirectory
static ReadOnlyCollection<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) => static ReadOnlyCollection<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) =>
XDirectory.GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage); XDirectory.GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
ReadOnlyCollection<ReadOnlyCollection<FilePath>> TestStatic_GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) =>
GetFilePathCollections(propertyConfiguration, directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) =>
XDirectory.GetFilePathCollections(propertyConfiguration, directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
void TestStatic_MoveFiles(List<string> files, string find, string replace) => void TestStatic_MoveFiles(List<string> files, string find, string replace) =>
MoveFiles(files, find, replace); MoveFiles(files, find, replace);
static void MoveFiles(List<string> files, string find, string replace) => static void MoveFiles(List<string> files, string find, string replace) =>
XDirectory.MoveFiles(files, find, replace); XDirectory.MoveFiles(files, find, replace);
(string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection, string[] directories, Action? tick) => (string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string[] directories, Action? tick) =>
GetToDoCollection(propertyConfiguration, filesCollection, directories, tick); GetToDoCollection(propertyConfiguration, filePathsCollection, directories, tick);
static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection, string[] directories, Action? tick) => static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string[] directories, Action? tick) =>
XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates: false, ifCanUseId: true, filesCollection, directories, tick); XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates: false, ifCanUseId: true, filePathsCollection, directories, tick);
(string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<string[]> filesCollection, string[] directories, Action? tick) => (string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string[] directories, Action? tick) =>
GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filesCollection, directories, tick); GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, directories, tick);
static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<string[]> filesCollection, string[] directories, Action? tick) => static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string[] directories, Action? tick) =>
XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filesCollection, directories, tick); XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, directories, tick);
List<string> TestStatic_CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) => List<string> TestStatic_CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) =>
CopyOrMove(toDoCollection, move, moveBack, tick); CopyOrMove(toDoCollection, move, moveBack, tick);
static List<string> CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) => static List<string> CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) =>
XDirectory.CopyOrMove(toDoCollection, move, moveBack, tick); XDirectory.CopyOrMove(toDoCollection, move, moveBack, tick);
ReadOnlyCollection<ReadOnlyCollection<FilePath>> TestStatic_GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) =>
GetFilePathCollections(propertyConfiguration, filesCollection);
static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) =>
XDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
} }

View File

@ -54,6 +54,14 @@ internal abstract partial class XDirectory
return new(results); return new(results);
} }
internal static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage)
{
ReadOnlyCollection<ReadOnlyCollection<FilePath>> results;
ReadOnlyCollection<string[]> filesCollection = GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
results = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
return results;
}
internal static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<string[]> filesCollection) internal static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<string[]> filesCollection)
{ {
Dictionary<string, List<string>> results = []; Dictionary<string, List<string>> results = [];
@ -76,6 +84,26 @@ internal abstract partial class XDirectory
return results; return results;
} }
internal static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{
Dictionary<string, List<string>> results = [];
List<string>? collection;
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{
foreach (FilePath filePath in filePaths)
{
if (!results.TryGetValue(filePath.Name, out collection))
{
results.Add(filePath.Name, []);
if (!results.TryGetValue(filePath.Name, out collection))
throw new Exception();
}
collection.Add(filePath.FullName);
}
}
return results;
}
internal static int LookForAbandoned(ReadOnlyCollection<string[]> jsonFilesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension) internal static int LookForAbandoned(ReadOnlyCollection<string[]> jsonFilesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension)
{ {
string fileName; string fileName;
@ -147,41 +175,37 @@ internal abstract partial class XDirectory
return result; return result;
} }
internal static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles) internal static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles)
{ {
List<FilePair> results = []; List<FilePair> results = [];
string? match; string? match;
string fileName;
bool uniqueFileName; bool uniqueFileName;
string fileExtension;
List<string>? collection; List<string>? collection;
bool? isNotUniqueAndNeedsReview; bool? isNotUniqueAndNeedsReview;
foreach (string[] files in filesCollection) foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
foreach (string file in files) foreach (FilePath filePath in filePaths)
{ {
isNotUniqueAndNeedsReview = null; isNotUniqueAndNeedsReview = null;
fileName = Path.GetFileName(file); if (propertyConfiguration.IgnoreExtensions.Contains(filePath.ExtensionLowered))
fileExtension = Path.GetExtension(file);
if (propertyConfiguration.IgnoreExtensions.Contains(fileExtension))
continue; continue;
if (!fileNamesToFiles.TryGetValue(fileName, out collection)) if (!fileNamesToFiles.TryGetValue(filePath.Name, out collection))
throw new Exception(); throw new Exception();
uniqueFileName = collection.Count == 1; uniqueFileName = collection.Count == 1;
if (!uniqueFileName) if (!uniqueFileName)
isNotUniqueAndNeedsReview = GetIsNotUniqueAndNeedsReview(file, collection); isNotUniqueAndNeedsReview = GetIsNotUniqueAndNeedsReview(filePath.FullName, collection);
if (!compareFileNamesToFiles.TryGetValue(string.Concat(fileName, extension), out collection)) if (!compareFileNamesToFiles.TryGetValue(string.Concat(filePath.Name, extension), out collection))
results.Add(new(file, uniqueFileName, isNotUniqueAndNeedsReview, [], null)); results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, [], null));
else else
{ {
if (collection.Count == 0) if (collection.Count == 0)
results.Add(new(file, uniqueFileName, isNotUniqueAndNeedsReview, collection, null)); results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, collection, null));
else if (uniqueFileName && collection.Count == 1) else if (uniqueFileName && collection.Count == 1)
results.Add(new(file, uniqueFileName, isNotUniqueAndNeedsReview, collection, collection.First())); results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, collection, collection.First()));
else else
{ {
match = GetMatch(file, collection); match = GetMatch(filePath.FullName, collection);
results.Add(new(file, uniqueFileName, isNotUniqueAndNeedsReview, collection, match)); results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, collection, match));
} }
} }
} }
@ -272,24 +296,38 @@ internal abstract partial class XDirectory
} }
} }
private static FilePath[] GetSortedRecords(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) private static FilePath[] GetSortedRecords(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
List<FilePath> results = []; List<FilePath> results = [];
FilePath filePath; foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
Models.FileHolder fileHolder;
foreach (string[] files in filesCollection)
{ {
foreach (string file in files) foreach (FilePath filePath in filePaths)
{
fileHolder = IFileHolder.Get(file);
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
results.Add(filePath); results.Add(filePath);
}
} }
return (from l in results orderby l.CreationTicks, l.FullName.Length descending select l).ToArray(); return (from l in results orderby l.CreationTicks, l.FullName.Length descending select l).ToArray();
} }
internal static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<string[]> filesCollection, string[] directories, Action? tick) internal static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection)
{
List<ReadOnlyCollection<FilePath>> results = [];
FilePath filePath;
List<FilePath> filePaths;
Models.FileHolder fileHolder;
foreach (string[] files in filesCollection)
{
filePaths = [];
foreach (string file in files)
{
fileHolder = IFileHolder.Get(file);
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
filePaths.Add(filePath);
}
results.Add(new(filePaths));
}
return new(results);
}
internal static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string[] directories, Action? tick)
{ {
List<(FilePath, string)> results = []; List<(FilePath, string)> results = [];
string paddedId; string paddedId;
@ -307,7 +345,7 @@ internal abstract partial class XDirectory
List<string> distinct = []; List<string> distinct = [];
Models.FileHolder fileHolder; Models.FileHolder fileHolder;
List<string> distinctDirectories = []; List<string> distinctDirectories = [];
FilePath[] sortedRecords = GetSortedRecords(propertyConfiguration, filesCollection); FilePath[] sortedRecords = GetSortedRecords(filePathsCollection);
bool isOffsetDeterministicHashCode = IId.IsOffsetDeterministicHashCode(propertyConfiguration); bool isOffsetDeterministicHashCode = IId.IsOffsetDeterministicHashCode(propertyConfiguration);
for (int i = 0; i < sortedRecords.Length; i++) for (int i = 0; i < sortedRecords.Length; i++)
{ {

View File

@ -33,8 +33,8 @@
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.4.3" /> <PackageReference Include="MSTest.TestAdapter" Version="3.5.0" />
<PackageReference Include="MSTest.TestFramework" Version="3.4.3" /> <PackageReference Include="MSTest.TestFramework" Version="3.5.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\BlurHash\BlurHash.csproj" /> <ProjectReference Include="..\BlurHash\BlurHash.csproj" />

View File

@ -32,8 +32,8 @@
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.4.3" /> <PackageReference Include="MSTest.TestAdapter" Version="3.5.0" />
<PackageReference Include="MSTest.TestFramework" Version="3.4.3" /> <PackageReference Include="MSTest.TestFramework" Version="3.5.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\BlurHash\BlurHash.csproj" /> <ProjectReference Include="..\BlurHash\BlurHash.csproj" />