diff --git a/.vscode/mklink.md b/.vscode/mklink.md new file mode 100644 index 0000000..5ab8c3a --- /dev/null +++ b/.vscode/mklink.md @@ -0,0 +1,14 @@ +--- +type: "note" +created: "2023-10-20T03:56:21.490Z" +updated: "2023-10-20T03:57:15.006Z" +--- + +# mklink + +```bash +``` + +```bash +mklink /J "D:\1-Images-A\Images-4083e56a-Results\A2)People\4083e56a\{}\!" "D:\1-Images-A\Images-4083e56a-Results\E)Distance\4083e56a\{}\!" +``` diff --git a/BlurHash/Models/BlurHasher.cs b/BlurHash/Models/BlurHasher.cs index 4eb8b05..0e84ff2 100644 --- a/BlurHash/Models/BlurHasher.cs +++ b/BlurHash/Models/BlurHasher.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Drawing; using System.Text; using View_by_Distance.Shared.Models; @@ -21,7 +22,7 @@ public class C2_BlurHasher : IBlurHasher public void Update(string resultsFullGroupDirectory) { _FileGroups.Clear(); - Dictionary keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, resultsFullGroupDirectory, [_PropertyConfiguration.ResultContent, _PropertyConfiguration.ResultSingleton]); + ReadOnlyDictionary keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, resultsFullGroupDirectory, [_PropertyConfiguration.ResultContent, _PropertyConfiguration.ResultSingleton]); foreach (KeyValuePair keyValuePair in keyValuePairs) _FileGroups.Add(keyValuePair.Key, keyValuePair.Value); } @@ -39,17 +40,17 @@ public class C2_BlurHasher : IBlurHasher return result; } - string IBlurHasher.GetFile(FileHolder fileHolder) + string IBlurHasher.GetFile(FilePath filePath) { string result; if (_FileGroups.Count == 0) throw new Exception("Call Update first!"); - (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration.ResultAllInOneSubdirectoryLength, fileHolder.Name); - result = Path.Combine(_FileGroups[_PropertyConfiguration.ResultSingleton][directoryIndex], $"{fileHolder.Name}.csv"); + (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); + result = Path.Combine(_FileGroups[_PropertyConfiguration.ResultSingleton][directoryIndex], $"{filePath.Name}.csv"); return result; } - string IBlurHasher.EncodeAndSave(FileHolder fileHolder) + string IBlurHasher.EncodeAndSave(FilePath filePath, FileHolder fileHolder) { string result; if (_FileGroups.Count == 0) @@ -57,7 +58,7 @@ public class C2_BlurHasher : IBlurHasher int actualByte; string extension = ".png"; IBlurHasher blurHasher = this; - string file = blurHasher.GetFile(fileHolder); + string file = blurHasher.GetFile(filePath); #pragma warning disable CA1416 Image image = Image.FromFile(fileHolder.FullName); int outputWidth = (int)(image.Width * .25); @@ -71,7 +72,7 @@ public class C2_BlurHasher : IBlurHasher string fileNameWithoutExtension = $"{componentsX}x{componentsY}-{outputWidth}x{outputHeight}-{joined}"; string contents = string.Concat(result, Environment.NewLine, fileNameWithoutExtension, Environment.NewLine, extension); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(file, contents, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); - (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration.ResultAllInOneSubdirectoryLength, joined); + (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); file = Path.Combine(_FileGroups[_PropertyConfiguration.ResultContent][directoryIndex], $"{fileNameWithoutExtension}{extension}"); if (!File.Exists(file)) { diff --git a/Copy-Distinct/CopyDistinct.cs b/Copy-Distinct/CopyDistinct.cs index 0c283c6..769a6d5 100644 --- a/Copy-Distinct/CopyDistinct.cs +++ b/Copy-Distinct/CopyDistinct.cs @@ -6,6 +6,7 @@ using System.Collections.ObjectModel; using View_by_Distance.Copy.Distinct.Models; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Methods; +using View_by_Distance.Shared.Models.Stateless.Methods; namespace View_by_Distance.Copy.Distinct; @@ -17,7 +18,7 @@ public class CopyDistinct private readonly Configuration _Configuration; private readonly IsEnvironment _IsEnvironment; private readonly IConfigurationRoot _ConfigurationRoot; - private readonly IReadOnlyDictionary _FileGroups; + private readonly ReadOnlyDictionary _FileGroups; private readonly Property.Models.Configuration _PropertyConfiguration; public CopyDistinct(List args, ILogger logger, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) @@ -63,7 +64,7 @@ public class CopyDistinct const string directorySearchFilter = "*"; string copyTo = Path.GetFullPath(_AppSettings.CopyTo); bool move = copyTo == _PropertyConfiguration.RootDirectory; - ReadOnlyCollection filesCollection = Shared.Models.Stateless.Methods.IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage); + ReadOnlyCollection filesCollection = IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage); bool anyLenFiles = filesCollection.Any(l => l.Any(m => m.EndsWith("len"))); if (!move) moveBack = false; @@ -92,13 +93,15 @@ public class CopyDistinct return (move, new(filesCollection), anyLenFiles, moveBack); } - private static (string[], List<(FileHolder, string?, string)>) GetMoveBackToDoCollection(ReadOnlyCollection filesCollection) + private static (string[], List<(FilePath, string)>) GetMoveBackToDoCollection(Property.Models.Configuration propertyConfiguration, ReadOnlyCollection filesCollection) { - List<(FileHolder, string?, string)> results = []; + List<(FilePath, string)> results = []; string key; string? value; string fileName; + FilePath filePath; string? directory; + FileHolder fileHolder; string destinationFile; List distinctFound = []; List distinctNeeded = []; @@ -146,7 +149,9 @@ public class CopyDistinct directory = Path.GetDirectoryName(value); if (string.IsNullOrEmpty(directory)) continue; - results.Add(new(new(file), null, value)); + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(file); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); + results.Add(new(filePath, value)); if (!distinctDirectories.Contains(directory)) distinctDirectories.Add(directory); } @@ -161,21 +166,21 @@ public class CopyDistinct string[] distinctDirectories; ConsoleKey? consoleKey = null; string message = nameof(CopyDistinct); - List<(FileHolder, string?, string)> toDoCollection; + List<(FilePath, string)> toDoCollection; int count = filesCollection.Select(l => l.Length).Sum(); ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; if (moveBack) { if (!anyLenFiles) throw new NotSupportedException(); - (distinctDirectories, toDoCollection) = GetMoveBackToDoCollection(filesCollection); + (distinctDirectories, toDoCollection) = GetMoveBackToDoCollection(_PropertyConfiguration, filesCollection); } else { progressBar = new(count, message, options); string key = string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey) ? _PropertyConfiguration.ResultAllInOne : _AppSettings.ResultDirectoryKey; string[] directories = _FileGroups[key]; - (distinctDirectories, toDoCollection) = Shared.Models.Stateless.Methods.IDirectory.GetToDoCollection(_PropertyConfiguration, _AppSettings.CopyDuplicates, _AppSettings.IfCanUseId, filesCollection, directories, () => progressBar.Tick()); + (distinctDirectories, toDoCollection) = IDirectory.GetToDoCollection(_PropertyConfiguration, _AppSettings.CopyDuplicates, _AppSettings.IfCanUseId, filesCollection, directories, () => progressBar.Tick()); progressBar.Dispose(); } foreach (string distinctDirectory in distinctDirectories) @@ -212,7 +217,7 @@ public class CopyDistinct else { progressBar = new(count, message, options); - results.AddRange(Shared.Models.Stateless.Methods.IDirectory.CopyOrMove(toDoCollection, move, moveBack, () => progressBar.Tick())); + results.AddRange(IDirectory.CopyOrMove(toDoCollection, move, moveBack, () => progressBar.Tick())); progressBar.Dispose(); if (move || moveBack) logger?.LogInformation("Done moving"); diff --git a/Distance/Models/_E_Distance.cs b/Distance/Models/_E_Distance.cs index d83390c..206914a 100644 --- a/Distance/Models/_E_Distance.cs +++ b/Distance/Models/_E_Distance.cs @@ -11,7 +11,7 @@ namespace View_by_Distance.Distance.Models; public partial class E_Distance : IDistance { - internal record Record(string File, FaceRecognitionDotNet.FaceEncoding FaceRecognitionDotNetFaceEncoding); + internal record Record(FilePath FilePath, FaceRecognitionDotNet.FaceEncoding FaceRecognitionDotNetFaceEncoding); private readonly List _Moved; private readonly List _Debug; @@ -40,11 +40,11 @@ public partial class E_Distance : IDistance _RangeDistanceToleranceAverage = rangeDistanceTolerance.Average(); } - private static void MoveUnableToMatch(string file) + private static void MoveUnableToMatch(FilePath filePath) { - string checkFile = $"{file}.unk"; - if (File.Exists(file) && !File.Exists(checkFile)) - File.Move(file, checkFile); + string checkFile = $"{filePath.FullName}.unk"; + if (File.Exists(filePath.FullName) && !File.Exists(checkFile)) + File.Move(filePath.FullName, checkFile); } private FaceDistanceContainer[] GetFaceDistanceContainers(MappingFromItem mappingFromItem, List intersectFaces) @@ -150,7 +150,7 @@ public partial class E_Distance : IDistance return results; } - private static FileInfo? CheckFileThenGetFileInfo(string facesFileNameExtension, MappingFromItem mappingFromItem, string file, List<(Face, double?)> checkFaces) + private static FileInfo? CheckFileThenGetFileInfo(string facesFileNameExtension, FilePath filePath, MappingFromItem mappingFromItem, string file, List<(Face, double?)> checkFaces) { FileInfo? result = null; string checkFile; @@ -165,7 +165,7 @@ public partial class E_Distance : IDistance mappedFaceDirectory = Path.GetDirectoryName(file); if (mappedFaceDirectory is null) throw new NotSupportedException(); - deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(mappingFromItem.Id, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); + deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(filePath, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); checkFile = Path.Combine(mappedFaceDirectory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}"); if (checkFile == file) continue; @@ -201,10 +201,9 @@ public partial class E_Distance : IDistance } } - public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, MappingFromItem mappingFromItem, List faces, ReadOnlyCollection> locationContainers) + public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, FilePath filePath, MappingFromItem mappingFromItem, List faces, ReadOnlyCollection> locationContainers) { string? json; - string fileName; string[] matches; FileInfo? fileInfo; List intersectFaces; @@ -215,10 +214,9 @@ public partial class E_Distance : IDistance checkFaces.Clear(); foreach (LocationContainer locationContainer in locationContainers) { - if (_Renamed.Contains(locationContainer.File)) + if (_Renamed.Contains(locationContainer.FilePath.FullName)) continue; - fileName = Path.GetFileName(locationContainer.File); - if (locationContainer.FromDistanceContent && _DuplicateMappedFaceFiles.Contains(fileName)) + if (locationContainer.FromDistanceContent && _DuplicateMappedFaceFiles.Contains(locationContainer.FilePath.Name)) continue; checkFaces.Clear(); if (locationContainer.Directories.Count == 0) @@ -231,7 +229,7 @@ public partial class E_Distance : IDistance if (json is null) { if (_DistanceMoveUnableToMatch) - MoveUnableToMatch(locationContainer.File); + MoveUnableToMatch(locationContainer.FilePath); continue; } if (filteredFaces.Length > 0) @@ -254,42 +252,42 @@ public partial class E_Distance : IDistance if (checkFaces.Count == 0) { if (_DistanceMoveUnableToMatch) - MoveUnableToMatch(locationContainer.File); + MoveUnableToMatch(locationContainer.FilePath); continue; } if (checkFaces.Count != 1) { if (_DistanceMoveUnableToMatch) - MoveUnableToMatch(locationContainer.File); + MoveUnableToMatch(locationContainer.FilePath); continue; } - fileInfo = CheckFileThenGetFileInfo(facesFileNameExtension, mappingFromItem, locationContainer.File, checkFaces); + fileInfo = CheckFileThenGetFileInfo(facesFileNameExtension, filePath, mappingFromItem, locationContainer.FilePath.FullName, checkFaces); if (fileInfo is not null) { if (_DistanceRenameToMatch && fileInfo is not null) { if (fileInfo.Exists) - File.Delete(locationContainer.File); + File.Delete(locationContainer.FilePath.FullName); else - File.Move(locationContainer.File, fileInfo.FullName); - File.WriteAllText($"{fileInfo.FullName}.old", $"{fileInfo.FullName}{Environment.NewLine}{locationContainer.File}"); - _Renamed.Add(locationContainer.File); + File.Move(locationContainer.FilePath.FullName, fileInfo.FullName); + File.WriteAllText($"{fileInfo.FullName}.old", $"{fileInfo.FullName}{Environment.NewLine}{locationContainer.FilePath.FullName}"); + _Renamed.Add(locationContainer.FilePath.FullName); } continue; } - if (_AllMappedFaceFileNames.Contains(fileName)) + if (_AllMappedFaceFileNames.Contains(locationContainer.FilePath.Name)) { lock (_AllMappedFaceFiles) - matches = (from l in _AllMappedFaceFiles where l != locationContainer.File && Path.GetFileName(l) == fileName select l).ToArray(); + matches = (from l in _AllMappedFaceFiles where l != locationContainer.FilePath.FullName && Path.GetFileName(l) == locationContainer.FilePath.Name select l).ToArray(); if (locationContainer.FromDistanceContent && matches.Length > 0) - AppendMatchingDuplicates(locationContainer.File, matches); + AppendMatchingDuplicates(locationContainer.FilePath.FullName, matches); } if (!locationContainer.FromDistanceContent) continue; lock (_AllMappedFaceFiles) - _AllMappedFaceFiles.Add(locationContainer.File); + _AllMappedFaceFiles.Add(locationContainer.FilePath.FullName); lock (_AllMappedFaceFileNames) - _AllMappedFaceFileNames.Add(fileName); + _AllMappedFaceFileNames.Add(locationContainer.FilePath.Name); } } @@ -491,13 +489,13 @@ public partial class E_Distance : IDistance List faceDistanceEncodings = []; foreach (Record record in records) { - files.Add(record.File); + files.Add(record.FilePath.FullName); faceDistanceEncodings.Add(new(record.FaceRecognitionDotNetFaceEncoding)); } foreach (Record record in records) { mappedRelations = []; - fileHolder = new(record.File); + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(record.FilePath.FullName); if (files.Count > 1) { faceDistanceEncoding = new(record.FaceRecognitionDotNetFaceEncoding); @@ -538,7 +536,7 @@ public partial class E_Distance : IDistance if (modelsFaceEncoding is null) throw new NotSupportedException(); faceRecognitionDotNetFaceEncoding = FaceRecognition.LoadFaceEncoding(modelsFaceEncoding.RawEncoding); - records.Add(new(locationContainer.File, faceRecognitionDotNetFaceEncoding)); + records.Add(new(locationContainer.FilePath, faceRecognitionDotNetFaceEncoding)); } result = GetRelationCollections(faceDistancePermyriad, locationContainerDistanceTake, locationContainerDistanceTolerance, records); return result; diff --git a/Drag-Drop-Set-Property-Item/DragDropSetPropertyItem.cs b/Drag-Drop-Set-Property-Item/DragDropSetPropertyItem.cs index 2de7855..30ca0c5 100644 --- a/Drag-Drop-Set-Property-Item/DragDropSetPropertyItem.cs +++ b/Drag-Drop-Set-Property-Item/DragDropSetPropertyItem.cs @@ -114,7 +114,7 @@ public partial class DragDropSetPropertyItem : Form bool isValidImageFormatExtension; foreach (string file in files) { - fileHolder = new(file); + fileHolder = IFileHolder.Get(file); isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered); isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered); (dateTimeOriginal, _, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding); diff --git a/Duplicate-Search/DuplicateSearch.cs b/Duplicate-Search/DuplicateSearch.cs index d930969..97e8cea 100644 --- a/Duplicate-Search/DuplicateSearch.cs +++ b/Duplicate-Search/DuplicateSearch.cs @@ -187,11 +187,11 @@ public class DuplicateSearch mappingFromItem = collection[zero]; if (mappingFromItem is not null) { - resizedFileHolder = new(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}")); + resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}")); collection[0] = new(mappingFromItem.ContainerDateTimes, item.Property.DateTimeDigitized, item.Property.DateTimeOriginal, mappingFromItem.Id, mappingFromItem.ImageFileHolder, mappingFromItem.IsWrongYear, item.Property.Keywords ?? [], mappingFromItem.MinimumDateTime, item.Property.Model, mappingFromItem.RelativePath, resizedFileHolder); } } - resizedFileHolder = new(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath)); + resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath)); mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); collection.Add(mappingFromItem); } diff --git a/Face/Models/_D_Face.cs b/Face/Models/_D_Face.cs index 22a3491..94a9d8b 100644 --- a/Face/Models/_D_Face.cs +++ b/Face/Models/_D_Face.cs @@ -101,7 +101,7 @@ public class D_Face public void Update(string dResultsFullGroupDirectory) { _FileGroups.Clear(); - Dictionary keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, dResultsFullGroupDirectory, [_PropertyConfiguration.ResultCollection, _PropertyConfiguration.ResultContent]); + ReadOnlyDictionary keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, dResultsFullGroupDirectory, [_PropertyConfiguration.ResultCollection, _PropertyConfiguration.ResultContent]); foreach (KeyValuePair keyValuePair in keyValuePairs) _FileGroups.Add(keyValuePair.Key, keyValuePair.Value); } @@ -302,7 +302,7 @@ public class D_Face locationContainer.Directories, locationContainer.DirectoryNumber, locationContainer.DisplayDirectoryName, - locationContainer.File, + locationContainer.FilePath, locationContainer.FromDistanceContent, locationContainer.Id, location, @@ -316,7 +316,7 @@ public class D_Face return results; } - public List GetFaces(string outputResolution, string dResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, ReadOnlyCollection>? locationContainers, List? mappingFromPhotoPrismCollection) + public List GetFaces(string outputResolution, string dResultsFullGroupDirectory, FilePath filePath, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, ReadOnlyCollection>? locationContainers, List? mappingFromPhotoPrismCollection) { List? results; if (string.IsNullOrEmpty(dResultsFullGroupDirectory)) @@ -325,7 +325,7 @@ public class D_Face List? locations; string[] changesFrom = [nameof(A_Property), nameof(B_Metadata), nameof(C_Resize)]; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration.ResultAllInOneSubdirectoryLength, mappingFromItem.ImageFileHolder.Name); + (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); FileInfo fileInfo = new(Path.Combine(_FileGroups[_PropertyConfiguration.ResultCollection][directoryIndex], $"{mappingFromItem.ImageFileHolder.NameWithoutExtension}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json")); if (_ForceFaceLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) { @@ -394,7 +394,7 @@ public class D_Face return results; } - public List<(Shared.Models.Face, FileInfo?, string, bool)> SaveFaces(string f, string dResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, List faces) + public List<(Shared.Models.Face, FileInfo?, string, bool)> SaveFaces(string f, string dResultsFullGroupDirectory, FilePath filePath, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, List faces) { List<(Shared.Models.Face, FileInfo?, string, bool Save)> results = []; bool save; @@ -402,7 +402,7 @@ public class D_Face string deterministicHashCodeKey; string[] changesFrom = [nameof(A_Property), nameof(B_Metadata), nameof(C_Resize)]; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration.ResultAllInOneSubdirectoryLength, mappingFromItem.ImageFileHolder.Name); + (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); string directory = Path.Combine(_FileGroups[_PropertyConfiguration.ResultContent][directoryIndex], mappingFromItem.ImageFileHolder.NameWithoutExtension); bool directoryExists = Directory.Exists(directory); foreach (Shared.Models.Face face in faces) @@ -413,7 +413,7 @@ public class D_Face results.Add(new(face, null, string.Empty, save)); continue; } - deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(mappingFromItem.Id, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); + deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(filePath, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); fileInfo = new FileInfo(Path.Combine(directory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{_FileNameExtension}")); if (!directoryExists) save = true; diff --git a/FaceParts/Models/_D2_FaceParts.cs b/FaceParts/Models/_D2_FaceParts.cs index ef4e55d..e8faec0 100644 --- a/FaceParts/Models/_D2_FaceParts.cs +++ b/FaceParts/Models/_D2_FaceParts.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; @@ -51,7 +52,7 @@ public class D2_FaceParts public void Update(string dResultsFullGroupDirectory) { _FileGroups.Clear(); - Dictionary keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, dResultsFullGroupDirectory, [_PropertyConfiguration.ResultContent]); + ReadOnlyDictionary keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, dResultsFullGroupDirectory, [_PropertyConfiguration.ResultContent]); foreach (KeyValuePair keyValuePair in keyValuePairs) _FileGroups.Add(keyValuePair.Key, keyValuePair.Value); } @@ -182,7 +183,7 @@ public class D2_FaceParts return result; } - private void SaveFaceParts(int pointSize, IFileHolder resizedFileHolder, bool saveRotated, List<(Shared.Models.Face, string, string)> collection) + private void SaveFaceParts(int pointSize, FileHolder resizedFileHolder, bool saveRotated, List<(Shared.Models.Face, string, string)> collection) { int x; int y; @@ -244,7 +245,7 @@ public class D2_FaceParts #pragma warning restore CA1416 - public void SaveFaceLandmarkImages(Configuration configuration, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, List faces, bool saveRotated) + public void SaveFaceLandmarkImages(Configuration configuration, FilePath filePath, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, List faces, bool saveRotated) { FileInfo fileInfo; bool check = false; @@ -257,7 +258,7 @@ public class D2_FaceParts List<(Shared.Models.Face, string, string)> collection = []; string[] changesFrom = [nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face)]; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration.ResultAllInOneSubdirectoryLength, mappingFromItem.ImageFileHolder.Name); + (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); string directory = Path.Combine(_FileGroups[_PropertyConfiguration.ResultContent][directoryIndex], mappingFromItem.ImageFileHolder.NameWithoutExtension); bool directoryExists = Directory.Exists(directory); foreach (Shared.Models.Face face in faces) @@ -267,7 +268,7 @@ public class D2_FaceParts collection.Add(new(face, string.Empty, string.Empty)); continue; } - deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(mappingFromItem.Id, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); + deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(filePath, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); fileInfo = new FileInfo(Path.Combine(directory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{_FileNameExtension}")); if (string.IsNullOrEmpty(fileInfo.DirectoryName)) continue; diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index a2b92c2..cab1949 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -127,7 +127,7 @@ public partial class DlibDotNet _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, propertyConfiguration.ResultSingleton)); string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration.PropertyConfiguration, nameof(A2_People), "{}"); string a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration.PropertyConfiguration, nameof(A2_People), "([])"); - personContainers = new(IPersonContainer.GetPersonContainers(a2PeopleSingletonDirectory, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension)); + personContainers = new(IPersonContainer.GetPersonContainers(a2PeopleSingletonDirectory, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), configuration.PropertyConfiguration, _Faces.FileNameExtension)); if (configuration.JLinks.Where(l => !string.IsNullOrEmpty(l)).Any()) { _JLinkResolvedDirectories.AddRange(Map.Models.Stateless.Methods.IMapLogic.GetJLinkDirectories(configuration.GenealogicalDataCommunicationFile, configuration.JLinks, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), a2PeopleSingletonDirectory, a2PeopleContentDirectory)); @@ -237,6 +237,7 @@ public partial class DlibDotNet private ReadOnlyCollection GetNotNineCollection(ReadOnlyCollection filesCollection) { List results = []; + FilePath filePath; FileHolder fileHolder; foreach (string[] files in filesCollection) { @@ -244,11 +245,11 @@ public partial class DlibDotNet { if (!file.Contains(" !9")) continue; - fileHolder = new(file); - (_, int? id) = IDirectory.GetId(_Configuration.PropertyConfiguration.Offset, fileHolder); - if (id is null) + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(file); + filePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: null); + if (filePath.Id is null) continue; - results.Add(id.Value); + results.Add(filePath.Id.Value); } } return new(results); @@ -332,7 +333,7 @@ public partial class DlibDotNet if (outputResolution.Any(char.IsNumber)) continue; (cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution); - filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent, _Configuration.PropertyConfiguration.ResultAllInOne); + filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent); filesCollection = IDirectory.GetFilesCollection(filesCollectionRootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage: true); count = filesCollection.Select(l => l.Length).Sum(); break; @@ -370,6 +371,8 @@ public partial class DlibDotNet ReadOnlyCollection distinctFilteredMappingCollection = GetMappings(_Configuration.PropertyConfiguration, eDistanceContentDirectory, containers, mapLogic, distinctItems: true); if (runToDoCollectionFirst) { + if (!Directory.Exists(eDistanceContentDirectory)) + _ = Directory.CreateDirectory(eDistanceContentDirectory); string json = JsonSerializer.Serialize(distinctFilteredMappingCollection); File.WriteAllText(Path.Combine(eDistanceContentDirectory, $"{ticks}.json"), json); } @@ -462,6 +465,7 @@ public partial class DlibDotNet Uri uri; string? line; string fileName; + FilePath filePath; Task task; string relativePath; FileHolder fileHolder; @@ -487,8 +491,9 @@ public partial class DlibDotNet extensionLowered = Path.GetExtension(uri.LocalPath); relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFile, length, forceExtensionToLower: true); isValidImageFormatExtension = _Configuration.PropertyConfiguration.ValidImageFormatExtensions.Contains(extensionLowered); - fileHolder = new(sourceDirectoryFile); - _ = new Item(fileHolder, relativePath, isValidImageFormatExtension); + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(sourceDirectoryFile); + filePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: null); + _ = new Item(filePath, fileHolder, relativePath, isValidImageFormatExtension); // container.Items.Add(item); } _Logger?.LogInformation(". . ."); @@ -774,12 +779,6 @@ public partial class DlibDotNet _Logger?.LogInformation(string.Concat("Moved <", item.ImageFileHolder.FullName, '>')); } - private void LogNameWithoutExtensionIsIdFormatBut(Item item) - { - _Logger?.LogInformation($"Name without extension is Id format but doesn't match id <{item.ImageFileHolder.FullName}>"); - File.Move(item.ImageFileHolder.FullName, $"{item.ImageFileHolder.FullName}.rename"); - } - private int GetNotMappedCountAndUpdateMappingFromPersonThenSetMapping(MapLogic mapLogic, Item item, bool? isFocusRelativePath, ReadOnlyCollection> locationContainers, MappingFromItem mappingFromItem, List? mappingFromPhotoPrismCollection, List faces) { int result; @@ -801,7 +800,7 @@ public partial class DlibDotNet bool? isFocusModel = GetIsFocusModel(item.Property); long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray(); ReadOnlyDictionary>? wholePercentagesToPersonContainers; - ReadOnlyCollection locationContainersFiles = new((from l in locationContainers select l.File).ToArray()); + ReadOnlyCollection locationContainersFiles = new((from l in locationContainers select l.FilePath.FullName).ToArray()); foreach (Shared.Models.Face face in faces) { wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(item.Property?.Id); @@ -826,7 +825,7 @@ public partial class DlibDotNet confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, face.Location.Confidence); faceAreaPermyriad = IMapping.GetAreaPermyriad(_Configuration.FaceAreaPermyriad, face.Location, face.OutputResolution); wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); - deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); + deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.FilePath, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle); inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation); mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath); @@ -834,7 +833,7 @@ public partial class DlibDotNet isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); } - mapping = new(mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection); + mapping = new(item.FilePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection); notMapped += mapLogic.UpdateMappingFromPerson(wholePercentagesToPersonContainers, mapping); face.SetMapping(mapping); } @@ -904,7 +903,7 @@ public partial class DlibDotNet else { wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(Shared.Models.Stateless.ILocation.Digits); - deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, Shared.Models.Stateless.ILocation.Digits); + deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.FilePath, Shared.Models.Stateless.ILocation.Digits); mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle); inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation); mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath); @@ -912,7 +911,7 @@ public partial class DlibDotNet isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); } - result = new(mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection: null); + result = new(item.FilePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection: null); int notMapped = mapLogic.UpdateMappingFromPerson(wholePercentagesToPersonContainers, result); return (result, notMapped); } @@ -940,8 +939,8 @@ public partial class DlibDotNet DateTime dateTime = DateTime.Now; Shared.Models.Property? property; List parseExceptions = []; - List> subFileTuples = []; string[] changesFrom = [nameof(A_Property)]; + List> subFileTuples = []; FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber); ReadOnlyCollection> locationContainers = mapLogic.GetLocationContainers(item); if (item.Property is null || item.Property.Id is null || !item.SourceDirectoryFileHolder.Exists || item.SourceDirectoryFileHolder.CreationTime is null || item.SourceDirectoryFileHolder.LastWriteTime is null || item.Any()) @@ -973,18 +972,12 @@ public partial class DlibDotNet subFileTuples.Add(new Tuple(nameof(A_Property), item.SourceDirectoryFileHolder.LastWriteTime.Value)); else subFileTuples.Add(new Tuple(nameof(A_Property), new FileInfo(item.SourceDirectoryFileHolder.FullName).LastWriteTime)); - short sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex(_Configuration.PropertyConfiguration.Offset); - bool nameWithoutExtensionIsIdFormat = Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(item.ImageFileHolder); - bool nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(item.ImageFileHolder, sortOrderOnlyLengthIndex); - if (nameWithoutExtensionIsIdFormat && item.ImageFileHolder.NameWithoutExtension != item.Property.Id.ToString()) - LogNameWithoutExtensionIsIdFormatBut(item); - if (nameWithoutExtensionIsPaddedIdFormat && item.ImageFileHolder.NameWithoutExtension.EndsWith(item.Property.Id.Value.ToString()[1..])) - LogNameWithoutExtensionIsIdFormatBut(item); + FilePath filePath = FilePath.Get(_Configuration.PropertyConfiguration, item.ImageFileHolder, index: null); if (resizedFileHolder.Exists && item.Property.Width is not null && item.Property.Width.Value > 4 && _Configuration.SaveBlurHashForOutputResolutions.Contains(outputResolution)) { - string? file = _BlurHasher.GetFile(resizedFileHolder); + string? file = _BlurHasher.GetFile(item.FilePath); if (file is not null && !File.Exists(file)) - _ = _BlurHasher.EncodeAndSave(resizedFileHolder); + _ = _BlurHasher.EncodeAndSave(item.FilePath, resizedFileHolder); } } if (property is null || item.Property is null) @@ -992,7 +985,7 @@ public partial class DlibDotNet item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder); MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); Map.Models.Stateless.Methods.IMapLogic.SetCreationTimeMaybeMoveToDecade(_Configuration.PropertyConfiguration, _Configuration.MoveToDecade && _Configuration.LocationContainerDistanceTolerance is null, mappingFromItem, locationContainers); - ReadOnlyDictionary metadataExtractorDirectories = metadata.GetMetadataCollection(subFileTuples, parseExceptions, changesFrom, mappingFromItem); + ReadOnlyDictionary metadataExtractorDirectories = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem); if (_AppSettings.Places.Count > 0) { float latitude; @@ -1015,7 +1008,7 @@ public partial class DlibDotNet distance += 1; } } - Dictionary outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, item.Property, mappingFromItem); + Dictionary outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem); if (_Configuration.SaveResizedSubfiles) _Resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize); if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) @@ -1027,21 +1020,21 @@ public partial class DlibDotNet List? mappingFromPhotoPrismCollection; if (!fileNameToCollection.TryGetValue(mappingFromItem.Id, out mappingFromPhotoPrismCollection)) mappingFromPhotoPrismCollection = null; - faces = _Faces.GetFaces(outputResolution, dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, locationContainers, mappingFromPhotoPrismCollection); + faces = _Faces.GetFaces(outputResolution, dResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, locationContainers, mappingFromPhotoPrismCollection); result = GetNotMappedCountAndUpdateMappingFromPersonThenSetMapping(mapLogic, item, isFocusRelativePath, locationContainers, mappingFromItem, mappingFromPhotoPrismCollection, faces); - List<(Shared.Models.Face, FileInfo?, string, bool Saved)> faceCollection = _Faces.SaveFaces(_FaceParts.FileNameExtension, dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, faces); + List<(Shared.Models.Face, FileInfo?, string, bool Saved)> faceCollection = _Faces.SaveFaces(_FaceParts.FileNameExtension, dResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, mappingFromItem, faces); if (_Configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) _FaceParts.CopyFacesAndSaveFaceLandmarkImage(facePartsCollectionDirectory, mappingFromItem, faceCollection); if ((_Configuration.DistanceMoveUnableToMatch || _Configuration.DistanceRenameToMatch) && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) && locationContainers is not null && faceCollection.All(l => !l.Saved)) - _Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, mappingFromItem, faces, locationContainers); + _Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, item.FilePath, mappingFromItem, faces, locationContainers); (bool review, int[] eyesCollection) = Shared.Models.Stateless.Methods.IFace.GetEyeCollection(_Configuration.EyeThreshold, faces); if (review || _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) { bool saveRotated = false; string sourceDirectorySegment = Property.Models.Stateless.IResult.GetRelativePath(_Configuration.PropertyConfiguration, container.SourceDirectory); - _FaceParts.SaveFaceLandmarkImages(_Configuration.PropertyConfiguration, subFileTuples, parseExceptions, mappingFromItem, faces, saveRotated); + _FaceParts.SaveFaceLandmarkImages(_Configuration.PropertyConfiguration, item.FilePath, subFileTuples, parseExceptions, mappingFromItem, faces, saveRotated); } } lock (sourceDirectoryChanges) @@ -1233,7 +1226,7 @@ public partial class DlibDotNet int count = filesCollection.Select(l => l.Length).Sum(); string message = $") Selecting for ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)"; progressBar = new(count, message, options); - (string[] distinctDirectories, List<(FileHolder, string?, string)> toDoCollection) = IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, filesCollection, fileGroups[_Configuration.PropertyConfiguration.ResultContent], () => progressBar.Tick()); + (string[] distinctDirectories, List<(FilePath, string)> toDoCollection) = IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, filesCollection, fileGroups[_Configuration.PropertyConfiguration.ResultContent], () => progressBar.Tick()); progressBar.Dispose(); foreach (string distinctDirectory in distinctDirectories) { diff --git a/Instance/Instance.csproj b/Instance/Instance.csproj index 9d7c6df..9904295 100644 --- a/Instance/Instance.csproj +++ b/Instance/Instance.csproj @@ -5,8 +5,8 @@ Exe win-x64 net8.0 - 2999dda1-5329-4d9f-9d68-cccfabe0e47f - + 2999dda1-5329-4d9f-9d68-cccfabe0e47f + Phares.View.by.Distance.Instance false diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index 03077de..29ceadf 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -200,9 +200,9 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic continue; foreach (LocationContainer locationContainer in keyValuePair.Value) { - if (locationContainer.File.Contains('!')) + if (locationContainer.FilePath.FullName.Contains('!')) continue; - renameCollection.Add(locationContainer.File); + renameCollection.Add(locationContainer.FilePath.FullName); } } if (renameCollection.Count > 0) @@ -259,7 +259,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic readOnlyPersonKeyFormattedCollection = new(personKeyFormattedCollection); readOnlyPersonKeyFormattedToNewestPersonKeyFormatted = new(personKeyFormattedToNewestPersonKeyFormatted); } - List records = Stateless.DistanceLogic.DeleteEmptyDirectoriesAndGetCollection(configuration, ticks, eDistanceContentDirectory, readOnlyPersonKeyFormattedToNewestPersonKeyFormatted, readOnlyPersonKeyFormattedCollection); + List records = Stateless.DistanceLogic.DeleteEmptyDirectoriesAndGetCollection(propertyConfiguration, configuration, ticks, eDistanceContentDirectory, readOnlyPersonKeyFormattedToNewestPersonKeyFormatted, readOnlyPersonKeyFormattedCollection); ReadOnlyCollection<(Stateless.MapLogic.PersonKeyFormattedIdThenWholePercentages, PersonContainer)> readOnlyPossiblyNewPersonDisplayDirectoryNamesAndPersonContainer; ReadOnlyCollection personKeyFormattedIdThenWholePercentagesCollection = Stateless.MapLogic.GetPersonKeyFormattedIdThenWholePercentages(configuration, ticks, records); // @@ -300,6 +300,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic personContainers, readOnlyPersonKeyToCount)); locationContainers.AddRange(Stateless.MapLogic.GetLocationContainers(maxDegreeOfParallelism, + propertyConfiguration, configuration, ticks, personContainers, @@ -431,17 +432,17 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic else { string checkFile; - string facesDirectory = Stateless.MapLogic.GetFacesDirectory(_PropertyConfiguration, dFacesContentDirectory, mapping.MappingFromItem); - FileHolder faceFileHolder = new(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}")); + string facesDirectory = Stateless.MapLogic.GetFacesDirectory(_PropertyConfiguration, dFacesContentDirectory, mapping.FilePath, mapping.MappingFromItem); + FileHolder faceFileHolder = IFileHolder.Get(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}")); if (!faceFileHolder.Exists) result = null; else { string shortcutFile = string.Empty; - string facePartsDirectory = Stateless.MapLogic.GetFacePartsDirectory(_PropertyConfiguration, d2FacePartsContentDirectory, mapping.MappingFromItem); + string facePartsDirectory = Stateless.MapLogic.GetFacePartsDirectory(_PropertyConfiguration, d2FacePartsContentDirectory, mapping.FilePath, mapping.MappingFromItem); checkFile = Path.Combine(directory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}"); - FileHolder hiddenFaceFileHolder = new(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesHiddenFileNameExtension}")); - FileHolder facePartsFileHolder = new(Path.Combine(facePartsDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacePartsFileNameExtension}")); + FileHolder hiddenFaceFileHolder = IFileHolder.Get(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesHiddenFileNameExtension}")); + FileHolder facePartsFileHolder = IFileHolder.Get(Path.Combine(facePartsDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacePartsFileNameExtension}")); result = new(checkFile, directory, faceFileHolder, hiddenFaceFileHolder, facePartsFileHolder, mapping.MappingFromItem.ResizedFileHolder, shortcutFile); } } @@ -616,8 +617,8 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic if (saveIndividually && question.MappingFromLocation.WholePercentages == mapping.MappingFromLocation.WholePercentages) results.Add(new(Path.Combine(directory, "Maybe"))); } - facesDirectory = Stateless.MapLogic.GetFacesDirectory(_PropertyConfiguration, dFacesContentDirectory, mapping.MappingFromItem); - faceFileHolder = new(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}")); + facesDirectory = Stateless.MapLogic.GetFacesDirectory(_PropertyConfiguration, dFacesContentDirectory, mapping.FilePath, mapping.MappingFromItem); + faceFileHolder = IFileHolder.Get(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}")); if (!faceFileHolder.Exists) continue; if (isByMapping) @@ -627,19 +628,19 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic } else if (saveIndividually) { - facePartsDirectory = Stateless.MapLogic.GetFacePartsDirectory(_PropertyConfiguration, d2FacePartsContentDirectory, mapping.MappingFromItem); - facePartsFileHolder = new(Path.Combine(facePartsDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacePartsFileNameExtension}")); + facePartsDirectory = Stateless.MapLogic.GetFacePartsDirectory(_PropertyConfiguration, d2FacePartsContentDirectory, mapping.FilePath, mapping.MappingFromItem); + facePartsFileHolder = IFileHolder.Get(Path.Combine(facePartsDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacePartsFileNameExtension}")); (saveContainer, SaveContainer? extraSaveContainer) = Stateless.MapLogic.GetContainers(_Configuration.FacesFileNameExtension, _Configuration.FacePartsFileNameExtension, directory, faceFileHolder, facePartsFileHolder, mapping); if (extraSaveContainer is not null) results.Add(extraSaveContainer); } else { - facePartsDirectory = Stateless.MapLogic.GetFacePartsDirectory(_PropertyConfiguration, d2FacePartsContentDirectory, mapping.MappingFromItem); + facePartsDirectory = Stateless.MapLogic.GetFacePartsDirectory(_PropertyConfiguration, d2FacePartsContentDirectory, mapping.FilePath, mapping.MappingFromItem); shortcutFile = Path.Combine(record.PersonDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}.lnk"); checkFile = Path.Combine(directory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}"); - hiddenFaceFileHolder = new(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesHiddenFileNameExtension}")); - facePartsFileHolder = new(Path.Combine(facePartsDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacePartsFileNameExtension}")); + hiddenFaceFileHolder = IFileHolder.Get(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesHiddenFileNameExtension}")); + facePartsFileHolder = IFileHolder.Get(Path.Combine(facePartsDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacePartsFileNameExtension}")); saveContainer = new(checkFile, directory, faceFileHolder, hiddenFaceFileHolder, facePartsFileHolder, mapping.MappingFromItem.ResizedFileHolder, shortcutFile); } results.Add(saveContainer); @@ -747,8 +748,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic key = string.Concat(personKeyFormatted, '\t', segmentB); if (!keyToCount.ContainsKey(key)) keyToCount.Add(key, new()); - if (!keyToCount.ContainsKey(key)) - keyToCount.Add(key, 0); + _ = keyToCount.TryAdd(key, 0); keyToCount[key]++; if (!_Configuration.SaveIndividually && keyToCount[key] < _Configuration.SortingMaximumPerKey) segmentC = null; @@ -828,13 +828,13 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic results.Add(new(record.PersonDirectory)); if (_Configuration.SaveIndividually && question.MappingFromLocation.WholePercentages == question.MappingFromLocation.WholePercentages) results.Add(new(Path.Combine(directory, "Maybe"))); - facesDirectory = Stateless.MapLogic.GetFacesDirectory(_PropertyConfiguration, dFacesContentDirectory, question.MappingFromItem); - faceFileHolder = new(Path.Combine(facesDirectory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}")); - facePartsDirectory = Stateless.MapLogic.GetFacePartsDirectory(_PropertyConfiguration, d2FacePartsContentDirectory, question.MappingFromItem); + facesDirectory = Stateless.MapLogic.GetFacesDirectory(_PropertyConfiguration, dFacesContentDirectory, question.FilePath, question.MappingFromItem); + faceFileHolder = IFileHolder.Get(Path.Combine(facesDirectory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}")); + facePartsDirectory = Stateless.MapLogic.GetFacePartsDirectory(_PropertyConfiguration, d2FacePartsContentDirectory, question.FilePath, question.MappingFromItem); shortcutFile = Path.Combine(record.PersonDirectory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}.lnk"); checkFile = Path.Combine(directory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}"); - hiddenFaceFileHolder = new(Path.Combine(facesDirectory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesHiddenFileNameExtension}")); - facePartsFileHolder = new(Path.Combine(facePartsDirectory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacePartsFileNameExtension}")); + hiddenFaceFileHolder = IFileHolder.Get(Path.Combine(facesDirectory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesHiddenFileNameExtension}")); + facePartsFileHolder = IFileHolder.Get(Path.Combine(facePartsDirectory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacePartsFileNameExtension}")); saveContainer = new(checkFile, directory, faceFileHolder, hiddenFaceFileHolder, facePartsFileHolder, question.MappingFromItem.ResizedFileHolder, shortcutFile); results.Add(saveContainer); if (!_Configuration.SaveIndividually && isBySorting && question.MappingFromPerson is null) @@ -988,6 +988,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic throw new NullReferenceException(nameof(_Configuration)); List results = []; string[] files; + List? ids; string checkDirectory; string[] checkDirectories; string personKeyFormatted; @@ -1019,10 +1020,10 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic (personKeyFormatted, personBirthday) = GetPersonBirthday(windowsShortcut.Path); if (personBirthday is null) throw new NotSupportedException(fileNameWithoutExtension); - if (!personKeyToIds.ContainsKey(personBirthday.Value.Ticks)) + if (!personKeyToIds.TryGetValue(personBirthday.Value.Ticks, out ids)) collection.Add(new(personBirthday.Value.Ticks, Path.Combine(checkDirectory, personKeyFormatted, fileNameWithoutExtension))); else - collection.Add(new(personBirthday.Value.Ticks, Path.Combine(checkDirectory, personKeyFormatted, fileNameWithoutExtension, $"{personKeyToIds[personBirthday.Value.Ticks].Count} Face(s)"))); + collection.Add(new(personBirthday.Value.Ticks, Path.Combine(checkDirectory, personKeyFormatted, fileNameWithoutExtension, $"{ids.Count} Face(s)"))); foreach ((long personKey, string displayDirectoryName) in collection) { matches = (from l in personContainers where l.Key == personKey && l.ApproximateYears.HasValue select l).ToArray(); @@ -1161,6 +1162,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); + List? ids; string fileName; string fullName; string directory; @@ -1215,7 +1217,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic personDirectory = Path.Combine(directory, "Unknown"); fileName = Path.Combine(personDirectory, $"{mapping.MappingFromItem.ResizedFileHolder.Name}.lnk"); collection.Add(new(mapping.MappingFromItem.ResizedFileHolder.FullName, personDirectory, mapping.MappingFromItem.GetDateTimeOriginalThenMinimumDateTime(), fileName, mapping.MappingFromLocation?.DeterministicHashCodeKey, MakeAllHidden: false)); - facesDirectory = Stateless.MapLogic.GetFacesDirectory(_PropertyConfiguration, dFacesContentDirectory, mapping.MappingFromItem); + facesDirectory = Stateless.MapLogic.GetFacesDirectory(_PropertyConfiguration, dFacesContentDirectory, mapping.FilePath, mapping.MappingFromItem); if (mapping.MappingFromLocation is null) continue; fullName = Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}"); @@ -1235,10 +1237,10 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic directoriesAndDateTimes.Add(new(mapping.MappingFromItem.ResizedFileHolder.DirectoryName, mapping.MappingFromItem.ContainerDateTimes)); } directory = Path.Combine(mapping.MappingFromItem.ResizedFileHolder.DirectoryName, $"{_PropertyConfiguration.ResultAllInOne}Shortcuts", personKeyFormatted); - if (!personKeyToIds.ContainsKey(mapping.MappingFromPerson.PersonKey)) + if (!personKeyToIds.TryGetValue(mapping.MappingFromPerson.PersonKey, out ids)) personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName); else - personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName, $"{personKeyToIds[mapping.MappingFromPerson.PersonKey].Count} Face(s)"); + personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName, $"{ids.Count} Face(s)"); fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ResizedFileHolder.Name}.lnk"); collection.Add(new(mapping.MappingFromItem.ResizedFileHolder.FullName, personDirectory, mapping.MappingFromItem.GetDateTimeOriginalThenMinimumDateTime(), fileName, mapping.MappingFromLocation?.DeterministicHashCodeKey, MakeAllHidden: false)); } diff --git a/Map/Models/Stateless/DecadeLogic.cs b/Map/Models/Stateless/DecadeLogic.cs index 4d9578a..d84c8f1 100644 --- a/Map/Models/Stateless/DecadeLogic.cs +++ b/Map/Models/Stateless/DecadeLogic.cs @@ -39,24 +39,22 @@ internal abstract class DecadeLogic string checkDirectory; string? yearDirectory; string yearDirectoryName; - string? personNameDirectory; string personNameDirectoryName; string? personKeyFormattedDirectory; string? personKeyFormattedDirectoryName; foreach (LocationContainer locationContainer in locationContainers) { - if (!File.Exists(locationContainer.File)) + if (!File.Exists(locationContainer.FilePath.FullName)) continue; dateTime = mappingFromItem.DateTimeOriginal is null ? mappingFromItem.MinimumDateTime : mappingFromItem.DateTimeOriginal.Value; if (locationContainer.CreationDateOnly.Year != dateTime.Year || locationContainer.CreationDateOnly.Month != dateTime.Month || locationContainer.CreationDateOnly.Day != dateTime.Day) - File.SetCreationTime(locationContainer.File, dateTime); + File.SetCreationTime(locationContainer.FilePath.FullName, dateTime); if (!moveToDecade) continue; - personNameDirectory = Path.GetDirectoryName(locationContainer.File); - if (string.IsNullOrEmpty(personNameDirectory)) + if (string.IsNullOrEmpty(locationContainer.FilePath.DirectoryName)) continue; - personNameDirectoryName = Path.GetFileName(personNameDirectory); - yearDirectory = Path.GetDirectoryName(personNameDirectory); + personNameDirectoryName = Path.GetFileName(locationContainer.FilePath.DirectoryName); + yearDirectory = Path.GetDirectoryName(locationContainer.FilePath.DirectoryName); if (string.IsNullOrEmpty(yearDirectory)) continue; yearDirectoryName = Path.GetFileName(yearDirectory); @@ -72,7 +70,7 @@ internal abstract class DecadeLogic checkDirectory = Path.Combine(personKeyFormattedDirectory, halfDecade, personNameDirectoryName); if (!Directory.Exists(checkDirectory)) _ = Directory.CreateDirectory(checkDirectory); - File.Move(locationContainer.File, Path.Combine(checkDirectory, Path.GetFileName(locationContainer.File))); + File.Move(locationContainer.FilePath.FullName, Path.Combine(checkDirectory, locationContainer.FilePath.Name)); } } diff --git a/Map/Models/Stateless/DistanceLogic.cs b/Map/Models/Stateless/DistanceLogic.cs index 92f7e9f..8bef1d7 100644 --- a/Map/Models/Stateless/DistanceLogic.cs +++ b/Map/Models/Stateless/DistanceLogic.cs @@ -1,8 +1,10 @@ using Humanizer; using ShellProgressBar; +using System.Buffers; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; +using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Stateless.Methods; namespace View_by_Distance.Map.Models.Stateless; @@ -11,7 +13,7 @@ internal record Record(string PersonKeyFormatted, int DirectoryNumber, string? PersonDisplayDirectoryName, bool? IsDefault, - string MappedFaceFile); + FilePath MappedFaceFilePath); internal abstract class DistanceLogic { @@ -208,31 +210,36 @@ internal abstract class DistanceLogic } } - private static List GetRecords(Configuration configuration, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, List distinct, string? personDisplayDirectoryName) + private static List GetRecords(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, List distinct, string? personDisplayDirectoryName) { List results = []; - int? id; string fileName; string checkFile; + FilePath filePath; + FileHolder fileHolder; int? wholePercentages; - foreach (string mappedFaceFile in files) + foreach (string file in files) { - if (mappedFaceFile.EndsWith(".lnk")) + if (file.EndsWith(".lnk")) continue; - (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFaceFile); - if (id is null || wholePercentages is null) + fileHolder = IFileHolder.Get(file); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); + if (filePath.Id is null) continue; - fileName = Path.GetFileName(mappedFaceFile); + wholePercentages = IMapping.GetWholePercentages(configuration.FacesFileNameExtension, filePath); + if (wholePercentages is null) + continue; + fileName = Path.GetFileName(file); if (distinct.Contains(fileName)) { - checkFile = $"{mappedFaceFile}.dup"; + checkFile = $"{file}.dup"; if (File.Exists(checkFile)) continue; - File.Move(mappedFaceFile, checkFile); + File.Move(file, checkFile); continue; } distinct.Add(fileName); - results.Add(new(personKeyFormatted, directoryNumber, personDisplayDirectoryName, isDefault, mappedFaceFile)); + results.Add(new(personKeyFormatted, directoryNumber, personDisplayDirectoryName, isDefault, filePath)); } return results; } @@ -256,7 +263,7 @@ internal abstract class DistanceLogic Directory.Move(personKeyDirectory, newestPersonKeyDirectory); } - internal static List DeleteEmptyDirectoriesAndGetCollection(Configuration configuration, long ticks, string eDistanceContentDirectory, ReadOnlyDictionary personKeyFormattedToNewestPersonKeyFormatted, ReadOnlyCollection personKeyFormattedCollection) + internal static List DeleteEmptyDirectoriesAndGetCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, string eDistanceContentDirectory, ReadOnlyDictionary personKeyFormattedToNewestPersonKeyFormatted, ReadOnlyCollection personKeyFormattedCollection) { List results = []; bool check; @@ -271,9 +278,9 @@ internal abstract class DistanceLogic ProgressBar progressBar; string[] yearDirectories; string personKeyFormatted; + List distinct = []; string? personFirstInitial; bool isReservedDirectoryName; - List distinct = []; string[] personNameDirectories; string? newestPersonKeyFormatted; string? personDisplayDirectoryName; @@ -331,7 +338,7 @@ internal abstract class DistanceLogic isDefault = null; personDisplayDirectoryName = null; files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly); - results.AddRange(GetRecords(configuration, isDefault, files, directoryNumber, personKeyFormatted, distinct, personDisplayDirectoryName)); + results.AddRange(GetRecords(propertyConfiguration, configuration, isDefault, files, directoryNumber, personKeyFormatted, distinct, personDisplayDirectoryName)); files = Directory.GetFiles(yearDirectory, "*.lnk", SearchOption.AllDirectories); foreach (string file in files) File.Delete(file); @@ -403,7 +410,7 @@ internal abstract class DistanceLogic else { personFirstInitial = personDisplayDirectoryName[..1]; - if (personFirstInitial.All(l => char.IsDigit(l))) + if (personFirstInitial.All(char.IsDigit)) { foreach (string file in files) File.Delete(file); @@ -419,7 +426,7 @@ internal abstract class DistanceLogic Directory.Move(personNameDirectory, personFirstInitialDirectory); files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); } - results.AddRange(GetRecords(configuration, isDefault, files, directoryNumber, personKeyFormatted, distinct, personDisplayDirectoryName)); + results.AddRange(GetRecords(propertyConfiguration, configuration, isDefault, files, directoryNumber, personKeyFormatted, distinct, personDisplayDirectoryName)); personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string personNameLinkDirectory in personNameLinkDirectories) { diff --git a/Map/Models/Stateless/LookForAbandonedLogic.cs b/Map/Models/Stateless/LookForAbandonedLogic.cs index 466b756..2d16a3d 100644 --- a/Map/Models/Stateless/LookForAbandonedLogic.cs +++ b/Map/Models/Stateless/LookForAbandonedLogic.cs @@ -1,3 +1,4 @@ +using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Stateless.Methods; namespace View_by_Distance.Map.Models.Stateless; @@ -7,21 +8,20 @@ internal abstract class LookForAbandonedLogic internal static void LookForAbandoned(Property.Models.Configuration propertyConfiguration, List distinctFilteredIds, string directory, string directoryName) { - string fileNameWithoutExtension; - bool nameWithoutExtensionIsIdFormat; + FilePath filePath; + FileHolder fileHolder; + string fileNameFirstSegment; List renameCollection = []; - bool nameWithoutExtensionIsPaddedIdFormat; - short sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex(propertyConfiguration.Offset); string[] distinctFilteredIdsValues = distinctFilteredIds.Select(l => l.ToString()).ToArray(); string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories); foreach (string file in files) { - fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(file))); - nameWithoutExtensionIsIdFormat = IProperty.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension); - nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileNameWithoutExtension, sortOrderOnlyLengthIndex); - if (!nameWithoutExtensionIsIdFormat && !nameWithoutExtensionIsPaddedIdFormat) + fileHolder = IFileHolder.Get(file); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); + fileNameFirstSegment = fileHolder.NameWithoutExtension.Split('.')[0]; + if (!filePath.IsIntelligentIdFormat && filePath.SortOrder is null) continue; - if (distinctFilteredIdsValues.Contains(fileNameWithoutExtension)) + if (distinctFilteredIdsValues.Contains(fileNameFirstSegment)) continue; renameCollection.Add(file); } diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index 0fb060d..193bf3d 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -17,66 +17,67 @@ internal abstract class MapLogic string PersonKeyFormatted, string? PersonDisplayDirectoryName, int? DirectoryNumber, - string File); + FilePath FilePath); internal record Duplicate(long PersonKey, int Id, - string File, + FilePath FilePath, float? Percent); internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted, string? PersonDisplayDirectoryName, bool? IsDefault, - string MappedFaceFile, + FilePath MappedFaceFilePath, int Id, int WholePercentages); internal static void SetSkipCollections(Configuration configuration, ReadOnlyCollection personContainers, string? a2PeopleSingletonDirectory, Dictionary> skipCollection, Dictionary> skipNotSkipCollection) { - int? id; - string fileName; string checkFile; int? wholePercentages; + List distinct = []; List distinctFiles = []; List distinctFileName = []; bool skipNotSkipDirectoriesAny = configuration.SkipNotSkipDirectories.Length > 0; string[] checkDirectories = (from l in configuration.SkipNotSkipDirectories select Path.GetFullPath($"{a2PeopleSingletonDirectory}{l}")).ToArray(); foreach (PersonContainer personContainer in personContainers) { - foreach (string personDisplayDirectoryAllFile in personContainer.DisplayDirectoryAllFiles) + foreach (FilePath personDisplayDirectoryAllFilePath in personContainer.DisplayDirectoryAllFilePaths) { - if (!personDisplayDirectoryAllFile.EndsWith(configuration.FacesFileNameExtension)) + if (personDisplayDirectoryAllFilePath.ExtensionLowered != configuration.FacesFileNameExtension) continue; - if (distinctFiles.Contains(personDisplayDirectoryAllFile)) + if (distinctFiles.Contains(personDisplayDirectoryAllFilePath.FullName)) continue; - distinctFiles.Add(personDisplayDirectoryAllFile); + distinctFiles.Add(personDisplayDirectoryAllFilePath.FullName); + distinct.Add(personDisplayDirectoryAllFilePath); } } - foreach (string distinctFile in distinctFiles) + foreach (FilePath filePath in distinct) { - fileName = Path.GetFileName(distinctFile); - if (distinctFileName.Contains(fileName)) + if (distinctFileName.Contains(filePath.Name)) { - checkFile = $"{distinctFile}.dup"; + checkFile = $"{filePath.FullName}.dup"; if (File.Exists(checkFile)) continue; - File.Move(distinctFile, checkFile); + File.Move(filePath.FullName, checkFile); continue; } - (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, distinctFile); - if (id is null || wholePercentages is null) + if (filePath.Id is null) continue; - if (!skipNotSkipDirectoriesAny || !checkDirectories.Any(l => distinctFile.StartsWith(l))) + wholePercentages = IMapping.GetWholePercentages(configuration.FacesFileNameExtension, filePath); + if (wholePercentages is null) + continue; + if (!skipNotSkipDirectoriesAny || !checkDirectories.Any(l => filePath.FullName.StartsWith(l))) { - if (!skipCollection.ContainsKey(id.Value)) - skipCollection.Add(id.Value, []); - skipCollection[id.Value].Add((distinctFile, wholePercentages.Value)); + if (!skipCollection.ContainsKey(filePath.Id.Value)) + skipCollection.Add(filePath.Id.Value, []); + skipCollection[filePath.Id.Value].Add((filePath.FullName, wholePercentages.Value)); } else { - if (!skipNotSkipCollection.ContainsKey(id.Value)) - skipNotSkipCollection.Add(id.Value, []); - skipNotSkipCollection[id.Value].Add((distinctFile, wholePercentages.Value)); + if (!skipNotSkipCollection.ContainsKey(filePath.Id.Value)) + skipNotSkipCollection.Add(filePath.Id.Value, []); + skipNotSkipCollection[filePath.Id.Value].Add((filePath.FullName, wholePercentages.Value)); } } } @@ -96,8 +97,7 @@ internal abstract class MapLogic if (personContainer.Birthdays.Length < 1) continue; newestPersonKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personContainer.Key.Value); - if (!personKeyFormattedToNewestPersonKeyFormatted.ContainsKey(personKeyFormatted)) - personKeyFormattedToNewestPersonKeyFormatted.Add(personKeyFormatted, newestPersonKeyFormatted); + _ = personKeyFormattedToNewestPersonKeyFormatted.TryAdd(personKeyFormatted, newestPersonKeyFormatted); } } } @@ -184,23 +184,21 @@ internal abstract class MapLogic private static List GetDisplayDirectoryAllFiles(string fileNameExtension, string personBirthdayFormat, ReadOnlyCollection personContainers) { List results = []; - string fileName; string personKeyFormatted; List distinct = []; foreach (PersonContainer personContainer in personContainers) { if (personContainer.Key is null) continue; - for (int i = personContainer.DisplayDirectoryAllFiles.Length - 1; i > -1; i--) + for (int i = personContainer.DisplayDirectoryAllFilePaths.Count - 1; i > -1; i--) { - if (!personContainer.DisplayDirectoryAllFiles[i].EndsWith(fileNameExtension)) + if (personContainer.DisplayDirectoryAllFilePaths[i].ExtensionLowered != fileNameExtension) continue; - fileName = Path.GetFileName(personContainer.DisplayDirectoryAllFiles[i]); - if (distinct.Contains(fileName)) + if (distinct.Contains(personContainer.DisplayDirectoryAllFilePaths[i].Name)) continue; - distinct.Add(fileName); + distinct.Add(personContainer.DisplayDirectoryAllFilePaths[i].Name); personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personContainer.Key.Value); - results.Add(new(personContainer.Key.Value, personKeyFormatted, personContainer.DisplayDirectoryName, null, personContainer.DisplayDirectoryAllFiles[i])); + results.Add(new(personContainer.Key.Value, personKeyFormatted, personContainer.DisplayDirectoryName, null, personContainer.DisplayDirectoryAllFilePaths[i])); } } return results; @@ -213,30 +211,30 @@ internal abstract class MapLogic { if (duplicate.Percent is null) continue; - _ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(duplicate.File), "\"")); + _ = Process.Start("explorer.exe", string.Concat("\"", duplicate.FilePath.DirectoryName, "\"")); personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, duplicate.PersonKey); } - foreach ((long personKey, int id, string file, float? percent) in duplicates) + foreach ((long personKey, int id, FilePath filePath, float? percent) in duplicates) { if (percent is not null && percent.Value == 0) continue; - _ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\"")); + _ = Process.Start("explorer.exe", string.Concat("\"", filePath.DirectoryName, "\"")); personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personKey); } - foreach ((long personKey, int id, string file, float? percent) in duplicates) + foreach ((long personKey, int id, FilePath filePath, float? percent) in duplicates) { if (percent is not null && percent.Value > 0) continue; - _ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\"")); + _ = Process.Start("explorer.exe", string.Concat("\"", filePath.DirectoryName, "\"")); personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personKey); } } - internal static string GetFacesDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dFacesContentDirectory, MappingFromItem mappingFromItem) + internal static string GetFacesDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dFacesContentDirectory, FilePath filePath, MappingFromItem mappingFromItem) { string result; - (string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, mappingFromItem.ImageFileHolder.NameWithoutExtension); - result = Path.Combine(dFacesContentDirectory, propertyConfiguration.ResultAllInOne, directoryName, mappingFromItem.ImageFileHolder.NameWithoutExtension); + (string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); + result = Path.Combine(dFacesContentDirectory, directoryName, mappingFromItem.ImageFileHolder.NameWithoutExtension); return result; } @@ -286,8 +284,7 @@ internal abstract class MapLogic personKeyToPersonContainerCollection.Add(personContainer.Key.Value, []); personKeyToPersonContainerCollection[personContainer.Key.Value].Add(personContainer); newestPersonKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personContainer.Key.Value); - if (!personKeyFormattedToPersonContainer.ContainsKey(newestPersonKeyFormatted)) - personKeyFormattedToPersonContainer.Add(newestPersonKeyFormatted, personContainer); + _ = personKeyFormattedToPersonContainer.TryAdd(newestPersonKeyFormatted, personContainer); } foreach (KeyValuePair> keyValuePair in personKeyToPersonContainerCollection) { @@ -379,7 +376,7 @@ internal abstract class MapLogic int? approximateYears = null; PersonBirthday personBirthday; PersonContainer personContainer; - string[] personDisplayDirectoryAllFiles = []; + List personDisplayDirectoryAllFilePaths = []; DateTime incrementDate = new(configuration.PersonBirthdayFirstYear, 1, 1); long oneHour = new DateTime(1, 1, 1, 1, 0, 0).Ticks - new DateTime(1, 1, 1).Ticks; for (int i = 0; i < int.MaxValue; i++) @@ -409,7 +406,7 @@ internal abstract class MapLogic if (check) continue; personBirthday = IPersonBirthday.GetPersonBirthday(personKey + (oneHour * 2)); - personContainer = new(approximateYears, [personBirthday], personDisplayDirectoryAllFiles, configuration.MappingDefaultName, personKey); + personContainer = new(approximateYears, [personBirthday], new(personDisplayDirectoryAllFilePaths), configuration.MappingDefaultName, personKey); results.Add(personContainer); if (results.Count > 99) break; @@ -429,13 +426,13 @@ internal abstract class MapLogic return result; } - private static List GetMappedFiles(Configuration configuration, ReadOnlyCollection personContainers, List records) + private static List GetMappedFiles(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, ReadOnlyCollection personContainers, List records) { List results = []; - string file; long personKey; - string fileName; string checkFile; + FilePath filePath; + FileHolder fileHolder; List distinct = []; PersonBirthday? personBirthday; results.AddRange(GetDisplayDirectoryAllFiles(configuration.FacesFileNameExtension, configuration.PersonBirthdayFormat, personContainers)); @@ -444,50 +441,66 @@ internal abstract class MapLogic personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, record.PersonKeyFormatted); if (personBirthday is null) continue; - fileName = Path.GetFileName(record.MappedFaceFile); - if (distinct.Contains(fileName)) + if (distinct.Contains(record.MappedFaceFilePath.Name)) continue; - distinct.Add(fileName); + distinct.Add(record.MappedFaceFilePath.Name); personKey = personBirthday.Value.Ticks; - results.Add(new(personKey, record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.DirectoryNumber, record.MappedFaceFile)); + results.Add(new(personKey, record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.DirectoryNumber, record.MappedFaceFilePath)); } for (int i = results.Count - 1; i > -1; i--) { - file = results[i].File; - if (file.EndsWith(".old")) + filePath = results[i].FilePath; + if (filePath.Name.EndsWith(".old")) { results.RemoveAt(i); continue; } - if (!file.EndsWith(".dup") && !file.EndsWith(".unk") && !file.EndsWith(".abd")) + if (!filePath.Name.EndsWith(".dup") && !filePath.Name.EndsWith(".unk") && !filePath.Name.EndsWith(".abd")) continue; - if (!File.Exists(file)) + if (!File.Exists(filePath.Name)) continue; - checkFile = file[..^4]; + checkFile = filePath.FullName[..^4]; if (File.Exists(checkFile)) continue; - File.Move(file, checkFile); - results[i] = new(results[i].PersonKey, results[i].PersonKeyFormatted, results[i].PersonDisplayDirectoryName, results[i].DirectoryNumber, file[..^4]); + File.Move(filePath.FullName, checkFile); + fileHolder = IFileHolder.Get(checkFile); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); + results[i] = new(results[i].PersonKey, results[i].PersonKeyFormatted, results[i].PersonDisplayDirectoryName, results[i].DirectoryNumber, filePath); } return results; } - private static void ParallelFor(Configuration configuration, Dictionary> skipCollection, List> locationContainers, MappedFile mappedFile) + private static void ParallelFor(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, Dictionary> skipCollection, List> locationContainers, MappedFile mappedFile) { + int? id; string checkFile; DateOnly dateOnly; + FilePath filePath; string[] fileMatches; + FileHolder fileHolder; + int? wholePercentages; const string lnk = ".lnk"; - int? id, wholePercentages; string personDisplayDirectoryName; const bool fromDistanceContent = true; IReadOnlyList directories; List<(string File, int WholePercentages)>? wholePercentagesCollection; - if (!mappedFile.File.EndsWith(lnk)) - (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFile.File); + if (!mappedFile.FilePath.Name.EndsWith(lnk)) + { + if (mappedFile.FilePath.Id is null) + return; + id = mappedFile.FilePath.Id; + wholePercentages = IMapping.GetWholePercentages(configuration.FacesFileNameExtension, mappedFile.FilePath); + } else - (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFile.File[..^4]); - if (id is null || wholePercentages is null) + { + fileHolder = IFileHolder.Get(mappedFile.FilePath.FullName[..^4]); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); + if (filePath.Id is null) + return; + id = filePath.Id; + wholePercentages = IMapping.GetWholePercentages(configuration.FacesFileNameExtension, filePath); + } + if (wholePercentages is null) return; if (string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory) && skipCollection.TryGetValue(id.Value, out wholePercentagesCollection)) { @@ -503,11 +516,11 @@ internal abstract class MapLogic continue; } } - dateOnly = DateOnly.FromDateTime(new FileInfo(mappedFile.File).CreationTime); - if (mappedFile.File.EndsWith(lnk) || (!configuration.DistanceMoveUnableToMatch && !configuration.DistanceRenameToMatch) || !File.Exists(mappedFile.File)) + dateOnly = DateOnly.FromDateTime(new DateTime(mappedFile.FilePath.CreationTicks)); + if (mappedFile.FilePath.Name.EndsWith(lnk) || (!configuration.DistanceMoveUnableToMatch && !configuration.DistanceRenameToMatch) || !File.Exists(mappedFile.FilePath.FullName)) directories = new List(); else - directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mappedFile.File); + directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mappedFile.FilePath.FullName); RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value); personDisplayDirectoryName = mappedFile.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : mappedFile.PersonDisplayDirectoryName; lock (locationContainers) @@ -515,7 +528,7 @@ internal abstract class MapLogic directories, mappedFile.DirectoryNumber, personDisplayDirectoryName, - mappedFile.File, + mappedFile.FilePath, fromDistanceContent, id.Value, null, @@ -529,11 +542,11 @@ internal abstract class MapLogic string key; float? percent; float itemPercentagesArea; - List delete = []; + List delete = []; List duplicates = []; RectangleF? itemPercentagesRectangle; - (string File, int WholePercentages) item; - Dictionary distinct = []; + (FilePath FilePath, int WholePercentages) item; + Dictionary distinct = []; foreach (LocationContainer locationContainer in locationContainers) { key = string.Concat(locationContainer.PersonKey, locationContainer.Id); @@ -549,12 +562,12 @@ internal abstract class MapLogic itemPercentagesArea = itemPercentagesRectangle.Value.Width * itemPercentagesRectangle.Value.Height; percent = ILocation.GetIntersectPercent(itemPercentagesRectangle.Value, itemPercentagesArea, locationContainer.Rectangle.Value); } - delete.Add(item.File); - delete.Add(locationContainer.File); - duplicates.Add(new(locationContainer.PersonKey, locationContainer.Id, locationContainer.File, percent)); + delete.Add(item.FilePath); + delete.Add(locationContainer.FilePath); + duplicates.Add(new(locationContainer.PersonKey, locationContainer.Id, locationContainer.FilePath, percent)); continue; } - distinct.Add(key, new(locationContainer.File, locationContainer.WholePercentages)); + distinct.Add(key, new(locationContainer.FilePath, locationContainer.WholePercentages)); } if (!configuration.DeletePossibleDuplicates && duplicates.Count > 0) OpenPossibleDuplicates(configuration, duplicates); @@ -562,10 +575,10 @@ internal abstract class MapLogic { if (delete.Count > 8) throw new Exception("Something maybe wrong!"); - foreach (string file in delete) + foreach (FilePath filePath in delete) { - if (File.Exists(file)) - File.Delete(file); + if (File.Exists(filePath.FullName)) + File.Delete(filePath.FullName); } } } @@ -584,10 +597,10 @@ internal abstract class MapLogic else { string checkFile = Path.Combine(directory, $"{keyMapping.MappingFromItem.ImageFileHolder.Name}{facePartsFileNameExtension}"); - result = new(checkFile, directory, new(facePartsContentCollectionFile)); + result = new(checkFile, directory, IFileHolder.Get(facePartsContentCollectionFile)); } - string facesDirectory = GetFacesDirectory(propertyConfiguration, dFacesContentDirectory, keyMapping.MappingFromItem); - FileHolder faceFileHolder = new(Path.Combine(facesDirectory, $"{keyMapping.MappingFromLocation.DeterministicHashCodeKey}{keyMapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}")); + string facesDirectory = GetFacesDirectory(propertyConfiguration, dFacesContentDirectory, keyMapping.FilePath, keyMapping.MappingFromItem); + FileHolder faceFileHolder = IFileHolder.Get(Path.Combine(facesDirectory, $"{keyMapping.MappingFromLocation.DeterministicHashCodeKey}{keyMapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}")); if (!faceFileHolder.Exists) saveContainer = null; else @@ -714,8 +727,7 @@ internal abstract class MapLogic } if (personContainer.Key is null) throw new Exception(); - if (!personKeyToCount.ContainsKey(personContainer.Key.Value)) - personKeyToCount.Add(personContainer.Key.Value, 0); + _ = personKeyToCount.TryAdd(personContainer.Key.Value, 0); personKeyToCount[personContainer.Key.Value]++; possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Add(new(personKeyFormattedIdThenWholePercentages, personContainer)); } @@ -731,29 +743,30 @@ internal abstract class MapLogic return results; } - internal static ReadOnlyCollection GetPersonKeyFormattedIdThenWholePercentages(Configuration configuration, long ticks, List collection) + internal static ReadOnlyCollection GetPersonKeyFormattedIdThenWholePercentages(Configuration configuration, long ticks, List records) { List results = []; - int? id; int? wholePercentages; List wholePercentagesCollection; Dictionary> idToWholePercentagesCollection = []; int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); - string message = $") {collection.Count:000} join from ticks Director(ies) - C - {totalSeconds} total second(s)"; + string message = $") {records.Count:000} join from ticks Director(ies) - C - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; - using ProgressBar progressBar = new(collection.Count, message, options); - foreach (Record record in collection) + using ProgressBar progressBar = new(records.Count, message, options); + foreach (Record record in records) { progressBar.Tick(); - (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, record.MappedFaceFile); - if (id is null || wholePercentages is null) + if (record.MappedFaceFilePath.Id is null) continue; - if (!idToWholePercentagesCollection.ContainsKey(id.Value)) - idToWholePercentagesCollection.Add(id.Value, []); - wholePercentagesCollection = idToWholePercentagesCollection[id.Value]; + wholePercentages = IMapping.GetWholePercentages(configuration.FacesFileNameExtension, record.MappedFaceFilePath); + if (wholePercentages is null) + continue; + if (!idToWholePercentagesCollection.ContainsKey(record.MappedFaceFilePath.Id.Value)) + idToWholePercentagesCollection.Add(record.MappedFaceFilePath.Id.Value, []); + wholePercentagesCollection = idToWholePercentagesCollection[record.MappedFaceFilePath.Id.Value]; wholePercentagesCollection.Add(wholePercentages.Value); - idToWholePercentagesCollection[id.Value].Add(wholePercentages.Value); - results.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.IsDefault, record.MappedFaceFile, id.Value, wholePercentages.Value)); + idToWholePercentagesCollection[record.MappedFaceFilePath.Id.Value].Add(wholePercentages.Value); + results.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.IsDefault, record.MappedFaceFilePath, record.MappedFaceFilePath.Id.Value, wholePercentages.Value)); } return new(results); } @@ -801,16 +814,17 @@ internal abstract class MapLogic int? approximateYears = null; PersonBirthday? personBirthday; PersonContainer personContainer; + List? collection; displayDirectoryName = configuration.MappingDefaultName; foreach (KeyValuePair keyValuePair in personKeyToCount) { if (personKeyToPersonContainer.ContainsKey(keyValuePair.Key)) continue; personBirthday = IPersonBirthday.GetPersonBirthday(keyValuePair.Key); - if (!personKeyToPersonContainerCollection.ContainsKey(keyValuePair.Key)) + if (!personKeyToPersonContainerCollection.TryGetValue(keyValuePair.Key, out collection)) personContainer = new(approximateYears, personBirthday, displayDirectoryName, keyValuePair.Key); else - personContainer = new(approximateYears, personBirthday, personKeyToPersonContainerCollection[keyValuePair.Key][zero].PersonDirectory, displayDirectoryName, keyValuePair.Key); + personContainer = new(approximateYears, personBirthday, collection[zero].PersonDirectory, displayDirectoryName, keyValuePair.Key); personKeyToPersonContainer.Add(keyValuePair.Key, personContainer); } } @@ -825,8 +839,8 @@ internal abstract class MapLogic string checkFile; const int zero = 0; string personKeyFormatted; - string[] deleteCollection; List distinct = []; + FilePath[] deleteCollection; PersonBirthday personBirthday; string personDisplayDirectory; DateTime dateTime = new(ticks); @@ -837,49 +851,49 @@ internal abstract class MapLogic continue; if (a2PeopleSingletonDirectory is null || personContainer.Key is null || personContainer.Birthdays is null || personContainer.PersonDirectory is null || personContainer.Birthdays.Length == 0) continue; - fileName = $"{Path.GetFileName(personKeyFormattedIdThenWholePercentages.MappedFaceFile)}{configuration.FacesHiddenFileNameExtension}"; + fileName = $"{Path.GetFileName(personKeyFormattedIdThenWholePercentages.MappedFaceFilePath.FullName)}{configuration.FacesHiddenFileNameExtension}"; personBirthday = personContainer.Birthdays[zero]; personKey = personBirthday.Value.Ticks; personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personBirthday); personDisplayDirectory = Path.Combine(a2PeopleSingletonDirectory, personContainer.PersonDirectory.Char.ToString(), personContainer.PersonDirectory.Group, personContainer.DisplayDirectoryName); personKeyFormattedDirectory = Path.GetFullPath(Path.Combine(personDisplayDirectory, personKeyFormatted)); - deleteCollection = (from l in personContainer.DisplayDirectoryAllFiles where l.StartsWith(personKeyFormattedDirectory) select l).ToArray(); - if (personContainer.DisplayDirectoryAllFiles.Length != 0 && deleteCollection.Length == 0) + deleteCollection = (from l in personContainer.DisplayDirectoryAllFilePaths where l.FullName.StartsWith(personKeyFormattedDirectory) select l).ToArray(); + if (personContainer.DisplayDirectoryAllFilePaths.Count != 0 && deleteCollection.Length == 0) throw new NotSupportedException(); if (!Directory.Exists(personKeyFormattedDirectory)) _ = Directory.CreateDirectory(personKeyFormattedDirectory); _ = readOnlyPersonKeyToCount.TryGetValue(personKey, out count); _ = Directory.CreateDirectory(Path.Combine(personDisplayDirectory, count.ToString("0000"))); Directory.SetLastWriteTime(personDisplayDirectory, dateTime.AddMinutes(count)); - matches = (from l in personContainer.DisplayDirectoryAllFiles where l.EndsWith(fileName) select true).ToArray(); + matches = (from l in personContainer.DisplayDirectoryAllFilePaths where l.FullName.EndsWith(fileName) select true).ToArray(); if (matches.Length > 0) continue; - matches = (from l in personContainer.DisplayDirectoryAllFiles where l.EndsWith(configuration.FacesHiddenFileNameExtension) select true).ToArray(); + matches = (from l in personContainer.DisplayDirectoryAllFilePaths where l.FullName.EndsWith(configuration.FacesHiddenFileNameExtension) select true).ToArray(); if (matches.Length > 0) continue; - if (!File.Exists(personKeyFormattedIdThenWholePercentages.MappedFaceFile)) + if (!File.Exists(personKeyFormattedIdThenWholePercentages.MappedFaceFilePath.FullName)) continue; - checkFile = Path.Combine(personKeyFormattedDirectory, $"{Path.GetFileName(personKeyFormattedIdThenWholePercentages.MappedFaceFile)}{configuration.FacesHiddenFileNameExtension}"); + checkFile = Path.Combine(personKeyFormattedDirectory, $"{Path.GetFileName(personKeyFormattedIdThenWholePercentages.MappedFaceFilePath.FullName)}{configuration.FacesHiddenFileNameExtension}"); if (File.Exists(checkFile)) continue; - File.Copy(personKeyFormattedIdThenWholePercentages.MappedFaceFile, checkFile); - foreach (string delete in deleteCollection) + File.Copy(personKeyFormattedIdThenWholePercentages.MappedFaceFilePath.FullName, checkFile); + foreach (FilePath delete in deleteCollection) { - if (delete.EndsWith(".lnk")) + if (delete.ExtensionLowered == ".lnk") continue; - if (!File.Exists(delete)) + if (!File.Exists(delete.FullName)) continue; - File.Delete(delete); + File.Delete(delete.FullName); } Directory.SetLastWriteTime(personDisplayDirectory, DateTime.Now); distinct.Add(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted); } } - internal static List> GetLocationContainers(int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection personContainers, Dictionary> skipCollection, List records) + internal static List> GetLocationContainers(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection personContainers, Dictionary> skipCollection, List records) { List> results = []; - List mappedFiles = GetMappedFiles(configuration, personContainers, records); + List mappedFiles = GetMappedFiles(propertyConfiguration, configuration, personContainers, records); if (mappedFiles.Count > 0 && (configuration.DistanceMoveUnableToMatch || configuration.DistanceRenameToMatch)) { int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); @@ -890,7 +904,7 @@ internal abstract class MapLogic _ = Parallel.For(0, mappedFiles.Count, parallelOptions, (i, state) => { progressBar.Tick(); - ParallelFor(configuration, skipCollection, results, mappedFiles[i]); + ParallelFor(propertyConfiguration, configuration, skipCollection, results, mappedFiles[i]); }); } if (string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory)) @@ -904,33 +918,27 @@ internal abstract class MapLogic internal static int CopyManualFiles(Configuration configuration, long ticks, ReadOnlyCollection personContainers, string eDistanceContentTicksDirectory) { int result = 0; - string fileName; string checkFile; - string? directory; string dateDirectory; string directoryName; string checkDirectory; string personKeyFormatted; - PersonBirthday personBirthday; List distinct = []; + PersonBirthday personBirthday; DateTime dateTime = new(ticks); string by = nameof(Shared.Models.Stateless.IMapLogic.ManualCopy); foreach (PersonContainer personContainer in personContainers) { if (personContainer.Key is null) continue; - for (int i = personContainer.DisplayDirectoryAllFiles.Length - 1; i > -1; i--) + for (int i = personContainer.DisplayDirectoryAllFilePaths.Count - 1; i > -1; i--) { - if (!personContainer.DisplayDirectoryAllFiles[i].EndsWith(configuration.FacesFileNameExtension)) + if (personContainer.DisplayDirectoryAllFilePaths[i].ExtensionLowered != configuration.FacesFileNameExtension) continue; - fileName = Path.GetFileName(personContainer.DisplayDirectoryAllFiles[i]); - if (distinct.Contains(fileName)) + if (distinct.Contains(personContainer.DisplayDirectoryAllFilePaths[i].Name)) continue; - distinct.Add(fileName); - directory = Path.GetDirectoryName(personContainer.DisplayDirectoryAllFiles[i]); - if (string.IsNullOrEmpty(directory)) - continue; - directoryName = Path.GetFileName(directory); + distinct.Add(personContainer.DisplayDirectoryAllFilePaths[i].Name); + directoryName = Path.GetFileName(personContainer.DisplayDirectoryAllFilePaths[i].DirectoryName); if (directoryName != personContainer.DisplayDirectoryName) continue; personBirthday = IPersonBirthday.GetPersonBirthday(personContainer.Key.Value); @@ -939,12 +947,13 @@ internal abstract class MapLogic checkDirectory = Path.Combine(dateDirectory, personContainer.DisplayDirectoryName); if (!Directory.Exists(checkDirectory)) _ = Directory.CreateDirectory(checkDirectory); - checkFile = Path.Combine(dateDirectory, fileName); + checkFile = Path.Combine(dateDirectory, personContainer.DisplayDirectoryAllFilePaths[i].Name); if (File.Exists(checkFile)) continue; - File.Move(personContainer.DisplayDirectoryAllFiles[i], checkFile); - personContainer.DisplayDirectoryAllFiles[i] = string.Empty; - result++; + File.Move(personContainer.DisplayDirectoryAllFilePaths[i].FullName, checkFile); + throw new NotImplementedException("readonly null?"); + // personContainer.DisplayDirectoryAllFilePaths[i] = null; + // result++; } } return result; @@ -961,11 +970,11 @@ internal abstract class MapLogic return result; } - internal static string GetFacePartsDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string d2FacePartsContentDirectory, MappingFromItem mappingFromItem) + internal static string GetFacePartsDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string d2FacePartsContentDirectory, FilePath filePath, MappingFromItem mappingFromItem) { string result; - (string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, mappingFromItem.ImageFileHolder.NameWithoutExtension); - result = Path.Combine(d2FacePartsContentDirectory, propertyConfiguration.ResultAllInOne, directoryName, mappingFromItem.ImageFileHolder.NameWithoutExtension); + (string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); + result = Path.Combine(d2FacePartsContentDirectory, directoryName, mappingFromItem.ImageFileHolder.NameWithoutExtension); return result; } @@ -975,7 +984,7 @@ internal abstract class MapLogic string shortcutFile; if (sortingContainer?.Source.MappingFromLocation is null) throw new NullReferenceException(nameof(sortingContainer.Source.MappingFromLocation)); - FileHolder faceFileHolder = new($"C:/{sortingContainer.Sorting.Id}.{sortingContainer.Sorting.WholePercentages}"); + FileHolder faceFileHolder = IFileHolder.Get($"C:/{sortingContainer.Sorting.Id}.{sortingContainer.Sorting.WholePercentages}"); if (keyMapping.MappingFromPerson is not null && keyMapping.MappingFromLocation is not null) shortcutFile = Path.Combine(directory, $"{keyMapping.MappingFromLocation.DeterministicHashCodeKey}{keyMapping.MappingFromItem.ImageFileHolder.ExtensionLowered}.{sortingContainer.Sorting.DistancePermyriad}.lnk"); else diff --git a/Map/Models/Stateless/RelationLogic.cs b/Map/Models/Stateless/RelationLogic.cs index b67d403..29e4c13 100644 --- a/Map/Models/Stateless/RelationLogic.cs +++ b/Map/Models/Stateless/RelationLogic.cs @@ -19,7 +19,7 @@ internal abstract class RelationLogic { if (!locationContainer.FromDistanceContent) continue; - if (!locationContainer.File.Contains(configuration.LocationContainerDirectoryPattern)) + if (!locationContainer.FilePath.FullName.Contains(configuration.LocationContainerDirectoryPattern)) continue; if (!personKeyTo.TryGetValue(locationContainer.PersonKey, out yearTo)) { @@ -312,9 +312,9 @@ internal abstract class RelationLogic { lines.Clear(); if (movedFiles.TryGetValue(relationFileHolder.FullName, out file)) - fileHolder = new(file); + fileHolder = IFileHolder.Get(file); else - fileHolder = new(relationFileHolder.FullName); + fileHolder = IFileHolder.Get(relationFileHolder.FullName); if (!relationFileHolder.Exists || relationFileHolder.CreationTime is null) continue; if (isCounterPersonYear) @@ -344,9 +344,9 @@ internal abstract class RelationLogic { relation = relations[i]; if (movedFiles.TryGetValue(relation.File, out file)) - fileHolder = new(file); + fileHolder = IFileHolder.Get(file); else - fileHolder = new(relation.File); + fileHolder = IFileHolder.Get(relation.File); if (!fileHolder.Exists || fileHolder.CreationTime is null) continue; fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileHolder.NameWithoutExtension); diff --git a/Metadata/Models/B_Metadata.cs b/Metadata/Models/B_Metadata.cs index 668bf23..7e7b290 100644 --- a/Metadata/Models/B_Metadata.cs +++ b/Metadata/Models/B_Metadata.cs @@ -16,7 +16,7 @@ public class B_Metadata : IMetadata private readonly bool _PropertiesChangedForMetadata; private readonly IPropertyConfiguration _PropertyConfiguration; private readonly bool _ForceMetadataLastWriteTimeToCreationTime; - private readonly IReadOnlyDictionary _FileGroups; + private readonly ReadOnlyDictionary _FileGroups; private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; public B_Metadata(IPropertyConfiguration propertyConfiguration) @@ -43,12 +43,12 @@ public class B_Metadata : IMetadata return result; } - public ReadOnlyDictionary GetMetadataCollection(List> subFileTuples, List parseExceptions, string[] changesFrom, MappingFromItem mappingFromItem) + public ReadOnlyDictionary GetMetadataCollection(FilePath filePath, List> subFileTuples, List parseExceptions, string[] changesFrom, MappingFromItem mappingFromItem) { Dictionary? results = null; string json = string.Empty; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration.ResultAllInOneSubdirectoryLength, mappingFromItem.ImageFileHolder.Name); + (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); FileInfo fileInfo = new(Path.Combine(_FileGroups[_PropertyConfiguration.ResultSingleton][directoryIndex], $"{mappingFromItem.ImageFileHolder.NameWithoutExtension}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json")); if (_ForceMetadataLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) { diff --git a/Move-By-Id/MoveById.cs b/Move-By-Id/MoveById.cs index 5b5f282..666d20e 100644 --- a/Move-By-Id/MoveById.cs +++ b/Move-By-Id/MoveById.cs @@ -6,7 +6,6 @@ using System.Text; using View_by_Distance.Move.By.Id.Models; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Methods; -using View_by_Distance.Shared.Models.Stateless.Methods; namespace View_by_Distance.Move.By.Id; @@ -105,31 +104,28 @@ public class MoveById int? id; string? message; string[] matches; + FilePath filePath; FileHolder fileHolder; bool isIgnoreExtension; const string jpeg = ".jpeg"; bool isValidImageFormatExtension; ASCIIEncoding asciiEncoding = new(); - bool nameWithoutExtensionIsIdFormat; - bool nameWithoutExtensionIsPaddedIdFormat; - short sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex(_PropertyConfiguration.Offset); foreach (string file in allFiles) { progressBar.Tick(); - fileHolder = new(file); + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(file); + filePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: null); if (fileHolder.ExtensionLowered == ".id" || fileHolder.DirectoryName is null) continue; if (allFiles.Contains($"{fileHolder.FullName}.id")) continue; isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered); - nameWithoutExtensionIsIdFormat = Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(fileHolder); isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered); - nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileHolder, sortOrderOnlyLengthIndex); if (!isIgnoreExtension && !isValidImageFormatExtension) { if (fileHolder.ExtensionLowered == jpeg) continue; - if (nameWithoutExtensionIsIdFormat || nameWithoutExtensionIsPaddedIdFormat) + if (filePath.IsIntelligentIdFormat || filePath.SortOrder is not null) continue; } (_, _, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding); diff --git a/Offset-Date-Time-Original/OffsetDateTimeOriginal.cs b/Offset-Date-Time-Original/OffsetDateTimeOriginal.cs index bdc55aa..ac5bac4 100644 --- a/Offset-Date-Time-Original/OffsetDateTimeOriginal.cs +++ b/Offset-Date-Time-Original/OffsetDateTimeOriginal.cs @@ -83,7 +83,7 @@ public class OffsetDateTimeOriginal string[] files = Directory.GetFiles(checkDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string file in files) { - fileHolder = new(file); + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(file); isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered); isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered); (dateTimeOriginal, dateTimes, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding); @@ -193,8 +193,8 @@ public class OffsetDateTimeOriginal bool targetIsIgnoreExtension; DateTime? badDateTimeOriginal; DateTime? targetDateTimeOriginal; - FileHolder badFileHolder = new(badFiles.First()); - FileHolder targetFileHolder = new(targetFiles.First()); + FileHolder badFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(badFiles.First()); + FileHolder targetFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(targetFiles.First()); bool badIsValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(badFileHolder.ExtensionLowered); bool targetIsValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(targetFileHolder.ExtensionLowered); badIsIgnoreExtension = badIsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(badFileHolder.ExtensionLowered); diff --git a/Property/Models/A_Property.cs b/Property/Models/A_Property.cs index 46b5d8c..6a63215 100644 --- a/Property/Models/A_Property.cs +++ b/Property/Models/A_Property.cs @@ -1,4 +1,5 @@ using ShellProgressBar; +using System.Collections.ObjectModel; using System.Text; using System.Text.Json; using View_by_Distance.Property.Models.Stateless; @@ -21,7 +22,7 @@ public class A_Property private readonly Configuration _Configuration; private readonly List _AngleBracketCollection; private readonly IPropertyConfiguration _PropertyConfiguration; - private readonly IReadOnlyDictionary _FileGroups; + private readonly ReadOnlyDictionary _FileGroups; public A_Property(int maxDegreeOfParallelism, Configuration propertyConfiguration, string outputExtension, bool reverse, string aResultsFullGroupDirectory) { @@ -56,7 +57,7 @@ public class A_Property fileInfo = new(Path.Combine(angleBracket.Replace("<>", _PropertyConfiguration.ResultSingleton), $"{item.ImageFileHolder.NameWithoutExtension}{item.ImageFileHolder.ExtensionLowered}.json")); else { - (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration.ResultAllInOneSubdirectoryLength, item.ImageFileHolder.Name); + (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, item.FilePath); fileInfo = new(Path.Combine(_FileGroups[_PropertyConfiguration.ResultSingleton][directoryIndex], $"{item.ImageFileHolder.NameWithoutExtension}{item.ImageFileHolder.ExtensionLowered}.json")); } List dateTimes = (from l in sourceDirectoryFileTuples where l is not null && changesFrom.Contains(l.Item1) select l.Item2).ToList(); @@ -133,7 +134,7 @@ public class A_Property } if (result is null) { - id ??= item.ImageFileHolder.Id; + id ??= item.FilePath.Id; (_, _, result) = Stateless.Property.GetProperty(populateId, metadata, item.ImageFileHolder, result, isIgnoreExtension, item.IsValidImageFormatExtension, id, _ASCIIEncoding); json = JsonSerializer.Serialize(result, PropertyGenerationContext.Default.Property); if (populateId && Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true)) diff --git a/Property/Models/Binder/Configuration.cs b/Property/Models/Binder/Configuration.cs index 77db900..21fa898 100644 --- a/Property/Models/Binder/Configuration.cs +++ b/Property/Models/Binder/Configuration.cs @@ -12,6 +12,7 @@ public class Configuration public bool? ForcePropertyLastWriteTimeToCreationTime { get; set; } public string[]? IgnoreExtensions { get; set; } public string[]? IgnoreRulesKeyWords { get; set; } + public int? IntMinValueLength { get; set; } public int? MaxImagesInDirectoryForTopLevelFirstPass { get; set; } public string? ModelName { init; get; } public int? NumberOfJitters { init; get; } @@ -47,6 +48,7 @@ public class Configuration if (configuration.ForcePropertyLastWriteTimeToCreationTime is null) throw new NullReferenceException(nameof(configuration.ForcePropertyLastWriteTimeToCreationTime)); if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); if (configuration.IgnoreRulesKeyWords is null) throw new NullReferenceException(nameof(configuration.IgnoreRulesKeyWords)); + if (configuration.IntMinValueLength is null) throw new NullReferenceException(nameof(configuration.IntMinValueLength)); if (configuration.MaxImagesInDirectoryForTopLevelFirstPass is null) throw new NullReferenceException(nameof(configuration.MaxImagesInDirectoryForTopLevelFirstPass)); // if (configuration.ModelName is null) throw new NullReferenceException(nameof(configuration.ModelName)); // if (configuration.NumberOfJitters is null) throw new NullReferenceException(nameof(configuration.NumberOfJitters)); @@ -71,6 +73,7 @@ public class Configuration configuration.ForcePropertyLastWriteTimeToCreationTime.Value, configuration.IgnoreExtensions, configuration.IgnoreRulesKeyWords, + configuration.IntMinValueLength.Value, configuration.MaxImagesInDirectoryForTopLevelFirstPass.Value, configuration.ModelName, configuration.NumberOfJitters, diff --git a/Property/Models/Configuration.cs b/Property/Models/Configuration.cs index 804f1f0..51d72cd 100644 --- a/Property/Models/Configuration.cs +++ b/Property/Models/Configuration.cs @@ -15,6 +15,7 @@ public class Configuration : Shared.Models.Properties.IPropertyConfiguration public bool ForcePropertyLastWriteTimeToCreationTime { init; get; } public string[] IgnoreExtensions { init; get; } public string[] IgnoreRulesKeyWords { init; get; } + public int IntMinValueLength { init; get; } public int MaxImagesInDirectoryForTopLevelFirstPass { init; get; } public string? ModelName { init; get; } public int? NumberOfJitters { init; get; } @@ -39,6 +40,7 @@ public class Configuration : Shared.Models.Properties.IPropertyConfiguration bool forcePropertyLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRulesKeyWords, + int intMinValueLength, int maxImagesInDirectoryForTopLevelFirstPass, string? modelName, int? numberOfJitters, @@ -64,6 +66,7 @@ public class Configuration : Shared.Models.Properties.IPropertyConfiguration ForcePropertyLastWriteTimeToCreationTime = forcePropertyLastWriteTimeToCreationTime; IgnoreExtensions = ignoreExtensions; IgnoreRulesKeyWords = ignoreRulesKeyWords; + IntMinValueLength = intMinValueLength; MaxImagesInDirectoryForTopLevelFirstPass = maxImagesInDirectoryForTopLevelFirstPass; ModelName = modelName; NumberOfJitters = numberOfJitters; diff --git a/Property/Models/Stateless/IProperty.cs b/Property/Models/Stateless/IProperty.cs index 0903cd6..2b000d6 100644 --- a/Property/Models/Stateless/IProperty.cs +++ b/Property/Models/Stateless/IProperty.cs @@ -13,11 +13,6 @@ public interface IProperty static string DateTimeFormat() => "yyyy:MM:dd HH:mm:ss"; - int TestStatic_GetDeterministicHashCode(byte[] value) => - GetDeterministicHashCode(value); - static int GetDeterministicHashCode(byte[] value) => - Property.GetDeterministicHashCode(value); - byte[] TestStatic_GetBytes(string value) => GetBytes(value); static byte[] GetBytes(string value) => diff --git a/Property/Models/Stateless/Property.cs b/Property/Models/Stateless/Property.cs index fdee708..127b836 100644 --- a/Property/Models/Stateless/Property.cs +++ b/Property/Models/Stateless/Property.cs @@ -139,25 +139,6 @@ internal partial class Property return results; } - internal static int GetDeterministicHashCode(byte[] value) - { - int result; - unchecked - { - int hash1 = (5381 << 16) + 5381; - int hash2 = hash1; - for (int i = 0; i < value.Length; i += 2) - { - hash1 = ((hash1 << 5) + hash1) ^ value[i]; - if (i == value.Length - 1) - break; - hash2 = ((hash2 << 5) + hash2) ^ value[i + 1]; - } - result = hash1 + (hash2 * 1566083941); - } - return result; - } - #pragma warning disable CA1416 internal static PropertyItem GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value) @@ -260,7 +241,7 @@ internal partial class Property bytes = new byte[length]; Marshal.Copy(intPtr, bytes, 0, length); bitmap.UnlockBits(bitmapData); - id ??= GetDeterministicHashCode(bytes); + id ??= Shared.Models.Stateless.Methods.IId.GetDeterministicHashCode(bytes); } dateTimeFormat = IProperty.DateTimeFormat(); if (image.PropertyIdList.Contains((int)IExif.Tags.DateTime)) diff --git a/Rename/Rename.cs b/Rename/Rename.cs index c22e857..747407f 100644 --- a/Rename/Rename.cs +++ b/Rename/Rename.cs @@ -127,17 +127,16 @@ public class Rename } if (records.Count != 0) { - int intMinValueLength = int.MinValue.ToString().Length; foreach (Record record in records) { if (record.Id is null) continue; - if (intMinValueLength < record.Id.Value.ToString().Length) + if (_PropertyConfiguration.IntMinValueLength < record.Id.Value.ToString().Length) throw new NotSupportedException(); } - message = $"{intMinValueLength}) comparing records"; + message = $"{_PropertyConfiguration.IntMinValueLength}) comparing records"; progressBar = new(records.Count, message, options); - toDoCollection.AddRange(GetToDoCollection(progressBar, nefPresent, records, intMinValueLength)); + toDoCollection.AddRange(GetToDoCollection(progressBar, nefPresent, records)); progressBar.Dispose(); } foreach ((FileHolder fileHolder, string directory, string to) in toDoCollection) @@ -204,7 +203,7 @@ public class Rename if (distinct.Contains(lines[1])) continue; distinct.Add(lines[1]); - fileHolder = new(lines[0]); + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(lines[0]); results.Add(new(fileHolder, directory, lines[1])); } return results; @@ -216,6 +215,7 @@ public class Rename int? id; string? message; string? directory; + FilePath filePath; DateTime[] dateTimes; FileHolder fileHolder; string[]? ffmpegFiles; @@ -223,26 +223,22 @@ public class Rename DateTime? dateTimeOriginal; bool isValidImageFormatExtension; ASCIIEncoding asciiEncoding = new(); - bool nameWithoutExtensionIsIdFormat; - bool nameWithoutExtensionIsPaddedIdFormat; IReadOnlyList directories; - short sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex(_PropertyConfiguration.Offset); for (int i = 0; i < files.Length; i++) { progressBar.Tick(); - fileHolder = new(files[i]); + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(files[i]); if (!fileHolder.Exists) continue; directory = Path.GetDirectoryName(files[i]); if (string.IsNullOrEmpty(directory)) continue; + filePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: i); if (fileHolder.ExtensionLowered == ".paddedId" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null) continue; if (files.Contains($"{fileHolder.FullName}.paddedId")) continue; - nameWithoutExtensionIsIdFormat = Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(fileHolder); - nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileHolder, sortOrderOnlyLengthIndex); - if (nameWithoutExtensionIsIdFormat || nameWithoutExtensionIsPaddedIdFormat) + if (filePath.IsIntelligentIdFormat || filePath.SortOrder is not null) continue; isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered); isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered); @@ -262,7 +258,7 @@ public class Rename ffmpegFiles = Directory.GetFiles(fileHolder.DirectoryName, $"{fileHolder.Name}-*.jpg", SearchOption.TopDirectoryOnly); if (ffmpegFiles.Length == 0) continue; - fileHolder = new(ffmpegFiles.First()); + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(ffmpegFiles.First()); if (!fileHolder.Name.EndsWith("-0001.jpg")) throw new Exception(); isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered); @@ -275,7 +271,7 @@ public class Rename (dateTimeOriginal, dateTimes, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, metadata, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding); if (ffmpegFiles is not null) { - fileHolder = new(files[i]); + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(files[i]); foreach (string ffmpegFile in ffmpegFiles) File.Delete(ffmpegFile); } @@ -286,7 +282,7 @@ public class Rename return results; } - private List<(FileHolder, string, string)> GetToDoCollection(ProgressBar progressBar, bool nefPresent, List records, int intMinValueLength) + private List<(FileHolder, string, string)> GetToDoCollection(ProgressBar progressBar, bool nefPresent, List records) { List<(FileHolder, string, string)> results = []; int season; @@ -330,7 +326,7 @@ public class Rename if (distinct.Contains(checkFile)) continue; distinct.Add(checkFile); - results.Add(new(new($"{fileHolder.FullName}.paddedId"), fileHolder.DirectoryName, checkFile)); + results.Add(new(Shared.Models.Stateless.Methods.IFileHolder.Get($"{fileHolder.FullName}.paddedId"), fileHolder.DirectoryName, checkFile)); } checkFile = Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}"); if (File.Exists(checkFile)) @@ -340,13 +336,13 @@ public class Rename distinct.Add(checkFile); results.Add(new(fileHolder, fileHolder.DirectoryName, checkFile)); if (nefPresent) - results.Add(new(new($"{fileHolder.FullName[..^4]}.tif"), fileHolder.DirectoryName, $"{checkFile[..^4]}.tif")); + results.Add(new(Shared.Models.Stateless.Methods.IFileHolder.Get($"{fileHolder.FullName[..^4]}.tif"), fileHolder.DirectoryName, $"{checkFile[..^4]}.tif")); if (nefPresent) - results.Add(new(new($"{fileHolder.FullName[..^4]}.nef"), fileHolder.DirectoryName, $"{checkFile[..^4]}.nef")); + results.Add(new(Shared.Models.Stateless.Methods.IFileHolder.Get($"{fileHolder.FullName[..^4]}.nef"), fileHolder.DirectoryName, $"{checkFile[..^4]}.nef")); if (File.Exists(checkFile)) continue; File.Move(fileHolder.FullName, checkFile); - fileHolder = new(checkFile); + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(checkFile); if (fileHolder.DirectoryName is null) continue; } @@ -398,15 +394,15 @@ public class Rename distinct.Add(checkFile); results.Add(new(fileHolder, fileHolder.DirectoryName, checkFile)); if (nefPresent) - results.Add(new(new($"{fileHolder.FullName[..^4]}.tif"), fileHolder.DirectoryName, $"{checkFile[..^4]}.tif")); + results.Add(new(Shared.Models.Stateless.Methods.IFileHolder.Get($"{fileHolder.FullName[..^4]}.tif"), fileHolder.DirectoryName, $"{checkFile[..^4]}.tif")); if (nefPresent) - results.Add(new(new($"{fileHolder.FullName[..^4]}.nef"), fileHolder.DirectoryName, $"{checkFile[..^4]}.nef")); + results.Add(new(Shared.Models.Stateless.Methods.IFileHolder.Get($"{fileHolder.FullName[..^4]}.nef"), fileHolder.DirectoryName, $"{checkFile[..^4]}.nef")); } else { if (record.Id is null) continue; - paddedId = IDirectory.GetPaddedId(intMinValueLength, record.Index, record.Id.Value); + paddedId = IId.GetPaddedId(_PropertyConfiguration, record.Index, record.Id.Value); checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered; checkFile = Path.Combine(seasonDirectory, $"{paddedId}{checkFileExtension}"); if (checkFile == fileHolder.FullName) @@ -422,9 +418,9 @@ public class Rename distinct.Add(checkFile); results.Add(new(fileHolder, seasonDirectory, checkFile)); if (nefPresent) - results.Add(new(new($"{fileHolder.FullName[..^4]}.tif"), seasonDirectory, $"{checkFile[..^4]}.tif")); + results.Add(new(Shared.Models.Stateless.Methods.IFileHolder.Get($"{fileHolder.FullName[..^4]}.tif"), seasonDirectory, $"{checkFile[..^4]}.tif")); if (nefPresent) - results.Add(new(new($"{fileHolder.FullName[..^4]}.nef"), seasonDirectory, $"{checkFile[..^4]}.nef")); + results.Add(new(Shared.Models.Stateless.Methods.IFileHolder.Get($"{fileHolder.FullName[..^4]}.nef"), seasonDirectory, $"{checkFile[..^4]}.nef")); } } return results; diff --git a/Resize/Models/_C_Resize.cs b/Resize/Models/_C_Resize.cs index aab6da0..da8e290 100644 --- a/Resize/Models/_C_Resize.cs +++ b/Resize/Models/_C_Resize.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Drawing; using System.Drawing.Imaging; using System.Reflection; @@ -75,7 +76,7 @@ public class C_Resize public void Update(string cResultsFullGroupDirectory) { _FileGroups.Clear(); - Dictionary keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, [_PropertyConfiguration.ResultSingleton]); + ReadOnlyDictionary keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, [_PropertyConfiguration.ResultSingleton]); foreach (KeyValuePair keyValuePair in keyValuePairs) _FileGroups.Add(keyValuePair.Key, keyValuePair.Value); } @@ -415,32 +416,32 @@ public class C_Resize return results; } - private FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, Item item, bool outputResolutionHasNumber, string fileName) + private FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, FilePath filePath, bool outputResolutionHasNumber, string fileName) { FileHolder result; if (outputResolutionHasNumber) - result = new(Path.Combine(AngleBracketCollection[0].Replace("<>", _PropertyConfiguration.ResultContent), fileName)); + result = Shared.Models.Stateless.Methods.IFileHolder.Get(Path.Combine(AngleBracketCollection[0].Replace("<>", _PropertyConfiguration.ResultContent), fileName)); else { - (string directoryName, _) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration.ResultAllInOneSubdirectoryLength, item.ImageFileHolder.Name); - result = new(Path.Combine(cResultsFullGroupDirectory, _PropertyConfiguration.ResultContent, _PropertyConfiguration.ResultAllInOne, directoryName, fileName)); + (string directoryName, _) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); + result = Shared.Models.Stateless.Methods.IFileHolder.Get(Path.Combine(cResultsFullGroupDirectory, _PropertyConfiguration.ResultContent, directoryName, fileName)); } return result; } public FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, Item item, bool outputResolutionHasNumber) => - GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber, item.ImageFileHolder.Name); + GetResizedFileHolder(cResultsFullGroupDirectory, item.FilePath, outputResolutionHasNumber, item.ImageFileHolder.Name); public FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, Item item, bool outputResolutionHasNumber, int id) => - GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber, $"{id}{item.ImageFileHolder.ExtensionLowered}"); + GetResizedFileHolder(cResultsFullGroupDirectory, item.FilePath, outputResolutionHasNumber, $"{id}{item.ImageFileHolder.ExtensionLowered}"); - public Dictionary GetResizeKeyValuePairs(Configuration configuration, string cResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem) + public Dictionary GetResizeKeyValuePairs(Configuration configuration, string cResultsFullGroupDirectory, FilePath filePath, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem) { Dictionary? results; string json; string[] changesFrom = [nameof(A_Property), nameof(B_Metadata)]; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration.ResultAllInOneSubdirectoryLength, mappingFromItem.ImageFileHolder.Name); + (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); FileInfo fileInfo = new(Path.Combine(_FileGroups[_PropertyConfiguration.ResultSingleton][directoryIndex], $"{mappingFromItem.ImageFileHolder.NameWithoutExtension}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json")); if (_ForceResizeLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) { diff --git a/Set-Created-Date/SetCreatedDate.cs b/Set-Created-Date/SetCreatedDate.cs index 924f05d..3643e99 100644 --- a/Set-Created-Date/SetCreatedDate.cs +++ b/Set-Created-Date/SetCreatedDate.cs @@ -21,7 +21,7 @@ public class SetCreatedDate private readonly Configuration _Configuration; private readonly IsEnvironment _IsEnvironment; private readonly IConfigurationRoot _ConfigurationRoot; - private readonly IReadOnlyDictionary _FileGroups; + private readonly ReadOnlyDictionary _FileGroups; private readonly Property.Models.Configuration _PropertyConfiguration; public SetCreatedDate(List args, ILogger logger, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) @@ -77,7 +77,7 @@ public class SetCreatedDate foreach (string file in files) { progressBar.Tick(); - fileHolder = new(file); + fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(file); if (fileHolder.ExtensionLowered == ".id" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null) continue; if (_PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered)) diff --git a/Shared/Models/FileHolder.cs b/Shared/Models/FileHolder.cs index 958f31e..67a18a8 100644 --- a/Shared/Models/FileHolder.cs +++ b/Shared/Models/FileHolder.cs @@ -1,75 +1,57 @@ using System.Text.Json; +using System.Text.Json.Serialization; namespace View_by_Distance.Shared.Models; -public class FileHolder : Properties.IFileHolder +public record FileHolder(DateTime? CreationTime, + string? DirectoryName, + bool Exists, + string ExtensionLowered, + string FullName, + DateTime? LastWriteTime, + long? Length, + string Name, + string NameWithoutExtension) { - protected readonly DateTime? _CreationTime; - protected readonly string? _DirectoryName; - protected readonly bool _Exists; - protected readonly string _ExtensionLowered; - protected readonly string _FullName; - protected readonly int? _Id; - protected readonly DateTime? _LastWriteTime; - protected readonly long? _Length; - protected readonly string _Name; - protected readonly string _NameWithoutExtension; - public DateTime? CreationTime => _CreationTime; - public string? DirectoryName => _DirectoryName; - public bool Exists => _Exists; - public string ExtensionLowered => _ExtensionLowered; - public string FullName => _FullName; - public int? Id => _Id; - public DateTime? LastWriteTime => _LastWriteTime; - public long? Length => _Length; - public string Name => _Name; - public string NameWithoutExtension => _NameWithoutExtension; - - public FileHolder(DateTime? creationTime, string? directoryName, bool exists, string extensionLowered, string fullName, int? id, DateTime? lastWriteTime, long? length, string name, string nameWithoutExtension) - { - _CreationTime = creationTime; - _DirectoryName = directoryName; - _Exists = exists; - _ExtensionLowered = extensionLowered; - _FullName = fullName; - _Id = id; - _LastWriteTime = lastWriteTime; - _Length = length; - _Name = name; - _NameWithoutExtension = nameWithoutExtension; - } - - public FileHolder(FileInfo fileInfo, int? id) - { - if (fileInfo.Exists) - { - _CreationTime = fileInfo.CreationTime; - _CreationTime = fileInfo.CreationTime; - _LastWriteTime = fileInfo.LastWriteTime; - _Length = fileInfo.Length; - } - _DirectoryName = fileInfo.DirectoryName; - _Exists = fileInfo.Exists; - _ExtensionLowered = fileInfo.Extension.ToLower(); - _Id = id; - _FullName = fileInfo.FullName; - _Name = fileInfo.Name; - _NameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName); - } - - public FileHolder(string fileName) : - this(new FileInfo(fileName), null) - { } - - public FileHolder(string fileName, int? id) : - this(new FileInfo(fileName), id) - { } - public override string ToString() { - string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + string result = JsonSerializer.Serialize(this, FileHolderSourceGenerationContext.Default.FileHolder); return result; } + public static FileHolder Get(FileInfo fileInfo) + { + FileHolder result; + if (!fileInfo.Exists) + result = new(null, + fileInfo.DirectoryName, + fileInfo.Exists, + fileInfo.Extension.ToLower(), + fileInfo.FullName, + null, + null, + fileInfo.Name, + Path.GetFileNameWithoutExtension(fileInfo.FullName)); + else + { + result = new(fileInfo.CreationTime, + fileInfo.DirectoryName, + fileInfo.Exists, + fileInfo.Extension.ToLower(), + fileInfo.FullName, + fileInfo.LastWriteTime, + fileInfo.Length, + fileInfo.Name, + Path.GetFileNameWithoutExtension(fileInfo.FullName)); + } + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(FileHolder))] +public partial class FileHolderSourceGenerationContext : JsonSerializerContext +{ } \ No newline at end of file diff --git a/Shared/Models/FilePair.cs b/Shared/Models/FilePair.cs index 808105e..44e057a 100644 --- a/Shared/Models/FilePair.cs +++ b/Shared/Models/FilePair.cs @@ -1,3 +1,25 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + namespace View_by_Distance.Shared.Models; -public record FilePair(string Path, bool IsUnique, bool? IsNotUniqueAndNeedsReview, List Collection, string? Match) { } \ No newline at end of file +internal record FilePair(string Path, + bool IsUnique, + bool? IsNotUniqueAndNeedsReview, + List Collection, + string? Match) +{ + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, FilePairSourceGenerationContext.Default.FilePair); + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(FilePair))] +internal partial class FilePairSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Shared/Models/FilePath.cs b/Shared/Models/FilePath.cs new file mode 100644 index 0000000..96ac143 --- /dev/null +++ b/Shared/Models/FilePath.cs @@ -0,0 +1,86 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using View_by_Distance.Shared.Models.Stateless.Methods; + +namespace View_by_Distance.Shared.Models; + +public record FilePath(long CreationTicks, + string DirectoryName, + string ExtensionLowered, + string FileNameFirstSegment, + string FullName, + int? Id, + bool IsIntelligentIdFormat, + long LastWriteTicks, + long Length, + string Name, + string NameWithoutExtension, + int? SortOrder) +{ + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, FilePathSourceGenerationContext.Default.FilePath); + return result; + } + + public static FilePath Get(Properties.IPropertyConfiguration propertyConfiguration, FileHolder fileHolder, int? index) + { + if (fileHolder.CreationTime is null) + throw new NullReferenceException(nameof(fileHolder.CreationTime)); + if (fileHolder.LastWriteTime is null) + throw new NullReferenceException(nameof(fileHolder.LastWriteTime)); + if (fileHolder.Length is null) + throw new NullReferenceException(nameof(fileHolder.Length)); + FilePath result; + int? id; + int? sortOder; + string fileNameFirstSegment = fileHolder.Name.Split('.')[0]; + int sortOrderOnlyLengthIndex = propertyConfiguration.Offset.ToString().Length; + string fileDirectoryName = fileHolder.DirectoryName ?? throw new NullReferenceException(); + bool fileNameFirstSegmentIsIntelligentIdFormat = IId.NameWithoutExtensionIsIntelligentIdFormat(propertyConfiguration, fileNameFirstSegment); + bool fileNameFirstSegmentIsPaddedIntelligentIdFormat = IId.NameWithoutExtensionIsPaddedIntelligentIdFormat(propertyConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment); + bool fileNameFirstSegmentIsIdFormat = !fileNameFirstSegmentIsPaddedIntelligentIdFormat && !fileNameFirstSegmentIsIntelligentIdFormat && IId.NameWithoutExtensionIsIdFormat(propertyConfiguration, fileHolder); + if (!fileNameFirstSegmentIsIdFormat && !fileNameFirstSegmentIsIntelligentIdFormat && !fileNameFirstSegmentIsPaddedIntelligentIdFormat) + (id, sortOder) = (null, null); + else if (fileNameFirstSegmentIsIntelligentIdFormat) + (id, sortOder) = (IId.GetId(propertyConfiguration, fileNameFirstSegment), null); + else if (fileNameFirstSegmentIsPaddedIntelligentIdFormat) + { + if (!int.TryParse(fileNameFirstSegment[..sortOrderOnlyLengthIndex], out int absoluteValueOfSortOrder)) + (id, sortOder) = (null, null); + else + (id, sortOder) = (IId.GetId(propertyConfiguration, fileNameFirstSegment[sortOrderOnlyLengthIndex..]), absoluteValueOfSortOrder); + } + else if (fileNameFirstSegmentIsIdFormat) + { + if (index is null) + throw new NullReferenceException(nameof(index)); + if (!int.TryParse(fileNameFirstSegment, out int valueOfFileNameFirstSegment)) + throw new NotSupportedException(); + (id, sortOder) = (valueOfFileNameFirstSegment, propertyConfiguration.Offset + index); + } + else + throw new NotSupportedException(); + result = new(fileHolder.CreationTime.Value.Ticks, + fileDirectoryName, + fileHolder.ExtensionLowered, + fileNameFirstSegment, + fileHolder.FullName, + id, + fileNameFirstSegmentIsIntelligentIdFormat, + fileHolder.LastWriteTime.Value.Ticks, + fileHolder.Length.Value, + fileHolder.Name, + fileHolder.NameWithoutExtension, + sortOder); + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(FilePath))] +public partial class FilePathSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Shared/Models/Item.cs b/Shared/Models/Item.cs index 70de74d..b92b869 100644 --- a/Shared/Models/Item.cs +++ b/Shared/Models/Item.cs @@ -8,6 +8,7 @@ public class Item : Properties.IItem protected List _Faces; protected readonly bool? _FileSizeChanged; + protected readonly FilePath _FilePath; protected readonly FileHolder _ImageFileHolder; protected bool? _IsNotUniqueAndNeedsReview; protected bool _IsUniqueFileName; @@ -20,6 +21,7 @@ public class Item : Properties.IItem protected readonly FileHolder _SourceDirectoryFileHolder; public List Faces => _Faces; public bool? FileSizeChanged => _FileSizeChanged; + public FilePath FilePath => _FilePath; public FileHolder ImageFileHolder => _ImageFileHolder; public bool? IsNotUniqueAndNeedsReview => _IsNotUniqueAndNeedsReview; public bool IsUniqueFileName => _IsUniqueFileName; @@ -32,9 +34,10 @@ public class Item : Properties.IItem public FileHolder SourceDirectoryFileHolder => _SourceDirectoryFileHolder; [JsonConstructor] - public Item(List faces, bool? fileSizeChanged, FileHolder imageFileHolder, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, bool? lastWriteTimeChanged, bool? moved, Property? property, string relativePath, FileHolder? resizedFileHolder, FileHolder sourceDirectoryFileHolder) + public Item(List faces, FilePath filePath, bool? fileSizeChanged, FileHolder imageFileHolder, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, bool? lastWriteTimeChanged, bool? moved, Property? property, string relativePath, FileHolder? resizedFileHolder, FileHolder sourceDirectoryFileHolder) { _Faces = faces; + _FilePath = filePath; _FileSizeChanged = fileSizeChanged; _ImageFileHolder = imageFileHolder; _IsNotUniqueAndNeedsReview = isNotUniqueAndNeedsReview; @@ -48,8 +51,8 @@ public class Item : Properties.IItem _SourceDirectoryFileHolder = sourceDirectoryFileHolder; } - public Item(FileHolder sourceDirectoryFileHolder, string relativePath, FileHolder imageFileInfo, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, Property? property, bool? abandoned, bool? fileSizeChanged, bool? lastWriteTimeChanged) : - this([], fileSizeChanged, imageFileInfo, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, lastWriteTimeChanged, null, property, relativePath, null, sourceDirectoryFileHolder) + public Item(FilePath filePath, FileHolder sourceDirectoryFileHolder, string relativePath, FileHolder imageFileInfo, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, Property? property, bool? abandoned, bool? fileSizeChanged, bool? lastWriteTimeChanged) : + this([], filePath, fileSizeChanged, imageFileInfo, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, lastWriteTimeChanged, null, property, relativePath, null, sourceDirectoryFileHolder) { if (relativePath.EndsWith(".json")) throw new ArgumentException("Can not be a *.json file!"); @@ -57,8 +60,8 @@ public class Item : Properties.IItem throw new ArgumentException("Can not be a *.json file!"); } - public Item(FileHolder sourceDirectoryFileHolder, string relativePath, bool isValidImageFormatExtension) : - this(sourceDirectoryFileHolder, relativePath, sourceDirectoryFileHolder, null, false, isValidImageFormatExtension, null, null, null, null) + public Item(FilePath filePath, FileHolder sourceDirectoryFileHolder, string relativePath, bool isValidImageFormatExtension) : + this(filePath, sourceDirectoryFileHolder, relativePath, sourceDirectoryFileHolder, null, false, isValidImageFormatExtension, null, null, null, null) { } public override string ToString() diff --git a/Shared/Models/LocationContainer.cs b/Shared/Models/LocationContainer.cs index 6000c2a..93caf6a 100644 --- a/Shared/Models/LocationContainer.cs +++ b/Shared/Models/LocationContainer.cs @@ -6,7 +6,7 @@ public record LocationContainer(DateOnly CreationDateOnly, IReadOnlyList Directories, int? DirectoryNumber, string DisplayDirectoryName, - string File, + FilePath FilePath, bool FromDistanceContent, int Id, Location? Location, diff --git a/Shared/Models/Mapping.cs b/Shared/Models/Mapping.cs index cb2439c..4efc725 100644 --- a/Shared/Models/Mapping.cs +++ b/Shared/Models/Mapping.cs @@ -11,6 +11,7 @@ public class Mapping : Properties.IMapping public string? _SegmentC; protected SortingContainer? _SortingContainer; public int? By => _By; + public FilePath FilePath { init; get; } public MappingFromFilterPost MappingFromFilterPost { init; get; } public MappingFromFilterPre MappingFromFilterPre { init; get; } public MappingFromItem MappingFromItem { init; get; } @@ -21,9 +22,10 @@ public class Mapping : Properties.IMapping public SortingContainer? SortingContainer => _SortingContainer; [JsonConstructor] - public Mapping(int? by, MappingFromFilterPost mappingFromFilterPost, MappingFromFilterPre mappingFromFilterPre, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, MappingFromPerson? mappingFromPerson, List? mappingFromPhotoPrismCollection, string? segmentC, SortingContainer? sortingContainer) + public Mapping(int? by, FilePath filePath, MappingFromFilterPost mappingFromFilterPost, MappingFromFilterPre mappingFromFilterPre, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, MappingFromPerson? mappingFromPerson, List? mappingFromPhotoPrismCollection, string? segmentC, SortingContainer? sortingContainer) { _By = by; + FilePath = filePath; _SegmentC = segmentC; MappingFromFilterPost = mappingFromFilterPost; MappingFromFilterPre = mappingFromFilterPre; @@ -34,8 +36,8 @@ public class Mapping : Properties.IMapping _SortingContainer = sortingContainer; } - public Mapping(MappingFromFilterPost mappingFromFilterPost, MappingFromFilterPre mappingFromFilterPre, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, List? mappingFromPhotoPrismCollection) : - this(null, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, null, mappingFromPhotoPrismCollection, null, null) + public Mapping(FilePath filePath, MappingFromFilterPost mappingFromFilterPost, MappingFromFilterPre mappingFromFilterPre, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, List? mappingFromPhotoPrismCollection) : + this(null, filePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, null, mappingFromPhotoPrismCollection, null, null) { } public override string ToString() diff --git a/Shared/Models/Methods/IBlurHasher.cs b/Shared/Models/Methods/IBlurHasher.cs index 58cbc4c..df97cbe 100644 --- a/Shared/Models/Methods/IBlurHasher.cs +++ b/Shared/Models/Methods/IBlurHasher.cs @@ -3,9 +3,9 @@ namespace View_by_Distance.Shared.Models.Methods; public interface IBlurHasher { + string GetFile(FilePath filePath); string Encode(FileHolder fileHolder); - string GetFile(FileHolder fileHolder); - string EncodeAndSave(FileHolder fileHolder); void Update(string resultsFullGroupDirectory); + string EncodeAndSave(FilePath filePath, FileHolder fileHolder); } \ No newline at end of file diff --git a/Shared/Models/PersonContainer.cs b/Shared/Models/PersonContainer.cs index 5ffabcd..0c7ce76 100644 --- a/Shared/Models/PersonContainer.cs +++ b/Shared/Models/PersonContainer.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Text.Json; using System.Text.Json.Serialization; @@ -8,18 +9,18 @@ public class PersonContainer : Properties.IPersonContainer public int? ApproximateYears { init; get; } public PersonBirthday[]? Birthdays { init; get; } - public string[] DisplayDirectoryAllFiles { init; get; } + public ReadOnlyCollection DisplayDirectoryAllFilePaths { init; get; } public string DisplayDirectoryName { init; get; } public long? Key { init; get; } public bool? KeyIsMaxBirthday { init; get; } public PersonDirectory? PersonDirectory { init; get; } [JsonConstructor] - public PersonContainer(int? approximateYears, PersonBirthday[]? birthdays, string[] displayDirectoryAllFiles, string displayDirectoryName, long? key, PersonDirectory? personDirectory) + public PersonContainer(int? approximateYears, PersonBirthday[]? birthdays, ReadOnlyCollection displayDirectoryAllFiles, string displayDirectoryName, long? key, PersonDirectory? personDirectory) { ApproximateYears = approximateYears; Birthdays = birthdays; - DisplayDirectoryAllFiles = displayDirectoryAllFiles; + DisplayDirectoryAllFilePaths = displayDirectoryAllFiles; DisplayDirectoryName = displayDirectoryName; Key = key; PersonDirectory = personDirectory; @@ -27,22 +28,22 @@ public class PersonContainer : Properties.IPersonContainer } public PersonContainer(char[] personCharacters, PersonBirthday birthday, string displayDirectoryName, PersonDirectory personDirectory) : - this(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), [birthday], [], displayDirectoryName, birthday.Value.Ticks, personDirectory) + this(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), [birthday], new([]), displayDirectoryName, birthday.Value.Ticks, personDirectory) { } public PersonContainer(int? approximateYears, PersonBirthday birthdays, string displayDirectoryName, long key) : - this(approximateYears, [birthdays], [], displayDirectoryName, key, null) + this(approximateYears, [birthdays], new([]), displayDirectoryName, key, null) { } public PersonContainer(int? approximateYears, PersonBirthday birthdays, PersonDirectory? personDirectory, string displayDirectoryName, long key) : - this(approximateYears, [birthdays], [], displayDirectoryName, key, personDirectory) + this(approximateYears, [birthdays], new([]), displayDirectoryName, key, personDirectory) { } - public PersonContainer(int? approximateYears, string[] displayDirectoryAllFiles, string displayDirectoryName, PersonDirectory? personDirectory) : + public PersonContainer(int? approximateYears, ReadOnlyCollection displayDirectoryAllFiles, string displayDirectoryName, PersonDirectory? personDirectory) : this(approximateYears, null, displayDirectoryAllFiles, displayDirectoryName, null, personDirectory) { } - public PersonContainer(int? approximateYears, PersonBirthday[]? birthdays, string[] displayDirectoryAllFiles, string displayDirectoryName, long? key) : + public PersonContainer(int? approximateYears, PersonBirthday[]? birthdays, ReadOnlyCollection displayDirectoryAllFiles, string displayDirectoryName, long? key) : this(approximateYears, birthdays, displayDirectoryAllFiles, displayDirectoryName, key, null) { } diff --git a/Shared/Models/Properties/IFileHolder.cs b/Shared/Models/Properties/IFileHolder.cs deleted file mode 100644 index 20bbc5b..0000000 --- a/Shared/Models/Properties/IFileHolder.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace View_by_Distance.Shared.Models.Properties; - -public interface IFileHolder -{ - - public DateTime? CreationTime { get; } - public string? DirectoryName { get; } - public bool Exists { get; } - public string ExtensionLowered { get; } - public string FullName { get; } - public DateTime? LastWriteTime { get; } - public long? Length { get; } - public string Name { get; } - public string NameWithoutExtension { get; } - -} \ No newline at end of file diff --git a/Shared/Models/Properties/IItem.cs b/Shared/Models/Properties/IItem.cs index f073564..433367d 100644 --- a/Shared/Models/Properties/IItem.cs +++ b/Shared/Models/Properties/IItem.cs @@ -5,6 +5,7 @@ public interface IItem public bool? FileSizeChanged { get; } public List Faces { get; } + public FilePath FilePath { get; } public FileHolder ImageFileHolder { get; } public bool? IsNotUniqueAndNeedsReview { get; } public bool IsUniqueFileName { get; } diff --git a/Shared/Models/Properties/IMapping.cs b/Shared/Models/Properties/IMapping.cs index 16fdac4..91a98f4 100644 --- a/Shared/Models/Properties/IMapping.cs +++ b/Shared/Models/Properties/IMapping.cs @@ -4,6 +4,7 @@ public interface IMapping { public int? By { get; } + public FilePath FilePath { init; get; } public MappingFromFilterPost MappingFromFilterPost { init; get; } public MappingFromFilterPre MappingFromFilterPre { init; get; } public MappingFromLocation? MappingFromLocation { init; get; } diff --git a/Shared/Models/Properties/IPersonContainer.cs b/Shared/Models/Properties/IPersonContainer.cs index a436eb2..922f350 100644 --- a/Shared/Models/Properties/IPersonContainer.cs +++ b/Shared/Models/Properties/IPersonContainer.cs @@ -1,3 +1,5 @@ +using System.Collections.ObjectModel; + namespace View_by_Distance.Shared.Models.Properties; public interface IPersonContainer @@ -5,7 +7,7 @@ public interface IPersonContainer public int? ApproximateYears { init; get; } public PersonBirthday[]? Birthdays { init; get; } - public string[] DisplayDirectoryAllFiles { init; get; } + public ReadOnlyCollection DisplayDirectoryAllFilePaths { init; get; } public string DisplayDirectoryName { init; get; } public long? Key { init; get; } public bool? KeyIsMaxBirthday { init; get; } diff --git a/Shared/Models/Properties/IPropertyConfiguration.cs b/Shared/Models/Properties/IPropertyConfiguration.cs index 7280890..445a6e7 100644 --- a/Shared/Models/Properties/IPropertyConfiguration.cs +++ b/Shared/Models/Properties/IPropertyConfiguration.cs @@ -6,6 +6,7 @@ public interface IPropertyConfiguration public string DateGroup { init; get; } public string[] IgnoreExtensions { init; get; } public string[] IgnoreRulesKeyWords { init; get; } + public int IntMinValueLength { init; get; } public string PersonBirthdayFormat { init; get; } public bool PropertiesChangedForProperty { init; get; } public string[] PropertyContentCollectionFiles { init; get; } diff --git a/Shared/Models/SaveContainer.cs b/Shared/Models/SaveContainer.cs index eff3e08..dee9e4c 100644 --- a/Shared/Models/SaveContainer.cs +++ b/Shared/Models/SaveContainer.cs @@ -33,7 +33,7 @@ public class SaveContainer { } public SaveContainer(string directory, string locationContainersFile) : - this(string.Empty, directory, null, null, null, false, new(locationContainersFile), Path.Combine(directory, $"{Path.GetFileName(locationContainersFile)}.lnk")) + this(string.Empty, directory, null, null, null, false, Stateless.Methods.IFileHolder.Get(locationContainersFile), Path.Combine(directory, $"{Path.GetFileName(locationContainersFile)}.lnk")) { } public SaveContainer(string directory, FileHolder? faceFileHolder, FileHolder? resizedFileHolder, string shortcutFile) : diff --git a/Shared/Models/Stateless/Methods/Container.cs b/Shared/Models/Stateless/Methods/Container.cs index 9135498..40eff27 100644 --- a/Shared/Models/Stateless/Methods/Container.cs +++ b/Shared/Models/Stateless/Methods/Container.cs @@ -6,7 +6,7 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class Container { - private record FilePair(string Path, string? Directory, bool IsUnique, List Collection, Models.Item Item) { } + private record FilePair(bool IsUnique, List Collection, FilePath FilePath, Models.Item Item) { } internal static DateTime[] GetContainerDateTimes(IEnumerable items) { @@ -45,15 +45,15 @@ internal abstract class Container List? filePairs = null; ReadOnlyCollection? jsonFilesCollection = null; IReadOnlyDictionary>? compareFileNamesToFiles = null; - IReadOnlyDictionary> fileNamesToFiles = IDirectory.GetFilesKeyValuePairs(filesCollection); + IReadOnlyDictionary> fileNamesToFiles = XDirectory.GetFilesKeyValuePairs(filesCollection); for (int i = 0; i < int.MaxValue; i++) { renamed = 0; jsonFilesCollection = IDirectory.GetFilesCollection(aPropertySingletonDirectory, directorySearchFilter, extension, useCeilingAverage); - compareFileNamesToFiles = IDirectory.GetFilesKeyValuePairs(jsonFilesCollection); - renamed += IDirectory.LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension); - filePairs = IDirectory.GetFiles(filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles); - renamed += IDirectory.MaybeMove(propertyConfiguration.RootDirectory, propertyConfiguration.ResultAllInOne, propertyConfiguration.ResultAllInOneSubdirectoryLength, filePairs, aPropertySingletonDirectory, extension); + compareFileNamesToFiles = XDirectory.GetFilesKeyValuePairs(jsonFilesCollection); + renamed += XDirectory.LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension); + filePairs = XDirectory.GetFiles(filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles); + renamed += XDirectory.MaybeMove(propertyConfiguration, filePairs, aPropertySingletonDirectory, extension); if (renamed == 0) break; } @@ -80,33 +80,33 @@ internal abstract class Container private static void ParallelFor(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string extension, int rootDirectoryLength, Models.FilePair filePair, List results) { - string fileName; bool abandoned = false; Models.FileHolder sourceDirectoryFileHolder; Models.Property? property = GetProperty(filePair); - Models.FileHolder imageFileInfo = new(filePair.Path); - bool? fileSizeChanged = property is not null ? property.FileSize != imageFileInfo.Length : null; + Models.FileHolder imageFileInfo = IFileHolder.Get(filePair.Path); + FilePath filePath = FilePath.Get(propertyConfiguration, imageFileInfo, index: null); + bool? fileSizeChanged = property is not null ? property.FileSize != filePath.Length : null; + bool isValidImageFormatExtension = propertyConfiguration.ValidImageFormatExtensions.Contains(filePath.ExtensionLowered); string relativePath = IPath.GetRelativePath(filePair.Path, rootDirectoryLength, forceExtensionToLower: true); - bool isValidImageFormatExtension = propertyConfiguration.ValidImageFormatExtensions.Contains(imageFileInfo.ExtensionLowered); - bool? lastWriteTimeChanged = property is not null ? propertyConfiguration.PropertiesChangedForProperty || property.LastWriteTime != imageFileInfo.LastWriteTime : null; + bool? lastWriteTimeChanged = property is not null ? propertyConfiguration.PropertiesChangedForProperty || property.LastWriteTime.Ticks != filePath.LastWriteTicks : null; if (filePair.Match is not null) - sourceDirectoryFileHolder = new(filePair.Match); + sourceDirectoryFileHolder = IFileHolder.Get(filePair.Match); else if (!filePair.IsUnique) - sourceDirectoryFileHolder = new(Path.GetFullPath(string.Concat(aPropertySingletonDirectory, relativePath, extension))); + sourceDirectoryFileHolder = IFileHolder.Get(Path.GetFullPath(string.Concat(aPropertySingletonDirectory, relativePath, extension))); else { - fileName = Path.GetFileName(filePair.Path); - (string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, fileName); - sourceDirectoryFileHolder = new(Path.Combine(aPropertySingletonDirectory, propertyConfiguration.ResultAllInOne, directoryName, $"{fileName}{extension}")); + string fileName = Path.GetFileName(filePair.Path); + (string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); + sourceDirectoryFileHolder = IFileHolder.Get(Path.Combine(aPropertySingletonDirectory, directoryName, $"{fileName}{extension}")); } - if (imageFileInfo.LastWriteTime is not null && sourceDirectoryFileHolder.CreationTime is not null && sourceDirectoryFileHolder.LastWriteTime is not null && imageFileInfo.LastWriteTime.Value != sourceDirectoryFileHolder.CreationTime.Value) + if (sourceDirectoryFileHolder.CreationTime is not null && sourceDirectoryFileHolder.LastWriteTime is not null && filePath.LastWriteTicks != sourceDirectoryFileHolder.CreationTime.Value.Ticks) { - File.SetCreationTime(sourceDirectoryFileHolder.FullName, imageFileInfo.LastWriteTime.Value); + File.SetCreationTime(sourceDirectoryFileHolder.FullName, new(filePath.LastWriteTicks)); File.SetLastWriteTime(sourceDirectoryFileHolder.FullName, sourceDirectoryFileHolder.LastWriteTime.Value); } - Models.Item item = new(sourceDirectoryFileHolder, relativePath, imageFileInfo, filePair.IsNotUniqueAndNeedsReview, filePair.IsUnique, isValidImageFormatExtension, property, abandoned, fileSizeChanged, lastWriteTimeChanged); + Models.Item item = new(filePath, sourceDirectoryFileHolder, relativePath, imageFileInfo, filePair.IsNotUniqueAndNeedsReview, filePair.IsUnique, isValidImageFormatExtension, property, abandoned, fileSizeChanged, lastWriteTimeChanged); lock (results) - results.Add(new(filePair.Path, imageFileInfo.DirectoryName, filePair.IsUnique, filePair.Collection, item)); + results.Add(new(filePair.IsUnique, filePair.Collection, filePath, item)); } private static List GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, string extension, List filePairs) @@ -148,12 +148,10 @@ internal abstract class Container List collection = GetFilePairs(propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, extension, filePairs); foreach (FilePair filePair in collection) { - if (filePair.Directory is null) - continue; - if (!directoryToItems.TryGetValue(filePair.Directory, out items)) + if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryName, out items)) { - directoryToItems.Add(filePair.Directory, []); - if (!directoryToItems.TryGetValue(filePair.Directory, out items)) + directoryToItems.Add(filePair.FilePath.DirectoryName, []); + if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryName, out items)) throw new Exception(); } items.Add(filePair.Item); diff --git a/Shared/Models/Stateless/Methods/FileHolder.cs b/Shared/Models/Stateless/Methods/FileHolder.cs index 31b0c2a..c909661 100644 --- a/Shared/Models/Stateless/Methods/FileHolder.cs +++ b/Shared/Models/Stateless/Methods/FileHolder.cs @@ -7,14 +7,14 @@ internal abstract class FileHolder { List results = []; foreach ((string _, string[] files) in collection) - results.AddRange(files.Select(l => new Models.FileHolder(l))); + results.AddRange(files.Select(l => IFileHolder.Get(l))); return results; } internal static IEnumerable GetFileHolders(IEnumerable<(string, string)> collection) { foreach ((string _, string file) in collection) - yield return new(file); + yield return IFileHolder.Get(file); } internal static IEnumerable<(string, string[])> GetFiles(string root, string searchPattern) diff --git a/Shared/Models/Stateless/Methods/IContainer.cs b/Shared/Models/Stateless/Methods/IContainer.cs index 65e87f4..ad578fd 100644 --- a/Shared/Models/Stateless/Methods/IContainer.cs +++ b/Shared/Models/Stateless/Methods/IContainer.cs @@ -15,11 +15,6 @@ public interface IContainer static Models.Item[] GetFilterItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container container) => Container.GetFilterItems(propertyConfiguration, container); - List TestStatic_GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, ReadOnlyCollection filesCollection) => - Container.GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filesCollection); - static List GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, ReadOnlyCollection filesCollection) => - Container.GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filesCollection); - (int, Models.Container[]) TestStatic_GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) => GetContainers(propertyConfiguration, aPropertySingletonDirectory); static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) => diff --git a/Shared/Models/Stateless/Methods/IDirectory.cs b/Shared/Models/Stateless/Methods/IDirectory.cs index 0c2704a..a4934ab 100644 --- a/Shared/Models/Stateless/Methods/IDirectory.cs +++ b/Shared/Models/Stateless/Methods/IDirectory.cs @@ -5,11 +5,6 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; public interface IDirectory { - short TestStatic_GetSortOrderOnlyLengthIndex(int offset) => - GetSortOrderOnlyLengthIndex(offset); - static short GetSortOrderOnlyLengthIndex(int offset) => - (short)(offset.ToString().Length + 3); - char TestStatic_GetDirectory(string fileName) => GetDirectory(fileName); static char GetDirectory(string fileName) => @@ -20,77 +15,29 @@ public interface IDirectory static int GetDirectory(char directory) => directory == '-' ? 10 : int.TryParse(directory.ToString(), out int value) ? value : 11; - string TestStatic_GetPaddedId(int intMinValueLength, int index, int id) => - GetPaddedId(intMinValueLength, index, id); - static string GetPaddedId(int intMinValueLength, int index, int id) => - id > -1 ? $"{index}070{id.ToString().PadLeft(intMinValueLength, '0')}" : $"{index}030{id.ToString()[1..].PadLeft(intMinValueLength, '0')}"; - - bool TestStatic_NameWithoutExtensionIsPaddedIdFormat(string fileNameWithoutExtension, short sortOrderOnlyLengthIndex) => - NameWithoutExtensionIsPaddedIdFormat(fileNameWithoutExtension, sortOrderOnlyLengthIndex); - static bool NameWithoutExtensionIsPaddedIdFormat(string fileNameWithoutExtension, short sortOrderOnlyLengthIndex) => - fileNameWithoutExtension.Length > sortOrderOnlyLengthIndex - && fileNameWithoutExtension[sortOrderOnlyLengthIndex] == '0' - && fileNameWithoutExtension[sortOrderOnlyLengthIndex - 3] == '0' - && fileNameWithoutExtension.All(l => char.IsNumber(l)); - - bool TestStatic_NameWithoutExtensionIsPaddedIdFormat(Models.FileHolder fileHolder, short sortOrderOnlyLengthIndex) => - NameWithoutExtensionIsPaddedIdFormat(fileHolder, sortOrderOnlyLengthIndex); - static bool NameWithoutExtensionIsPaddedIdFormat(Models.FileHolder fileHolder, short sortOrderOnlyLengthIndex) => - NameWithoutExtensionIsPaddedIdFormat(fileHolder.NameWithoutExtension, sortOrderOnlyLengthIndex); - ReadOnlyCollection TestStatic_GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) => GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage); static ReadOnlyCollection GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) => XDirectory.GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage); - IReadOnlyDictionary> TestStatic_GetFilesKeyValuePairs(ReadOnlyCollection filesCollection) => - GetFilesKeyValuePairs(filesCollection); - static IReadOnlyDictionary> GetFilesKeyValuePairs(ReadOnlyCollection filesCollection) => - XDirectory.GetFilesKeyValuePairs(filesCollection); - - int TestStatic_LookForAbandoned(ReadOnlyCollection jsonFilesCollection, IReadOnlyDictionary> fileNamesToFiles, string extension) => - LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension); - static int LookForAbandoned(ReadOnlyCollection jsonFilesCollection, IReadOnlyDictionary> fileNamesToFiles, string extension) => - XDirectory.LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension); - - int TestStatic_MaybeMove(string directory, string resultAllInOne, int resultAllInOneSubdirectoryLength, List filePairs, string jsonGroupDirectory, string extension) => - MaybeMove(directory, resultAllInOne, resultAllInOneSubdirectoryLength, filePairs, jsonGroupDirectory, extension); - static int MaybeMove(string directory, string resultAllInOne, int resultAllInOneSubdirectoryLength, List filePairs, string jsonGroupDirectory, string extension) => - XDirectory.MaybeMove(directory, resultAllInOne, resultAllInOneSubdirectoryLength, filePairs, jsonGroupDirectory, extension); - - List TestStatic_GetFiles(ReadOnlyCollection filesCollection, IReadOnlyDictionary> fileNamesToFiles, string extension, IReadOnlyDictionary> compareFileNamesToFiles) => - GetFiles(filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles); - static List GetFiles(ReadOnlyCollection filesCollection, IReadOnlyDictionary> fileNamesToFiles, string extension, IReadOnlyDictionary> compareFileNamesToFiles) => - XDirectory.GetFiles(filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles); - void TestStatic_MoveFiles(List files, string find, string replace) => MoveFiles(files, find, replace); static void MoveFiles(List files, string find, string replace) => XDirectory.MoveFiles(files, find, replace); - (string[], List<(Models.FileHolder, string?, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection filesCollection, string[] directories, Action? tick) => + (string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection filesCollection, string[] directories, Action? tick) => GetToDoCollection(propertyConfiguration, filesCollection, directories, tick); - static (string[], List<(Models.FileHolder, string?, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection filesCollection, string[] directories, Action? tick) => + static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection filesCollection, string[] directories, Action? tick) => XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates: false, ifCanUseId: true, filesCollection, directories, tick); - (string[], List<(Models.FileHolder, string?, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection filesCollection, string[] directories, Action? tick) => + (string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection filesCollection, string[] directories, Action? tick) => GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filesCollection, directories, tick); - static (string[], List<(Models.FileHolder, string?, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection filesCollection, string[] directories, Action? tick) => + static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection filesCollection, string[] directories, Action? tick) => XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filesCollection, directories, tick); - List TestStatic_CopyOrMove(List<(Models.FileHolder, string?, string)> toDoCollection, bool move, bool moveBack, Action? tick) => + List TestStatic_CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) => CopyOrMove(toDoCollection, move, moveBack, tick); - static List CopyOrMove(List<(Models.FileHolder, string?, string)> toDoCollection, bool move, bool moveBack, Action? tick) => + static List CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) => XDirectory.CopyOrMove(toDoCollection, move, moveBack, tick); - (bool, int?) TestStatic_GetId(short sortOrderOnlyLengthIndex, Models.FileHolder fileHolder) => - GetId(sortOrderOnlyLengthIndex, fileHolder); - static (bool, int?) GetId(short sortOrderOnlyLengthIndex, Models.FileHolder fileHolder) => - XDirectory.GetId(sortOrderOnlyLengthIndex, fileHolder); - - (bool, int?) TestStatic_GetId(int offset, Models.FileHolder fileHolder) => - GetId(offset, fileHolder); - static (bool, int?) GetId(int offset, Models.FileHolder fileHolder) => - XDirectory.GetId(GetSortOrderOnlyLengthIndex(offset), fileHolder); - } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IFileHolder.cs b/Shared/Models/Stateless/Methods/IFileHolder.cs index 7b9b085..7bac89f 100644 --- a/Shared/Models/Stateless/Methods/IFileHolder.cs +++ b/Shared/Models/Stateless/Methods/IFileHolder.cs @@ -21,6 +21,24 @@ public interface IFileHolder Models.FileHolder TestStatic_Refresh(Models.FileHolder fileHolder) => Refresh(fileHolder); static Models.FileHolder Refresh(Models.FileHolder fileHolder) => - new(fileHolder.FullName); + Get(fileHolder.FullName); + + Models.FileHolder TestStatic_Get(string fileName) => + Get(fileName); + static Models.FileHolder Get(string fileName) => + Models.FileHolder.Get(new FileInfo(fileName)); + + Models.FileHolder TestStatic_Get(FilePath filePath) => + Get(filePath); + static Models.FileHolder Get(FilePath filePath) => + new(new(filePath.CreationTicks), + filePath.DirectoryName, + true, + filePath.ExtensionLowered, + filePath.FullName, + new(filePath.LastWriteTicks), + filePath.Length, + filePath.Name, + filePath.NameWithoutExtension); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IId.cs b/Shared/Models/Stateless/Methods/IId.cs new file mode 100644 index 0000000..ff3b056 --- /dev/null +++ b/Shared/Models/Stateless/Methods/IId.cs @@ -0,0 +1,43 @@ +namespace View_by_Distance.Shared.Models.Stateless.Methods; + +public interface IId +{ // ... + + string TestStatic_GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool ignore) => + GetIntelligentId(propertyConfiguration, id, ignore); + static string GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool ignore) => + Id.GetIntelligentId(propertyConfiguration, id, ignore); + + int TestStatic_GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) => + GetId(propertyConfiguration, intelligentId); + static int GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) => + Id.GetId(propertyConfiguration, intelligentId); + + string TestStatic_GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int index, int id) => + GetPaddedId(propertyConfiguration, index, id); + static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int index, int id) => + Id.GetPaddedId(propertyConfiguration, index, id); + + bool TestStatic_NameWithoutExtensionIsIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, string fileNameFirstSegment) => + NameWithoutExtensionIsIntelligentIdFormat(propertyConfiguration, fileNameFirstSegment); + static bool NameWithoutExtensionIsIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, string fileNameFirstSegment) => + fileNameFirstSegment.Length - 1 == propertyConfiguration.IntMinValueLength && fileNameFirstSegment[^1] is '1' or '2' or '8' or '9' && fileNameFirstSegment.All(char.IsNumber); + + bool TestStatic_NameWithoutExtensionIsPaddedIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) => + NameWithoutExtensionIsPaddedIntelligentIdFormat(propertyConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment); + static bool NameWithoutExtensionIsPaddedIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) => + fileNameFirstSegment.Length == propertyConfiguration.IntMinValueLength + sortOrderOnlyLengthIndex + 1 + && fileNameFirstSegment[^1] is '1' or '2' or '8' or '9' + && fileNameFirstSegment.All(char.IsNumber); + + bool TestStatic_NameWithoutExtensionIsIdFormat(Properties.IPropertyConfiguration propertyConfiguration, Models.FileHolder fileHolder) => + NameWithoutExtensionIsIdFormat(propertyConfiguration, fileHolder); + static bool NameWithoutExtensionIsIdFormat(Properties.IPropertyConfiguration propertyConfiguration, Models.FileHolder fileHolder) => + Id.NameWithoutExtensionIsIdFormat(propertyConfiguration, fileHolder.NameWithoutExtension.Split('.')[0]); + + int TestStatic_GetDeterministicHashCode(byte[] value) => + GetDeterministicHashCode(value); + static int GetDeterministicHashCode(byte[] value) => + Id.GetDeterministicHashCode(value); + +} \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IMapping.cs b/Shared/Models/Stateless/Methods/IMapping.cs index 9e366ff..b97c1c7 100644 --- a/Shared/Models/Stateless/Methods/IMapping.cs +++ b/Shared/Models/Stateless/Methods/IMapping.cs @@ -3,11 +3,6 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; public interface IMapping { // ... - (string?, string?, string?, bool?) TestStatic_GetSegments(string facesFileNameExtension, string fileName) - => GetSegments(facesFileNameExtension, fileName); - static (string?, string?, string?, bool?) GetSegments(string facesFileNameExtension, string fileName) - => Mapping.GetSegments(facesFileNameExtension, fileName); - int TestStatic_GetAreaPermyriad(int faceAreaPermyriad, int height, Models.Location location, int width) => GetAreaPermyriad(faceAreaPermyriad, height, location, width); static int GetAreaPermyriad(int faceAreaPermyriad, int height, Models.Location location, int width) @@ -23,19 +18,19 @@ public interface IMapping static int GetAreaPermyriad(int faceAreaPermyriad, Models.Location location, Models.OutputResolution outputResolution) => Mapping.GetAreaPermyriad(faceAreaPermyriad, location.Bottom, outputResolution.Height, location.Left, location.Right, location.Top, outputResolution.Width); - string TestStatic_GetDeterministicHashCodeKey(int id, Models.Location location, int locationDigits, Models.OutputResolution outputResolution) - => GetDeterministicHashCodeKey(id, location, locationDigits, outputResolution); - static string GetDeterministicHashCodeKey(int id, Models.Location location, int locationDigits, Models.OutputResolution outputResolution) - => $"{id}.{ILocation.GetLeftPadded(locationDigits, ILocation.GetWholePercentages(location, locationDigits, outputResolution))}"; + string TestStatic_GetDeterministicHashCodeKey(FilePath filePath, Models.Location location, int locationDigits, Models.OutputResolution outputResolution) + => GetDeterministicHashCodeKey(filePath, location, locationDigits, outputResolution); + static string GetDeterministicHashCodeKey(FilePath filePath, Models.Location location, int locationDigits, Models.OutputResolution outputResolution) + => filePath.IsIntelligentIdFormat ? $"{filePath.FileNameFirstSegment}.{ILocation.GetLeftPadded(locationDigits, ILocation.GetWholePercentages(location, locationDigits, outputResolution))}" : throw new NotImplementedException(); - string TestStatic_GetDeterministicHashCodeKey(int id, int locationDigits) - => GetDeterministicHashCodeKey(id, locationDigits); - static string GetDeterministicHashCodeKey(int id, int locationDigits) - => $"{id}.{ILocation.GetLeftPadded(locationDigits, ILocation.GetWholePercentages(locationDigits))}"; + string TestStatic_GetDeterministicHashCodeKey(FilePath filePath, int locationDigits) + => GetDeterministicHashCodeKey(filePath, locationDigits); + static string GetDeterministicHashCodeKey(FilePath filePath, int locationDigits) + => filePath.IsIntelligentIdFormat ? $"{filePath.FileNameFirstSegment}.{ILocation.GetLeftPadded(locationDigits, ILocation.GetWholePercentages(locationDigits))}" : throw new NotImplementedException(); - (int?, int?) TestStatic_GetConverted(string facesFileNameExtension, string file) => - GetConverted(facesFileNameExtension, file); - static (int?, int?) GetConverted(string facesFileNameExtension, string file) => - Mapping.GetConverted(facesFileNameExtension, file); + int? TestStatic_GetWholePercentages(string facesFileNameExtension, FilePath filePath) => + GetWholePercentages(facesFileNameExtension, filePath); + static int? GetWholePercentages(string facesFileNameExtension, FilePath filePath) => + Mapping.GetWholePercentages(facesFileNameExtension, filePath); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPath.cs b/Shared/Models/Stateless/Methods/IPath.cs index bb62bbf..3def722 100644 --- a/Shared/Models/Stateless/Methods/IPath.cs +++ b/Shared/Models/Stateless/Methods/IPath.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using View_by_Distance.Shared.Models.Properties; namespace View_by_Distance.Shared.Models.Stateless.Methods; @@ -61,14 +62,14 @@ public interface IPath static string GetDirectory(string sourceDirectory, int level, string directoryName) => XPath.GetDirectory(sourceDirectory, level, directoryName); - (string, int) TestStatic_GetDirectoryNameAndIndex(int resultAllInOneSubdirectoryLength, string fileName) => - GetDirectoryNameAndIndex(resultAllInOneSubdirectoryLength, fileName); - static (string, int) GetDirectoryNameAndIndex(int resultAllInOneSubdirectoryLength, string fileName) => - XPath.GetDirectoryNameAndIndex(resultAllInOneSubdirectoryLength, fileName); + (string, int) TestStatic_GetDirectoryNameAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath) => + GetDirectoryNameAndIndex(propertyConfiguration, filePath); + static (string, int) GetDirectoryNameAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath) => + XPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); - Dictionary TestStatic_GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? directories) => - GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, directories); - static Dictionary GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? directories) => - XPath.GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, directories); + ReadOnlyDictionary TestStatic_GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups) => + GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, jsonGroups); + static ReadOnlyDictionary GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups) => + XPath.GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, jsonGroups); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPersonContainer.cs b/Shared/Models/Stateless/Methods/IPersonContainer.cs index f73a33c..18fc592 100644 --- a/Shared/Models/Stateless/Methods/IPersonContainer.cs +++ b/Shared/Models/Stateless/Methods/IPersonContainer.cs @@ -10,10 +10,10 @@ public interface IPersonContainer static List GetPersonKeys(IEnumerable personContainers) => PersonContainer.GetPersonKeys(personContainers); - List TestStatic_GetPersonContainers(string a2PeopleSingletonDirectory, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension) => - GetPersonContainers(a2PeopleSingletonDirectory, personBirthdayFormat, personCharacters, facesFileNameExtension); - static List GetPersonContainers(string a2PeopleSingletonDirectory, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension) => - PersonContainer.GetPersonContainers(a2PeopleSingletonDirectory, personBirthdayFormat, personCharacters, facesFileNameExtension); + List TestStatic_GetPersonContainers(string a2PeopleSingletonDirectory, string personBirthdayFormat, char[] personCharacters, Properties.IPropertyConfiguration propertyConfiguration, string facesFileNameExtension) => + GetPersonContainers(a2PeopleSingletonDirectory, personBirthdayFormat, personCharacters, propertyConfiguration, facesFileNameExtension); + static List GetPersonContainers(string a2PeopleSingletonDirectory, string personBirthdayFormat, char[] personCharacters, Properties.IPropertyConfiguration propertyConfiguration, string facesFileNameExtension) => + PersonContainer.GetPersonContainers(a2PeopleSingletonDirectory, personBirthdayFormat, personCharacters, propertyConfiguration, facesFileNameExtension); string? TestStatic_VerifyAge(char numberSign, string personDisplayDirectory, string? minusOne, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) => VerifyAge(numberSign, personDisplayDirectory, minusOne, personDisplayDirectoryName, approximateYears, collection); diff --git a/Shared/Models/Stateless/Methods/IProperty.cs b/Shared/Models/Stateless/Methods/IProperty.cs index 2a5729f..53813cd 100644 --- a/Shared/Models/Stateless/Methods/IProperty.cs +++ b/Shared/Models/Stateless/Methods/IProperty.cs @@ -38,16 +38,6 @@ public interface IProperty static (bool?, string[]) IsWrongYear(Models.FileHolder fileHolder, DateTime? dateTimeOriginal, List dateTimes) => Property.IsWrongYear(fileHolder, dateTimeOriginal, dateTimes); - bool TestStatic_NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) => - NameWithoutExtensionIsIdFormat(fileNameWithoutExtension); - static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) => - Property.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension); - - bool TestStatic_NameWithoutExtensionIsIdFormat(Models.FileHolder fileHolder) => - NameWithoutExtensionIsIdFormat(fileHolder); - static bool NameWithoutExtensionIsIdFormat(Models.FileHolder fileHolder) => - NameWithoutExtensionIsIdFormat(fileHolder.NameWithoutExtension); - List TestStatic_GetDateTimes(Models.Property property) => GetDateTimes(property); static List GetDateTimes(Models.Property property) => diff --git a/Shared/Models/Stateless/Methods/Id.cs b/Shared/Models/Stateless/Methods/Id.cs new file mode 100644 index 0000000..ea69b18 --- /dev/null +++ b/Shared/Models/Stateless/Methods/Id.cs @@ -0,0 +1,95 @@ +using System.Text; + +namespace View_by_Distance.Shared.Models.Stateless.Methods; + +internal abstract class Id +{ + + internal static bool NameWithoutExtensionIsIdFormat(Properties.IPropertyConfiguration propertyConfiguration, string fileNameWithoutExtension) + { + bool result; + if (fileNameWithoutExtension.Length < 5 || fileNameWithoutExtension.Length > propertyConfiguration.IntMinValueLength) + result = false; + else + { + bool skipOneAllAreNumbers = fileNameWithoutExtension[1..].All(char.IsNumber); + result = (skipOneAllAreNumbers && fileNameWithoutExtension[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileNameWithoutExtension[0])); + } + return result; + } + + internal static int GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) + { + int result; + StringBuilder results = new(); + if (propertyConfiguration.IntMinValueLength < (propertyConfiguration.ResultAllInOneSubdirectoryLength + 2)) + throw new NotSupportedException(); + for (int i = intelligentId.Length - (propertyConfiguration.ResultAllInOneSubdirectoryLength + 2); i > -1; i--) + _ = results.Append(intelligentId[i]); + _ = results.Append(intelligentId[^3]).Append(intelligentId[^2]); + result = int.Parse(results.ToString()); + if (intelligentId[^1] is '1' or '2') + result *= -1; + else if (intelligentId[^1] is not '9' and not '8') + throw new NotSupportedException(); + return result; + } + + internal static string GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool ignore) + { + string result; + StringBuilder stringBuilder = new(); + if (propertyConfiguration.IntMinValueLength < (propertyConfiguration.ResultAllInOneSubdirectoryLength + 2)) + throw new NotSupportedException(); + int key; + string value; + List resultAllInOneSubdirectoryChars = []; + if (id > -1) + { + key = ignore ? 8 : 9; + value = id.ToString().PadLeft(propertyConfiguration.IntMinValueLength, '0'); + } + else + { + key = ignore ? 2 : 1; + value = id.ToString()[1..].PadLeft(propertyConfiguration.IntMinValueLength, '0'); + } + for (int i = value.Length - propertyConfiguration.ResultAllInOneSubdirectoryLength - 1; i > -1; i--) + _ = stringBuilder.Append(value[i]); + for (int i = value.Length - propertyConfiguration.ResultAllInOneSubdirectoryLength; i < value.Length; i++) + resultAllInOneSubdirectoryChars.Add(value[i]); + result = $"{stringBuilder}{string.Join(string.Empty, resultAllInOneSubdirectoryChars)}{key}"; + return result; + } + + internal static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int index, int id) + { + string result; + string intelligentId = GetIntelligentId(propertyConfiguration, id, ignore: false); + int check = GetId(propertyConfiguration, intelligentId); + if (check != id) + throw new NotSupportedException(); + result = $"{propertyConfiguration.Offset + index}{intelligentId}"; + return result; + } + + internal static int GetDeterministicHashCode(byte[] value) + { + int result; + unchecked + { + int hash1 = (5381 << 16) + 5381; + int hash2 = hash1; + for (int i = 0; i < value.Length; i += 2) + { + hash1 = ((hash1 << 5) + hash1) ^ value[i]; + if (i == value.Length - 1) + break; + hash2 = ((hash2 << 5) + hash2) ^ value[i + 1]; + } + result = hash1 + (hash2 * 1566083941); + } + return result; + } + +} \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/Mapping.cs b/Shared/Models/Stateless/Methods/Mapping.cs index 0164da9..29d2327 100644 --- a/Shared/Models/Stateless/Methods/Mapping.cs +++ b/Shared/Models/Stateless/Methods/Mapping.cs @@ -3,66 +3,48 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class Mapping { - internal static (string?, string?, string?, bool?) GetSegments(string facesFileNameExtension, string fileName) + internal static (string?, string?, bool?) GetSegments(string facesFileNameExtension, FilePath filePath) { - string[] segments = fileName.Split('.'); - string? id; string? extensionLowered; string? wholePercentages; bool? needsFacesFileNameExtension; + string[] segments = filePath.Name.Split('.'); if (segments.Length < 4 || $".{segments[3]}" != facesFileNameExtension) { - id = null; extensionLowered = null; wholePercentages = null; needsFacesFileNameExtension = null; } else { - id = segments[0]; extensionLowered = $".{segments[2]}"; wholePercentages = segments[1]; needsFacesFileNameExtension = segments.Length == 3; } - return new(id, wholePercentages, extensionLowered, needsFacesFileNameExtension); + return new(wholePercentages, extensionLowered, needsFacesFileNameExtension); } - private static (int?, int?) GetConvertedFromSegments(string facesFileNameExtension, string fileName) + private static int? GetConvertedFromSegments(string facesFileNameExtension, FilePath filePath) { - int? id; - int? wholePercentages; - (string? Id, string? WholePercentages, string? ExtensionLowered, bool? Check) segments = GetSegments(facesFileNameExtension, fileName); - if (string.IsNullOrEmpty(segments.Id) || string.IsNullOrEmpty(segments.WholePercentages) || string.IsNullOrEmpty(segments.ExtensionLowered) || segments.Check is null) - { - id = null; - wholePercentages = null; - } - else if (!int.TryParse(segments.Id, out int idValue) || !int.TryParse(segments.WholePercentages, out int wholePercentagesValue)) - { - id = null; - wholePercentages = null; - } + int? result; + (string? WholePercentages, string? ExtensionLowered, bool? Check) segments = GetSegments(facesFileNameExtension, filePath); + if (string.IsNullOrEmpty(segments.WholePercentages) || string.IsNullOrEmpty(segments.ExtensionLowered) || segments.Check is null) + result = null; + else if (!int.TryParse(segments.WholePercentages, out int wholePercentages)) + result = null; else - { - id = idValue; - wholePercentages = wholePercentagesValue; - } - return new(id, wholePercentages); + result = wholePercentages; + return result; } - internal static (int?, int?) GetConverted(string facesFileNameExtension, string file) + internal static int? GetWholePercentages(string facesFileNameExtension, FilePath filePath) { - int? id; int? wholePercentages; - string fileName = Path.GetFileName(file); - if (fileName.Length >= 2 && !fileName[1..].Contains('-')) - (id, wholePercentages) = GetConvertedFromSegments(facesFileNameExtension, fileName); - else - { - id = null; + if (filePath.Name.Length < 2 || filePath.Name[1..].Contains('-')) wholePercentages = null; - } - return new(id, wholePercentages); + else + wholePercentages = GetConvertedFromSegments(facesFileNameExtension, filePath); + return wholePercentages; } internal static int GetAreaPermyriad(int faceAreaPermyriad, int bottom, int height, int left, int right, int top, int width) diff --git a/Shared/Models/Stateless/Methods/PersonContainer.cs b/Shared/Models/Stateless/Methods/PersonContainer.cs index d7c4fee..38751ec 100644 --- a/Shared/Models/Stateless/Methods/PersonContainer.cs +++ b/Shared/Models/Stateless/Methods/PersonContainer.cs @@ -3,17 +3,24 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class PersonContainer { - private static List GetFiles(string personDisplayDirectory) + private static List GetFilePaths(Properties.IPropertyConfiguration propertyConfiguration, string personDisplayDirectory) { - List results = []; + List results = []; string[] files; - string extension; string checkFile; + FilePath filePath; string directoryName; List distinct = []; + Models.FileHolder fileHolder; string fileNameWithoutExtension; string personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); - results.AddRange(Directory.GetFiles(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly)); + files = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string file in files) + { + fileHolder = IFileHolder.Get(file); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); + results.Add(filePath); + } string[] directories = Directory.GetDirectories(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string directory in directories) { @@ -21,10 +28,11 @@ internal abstract class PersonContainer files = Directory.GetFiles(directory, "*", SearchOption.TopDirectoryOnly); foreach (string file in files) { - extension = Path.GetExtension(file); - if (extension is not ".json" and not ".pged") + fileHolder = IFileHolder.Get(file); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); + if (filePath.ExtensionLowered is not ".json" and not ".pged") { - results.Add(file); + results.Add(filePath); continue; } fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); @@ -38,11 +46,13 @@ internal abstract class PersonContainer } else if (fileNameWithoutExtension != directoryName) { - checkFile = Path.Combine(directory, $"{fileNameWithoutExtension}{extension}"); + checkFile = Path.Combine(directory, $"{fileNameWithoutExtension}{filePath.ExtensionLowered}"); if (!File.Exists(checkFile)) { File.Move(file, checkFile); - results.Add(checkFile); + fileHolder = IFileHolder.Get(checkFile); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); + results.Add(filePath); } else { @@ -53,26 +63,31 @@ internal abstract class PersonContainer } continue; } - results.Add(file); + results.Add(filePath); } } return results; } - private static List GetFiles(string facesFileNameExtension, string personDisplayDirectory) + private static List GetFilePaths(string facesFileNameExtension, Properties.IPropertyConfiguration propertyConfiguration, string personDisplayDirectory) { - List results; - int? id; + List results; string checkFile; + FilePath filePath; int? wholePercentages; string? checkDirectory; + Models.FileHolder fileHolder; string[] files = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string file in files) { if (file.EndsWith(".lnk")) continue; - (id, wholePercentages) = IMapping.GetConverted(facesFileNameExtension, file); - if (id is not null && wholePercentages is not null) + fileHolder = IFileHolder.Get(file); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); + if (filePath.Id is null ) + continue; + wholePercentages = IMapping.GetWholePercentages(facesFileNameExtension, filePath); + if (wholePercentages is null) continue; checkDirectory = Path.GetDirectoryName(file); if (string.IsNullOrEmpty(checkDirectory)) @@ -86,20 +101,22 @@ internal abstract class PersonContainer else File.Move(file, checkFile); } - results = GetFiles(personDisplayDirectory); + results = GetFilePaths(propertyConfiguration, personDisplayDirectory); return results; } - private static List GetPersonContainersCollections(string facesFileNameExtension, PersonDirectory personDirectory, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) + private static List GetPersonContainersCollections(string facesFileNameExtension, Properties.IPropertyConfiguration propertyConfiguration, PersonDirectory personDirectory, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) { List results = []; long personKey; string[] files; + FilePath filePath; const int zero = 0; string personKeyDirectory; + Models.FileHolder fileHolder; Models.PersonContainer personContainer; Models.PersonBirthday[] orderedPersonBirthdays; - List personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory); + List personDisplayDirectoryAllFilePaths = GetFilePaths(facesFileNameExtension, propertyConfiguration, personDisplayDirectory); foreach ((string personKeyFormatted, Models.PersonBirthday personBirthday) in collection) { orderedPersonBirthdays = (from l in collection where !l.PersonKeyFormatted.Contains(numberSign) orderby l.PersonBirthday.Value.Ticks descending select l.PersonBirthday).ToArray(); @@ -115,8 +132,15 @@ internal abstract class PersonContainer files = Directory.GetFiles(personKeyDirectory, "*", SearchOption.AllDirectories); if (files.Length == 0) continue; - personDisplayDirectoryAllFiles.AddRange(files.Where(l => l.EndsWith(".rel"))); - personContainer = new(approximateYears, orderedPersonBirthdays, personDisplayDirectoryAllFiles.ToArray(), personDisplayDirectoryName, personKey, personDirectory); + foreach (string file in files) + { + if (!file.EndsWith(".rel")) + continue; + fileHolder = IFileHolder.Get(file); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); + personDisplayDirectoryAllFilePaths.Add(filePath); + } + personContainer = new(approximateYears, orderedPersonBirthdays, new(personDisplayDirectoryAllFilePaths), personDisplayDirectoryName, personKey, personDirectory); results.Add(personContainer); } return results; @@ -153,7 +177,7 @@ internal abstract class PersonContainer return result; } - private static (List, List) GetPersonContainersGroup(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, PersonDirectory personDirectory, string[] personDisplayDirectories) + private static (List, List) GetPersonContainersGroup(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Properties.IPropertyConfiguration propertyConfiguration, PersonDirectory personDirectory, string[] personDisplayDirectories) { List results = []; string? minusOne; @@ -163,9 +187,9 @@ internal abstract class PersonContainer string[] personKeyDirectories; string? personDisplayDirectoryName; Models.PersonContainer personContainer; - List personDisplayDirectoryAllFiles; List personContainers; List<(string, Models.PersonBirthday)> collection; + List personDisplayDirectoryAllFilePaths; foreach (string personDisplayDirectory in personDisplayDirectories) { personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); @@ -185,20 +209,20 @@ internal abstract class PersonContainer continue; if (collection.Count > 0) { - personContainers = GetPersonContainersCollections(facesFileNameExtension, personDirectory, numberSign, personDisplayDirectory, personDisplayDirectoryName, approximateYears, collection); + personContainers = GetPersonContainersCollections(facesFileNameExtension, propertyConfiguration, personDirectory, numberSign, personDisplayDirectory, personDisplayDirectoryName, approximateYears, collection); results.AddRange(personContainers); } else { - personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory); - personContainer = new(approximateYears, personDisplayDirectoryAllFiles.ToArray(), personDisplayDirectoryName, personDirectory); + personDisplayDirectoryAllFilePaths = GetFilePaths(facesFileNameExtension, propertyConfiguration, personDisplayDirectory); + personContainer = new(approximateYears, new(personDisplayDirectoryAllFilePaths), personDisplayDirectoryName, personDirectory); results.Add(personContainer); } } return new(changes, results); } - private static (List, List) GetPersonContainersInnerGroups(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, string groupDirectory, string groupDirectoryName) + private static (List, List) GetPersonContainersInnerGroups(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Properties.IPropertyConfiguration propertyConfiguration, string groupDirectory, string groupDirectoryName) { List results = []; string[] segments; @@ -215,7 +239,7 @@ internal abstract class PersonContainer if (@char == exclamationPoint) { personDirectory = new(@char, "Ignore", 'U', 'U', 'U'); - (changes, collection) = GetPersonContainersGroup(personBirthdayFormat, facesFileNameExtension, personCharacters, personDirectory, innerGroupDirectories); + (changes, collection) = GetPersonContainersGroup(personBirthdayFormat, facesFileNameExtension, personCharacters, propertyConfiguration, personDirectory, innerGroupDirectories); allChanges.AddRange(changes); results.AddRange(collection); } @@ -237,7 +261,7 @@ internal abstract class PersonContainer continue; personDirectory = new(@char, innerGroupDirectoryName, segments[zero][zero], segments[1][zero], segments[2][zero]); personDisplayDirectories = Directory.GetDirectories(innerGroupDirectory, "*", SearchOption.TopDirectoryOnly); - (changes, collection) = GetPersonContainersGroup(personBirthdayFormat, facesFileNameExtension, personCharacters, personDirectory, personDisplayDirectories); + (changes, collection) = GetPersonContainersGroup(personBirthdayFormat, facesFileNameExtension, personCharacters, propertyConfiguration, personDirectory, personDisplayDirectories); allChanges.AddRange(changes); results.AddRange(collection); } @@ -245,7 +269,7 @@ internal abstract class PersonContainer return new(allChanges, results); } - private static List GetPersonContainersGroups(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, string[] groupDirectories) + private static List GetPersonContainersGroups(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Properties.IPropertyConfiguration propertyConfiguration, string[] groupDirectories) { List results; List changes; @@ -260,7 +284,7 @@ internal abstract class PersonContainer groupDirectoryName = Path.GetFileName(groupDirectory); if (personCharacters[i] != groupDirectoryName.First()) continue; - (changes, collection) = GetPersonContainersInnerGroups(personBirthdayFormat, facesFileNameExtension, personCharacters, groupDirectory, groupDirectoryName); + (changes, collection) = GetPersonContainersInnerGroups(personBirthdayFormat, facesFileNameExtension, personCharacters, propertyConfiguration, groupDirectory, groupDirectoryName); allChanges.AddRange(changes); personContainers.AddRange(collection); } @@ -271,7 +295,7 @@ internal abstract class PersonContainer return results; } - internal static List GetPersonContainers(string a2PeopleSingletonDirectory, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension) + internal static List GetPersonContainers(string a2PeopleSingletonDirectory, string personBirthdayFormat, char[] personCharacters, Properties.IPropertyConfiguration propertyConfiguration, string facesFileNameExtension) { List results; if (!Directory.Exists(a2PeopleSingletonDirectory)) @@ -287,7 +311,7 @@ internal abstract class PersonContainer if (groupDirectories.Length == 0) results = []; else - results = GetPersonContainersGroups(personBirthdayFormat, facesFileNameExtension, personCharacters, groupDirectories); + results = GetPersonContainersGroups(personBirthdayFormat, facesFileNameExtension, personCharacters, propertyConfiguration, groupDirectories); return results; } diff --git a/Shared/Models/Stateless/Methods/Property.cs b/Shared/Models/Stateless/Methods/Property.cs index 3ab1c7c..b70ed78 100644 --- a/Shared/Models/Stateless/Methods/Property.cs +++ b/Shared/Models/Stateless/Methods/Property.cs @@ -274,18 +274,4 @@ internal abstract class Property return result; } - internal static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) - { - bool result; - int intMinValueLength = int.MinValue.ToString().Length; - if (fileNameWithoutExtension.Length < 5 || fileNameWithoutExtension.Length > intMinValueLength) - result = false; - else - { - bool skipOneAllAreNumbers = fileNameWithoutExtension[1..].All(l => char.IsNumber(l)); - result = (skipOneAllAreNumbers && fileNameWithoutExtension[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileNameWithoutExtension[0])); - } - return result; - } - } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/XDirectory.cs b/Shared/Models/Stateless/Methods/XDirectory.cs index 01f291d..b36e727 100644 --- a/Shared/Models/Stateless/Methods/XDirectory.cs +++ b/Shared/Models/Stateless/Methods/XDirectory.cs @@ -5,8 +5,6 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract partial class XDirectory { - private record SortedRecord(Models.FileHolder FileHolder, bool NameWithoutExtensionIsIdFormat, int? Id); - private static int GetCeilingAverage(List fileCollection) { List counts = []; @@ -39,6 +37,8 @@ internal abstract partial class XDirectory fileSearchFilter = string.Concat('*', fileSearchFilter); if (!directorySearchFilter.Contains('*')) directorySearchFilter = string.Concat('*', directorySearchFilter); + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); results.Add(Directory.GetFiles(directory, fileSearchFilter, SearchOption.TopDirectoryOnly)); string[] directories = Directory.GetDirectories(directory, directorySearchFilter, SearchOption.TopDirectoryOnly); foreach (string innerDirectory in directories) @@ -185,46 +185,28 @@ internal abstract partial class XDirectory return results; } - private static void IsUniqueLoop(string resultAllInOne, string resultAllInOneDirectory, int resultAllInOneSubdirectoryLength, FilePair item, List<(string, string)> rename) + private static void IsNotUniqueLoop(Properties.IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, FilePair filePair, List<(string, string)> rename) { - string fileName; - string directoryName; - foreach (string path in item.Collection) + int length = propertyConfiguration.RootDirectory.Length; + foreach (string path in filePair.Collection) { - if (path.Contains(resultAllInOne)) + if (filePair.Match is null || path != filePair.Match) continue; - fileName = Path.GetFileName(path); - (directoryName, _) = IPath.GetDirectoryNameAndIndex(resultAllInOneSubdirectoryLength, fileName); - rename.Add(new(path, Path.Combine(resultAllInOneDirectory, directoryName, fileName))); + rename.Add(new(path, string.Concat(jsonGroupDirectory, filePair.Path[length..], extension))); } } - private static void IsNotUniqueLoop(string directory, string resultAllInOne, string jsonGroupDirectory, string extension, FilePair item, List<(string, string)> rename) - { - int length = directory.Length; - foreach (string path in item.Collection) - { - if (!path.Contains(resultAllInOne)) - continue; - if (item.Match is null || path != item.Match) - continue; - rename.Add(new(path, string.Concat(jsonGroupDirectory, item.Path[length..], extension))); - } - } - - internal static int MaybeMove(string directory, string resultAllInOne, int resultAllInOneSubdirectoryLength, List filePairs, string jsonGroupDirectory, string extension) + internal static int MaybeMove(Properties.IPropertyConfiguration propertyConfiguration, List filePairs, string jsonGroupDirectory, string extension) { FileInfo? toFileInfo; FileInfo fromFileInfo; string checkDirectory; List<(string, string)> rename = []; - string resultAllInOneDirectory = Path.Combine(jsonGroupDirectory, resultAllInOne); - foreach (FilePair item in filePairs) + foreach (FilePair filePair in filePairs) { - if (item.IsUnique) - IsUniqueLoop(resultAllInOne, resultAllInOneDirectory, resultAllInOneSubdirectoryLength, item, rename); - else - IsNotUniqueLoop(directory, resultAllInOne, jsonGroupDirectory, extension, item, rename); + if (filePair.IsUnique) + continue; + IsNotUniqueLoop(propertyConfiguration, jsonGroupDirectory, extension, filePair, rename); } foreach ((string from, string to) in rename) { @@ -283,153 +265,109 @@ internal abstract partial class XDirectory } } - internal static (bool, int?) GetId(short sortOrderOnlyLengthIndex, Models.FileHolder fileHolder) + private static FilePath[] GetSortedRecords(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection filesCollection) { - int? id; - short? multiplier; - char negativeMarker; - int absoluteValueOfId; - bool nameWithoutExtensionIsIdFormat = IProperty.NameWithoutExtensionIsIdFormat(fileHolder); - bool nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileHolder, sortOrderOnlyLengthIndex); - if (!nameWithoutExtensionIsIdFormat && !nameWithoutExtensionIsPaddedIdFormat) - id = null; - else if (nameWithoutExtensionIsIdFormat) - { - if (!int.TryParse(fileHolder.NameWithoutExtension, out absoluteValueOfId)) - id = null; - else - id = absoluteValueOfId; - } - else - { - negativeMarker = fileHolder.NameWithoutExtension[sortOrderOnlyLengthIndex - 2]; - if (negativeMarker == '7') - multiplier = 1; - else if (negativeMarker == '3') - multiplier = -1; - else - multiplier = null; - if (!int.TryParse(fileHolder.NameWithoutExtension[sortOrderOnlyLengthIndex..], out absoluteValueOfId)) - id = null; - else - { - id = absoluteValueOfId * multiplier; - if (id is null || !fileHolder.NameWithoutExtension.EndsWith(id.Value.ToString()[1..])) - id = null; - } - } - return (nameWithoutExtensionIsIdFormat, id); - } - - private static SortedRecord[] GetSortedRecords(int offset, ReadOnlyCollection filesCollection) - { - List results = []; - int? id; + List results = []; + FilePath filePath; Models.FileHolder fileHolder; - bool nameWithoutExtensionIsIdFormat; - short sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex(offset); foreach (string[] files in filesCollection) { foreach (string file in files) { - fileHolder = new(file); - (nameWithoutExtensionIsIdFormat, id) = GetId(sortOrderOnlyLengthIndex, fileHolder); - results.Add(new(fileHolder, nameWithoutExtensionIsIdFormat, id)); + fileHolder = IFileHolder.Get(file); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); + results.Add(filePath); } } - return (from l in results orderby l.FileHolder.CreationTime, l.FileHolder.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<(Models.FileHolder, string?, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection filesCollection, string[] directories, Action? tick) + internal static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection filesCollection, string[] directories, Action? tick) { - List<(Models.FileHolder, string?, string)> results = []; + List<(FilePath, string)> results = []; string paddedId; string checkFile; string directory; FileInfo fileInfo; + FilePath filePath; int directoryIndex; + bool ignore = false; string paddedIdFile; bool wrapped = false; - string directoryName; + string intelligentId; bool paddedCheck = false; string fileDirectoryName; - SortedRecord sortedRecord; - string? alternateCheckFile; - string? alternateDirectory; - Models.FileHolder fileHolder; List distinctIds = []; List distinct = []; + Models.FileHolder fileHolder; List distinctDirectories = []; - int intMinValueLength = int.MinValue.ToString().Length; - SortedRecord[] sortedRecords = GetSortedRecords(propertyConfiguration.Offset, filesCollection); - string? alternateResultAllInOne = !propertyConfiguration.ResultAllInOne.Contains(' ') ? null : propertyConfiguration.ResultAllInOne.Replace(' ', '-'); + FilePath[] sortedRecords = GetSortedRecords(propertyConfiguration, filesCollection); for (int i = 0; i < sortedRecords.Length; i++) { tick?.Invoke(); - sortedRecord = sortedRecords[i]; - fileHolder = sortedRecord.FileHolder; - if (fileHolder.Name.EndsWith("len") || fileHolder.ExtensionLowered == ".id" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null) + filePath = sortedRecords[i]; + if (filePath.Name.EndsWith("len") || filePath.ExtensionLowered == ".id" || filePath.ExtensionLowered == ".lsv" || filePath.DirectoryName is null) continue; - (directoryName, directoryIndex) = IPath.GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, fileHolder.NameWithoutExtension); - fileDirectoryName = Path.GetFileName(fileHolder.DirectoryName); - if (fileDirectoryName.Length < propertyConfiguration.ResultAllInOneSubdirectoryLength + 3 || !fileHolder.Name.StartsWith(fileDirectoryName)) + (_, directoryIndex) = IPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); + fileDirectoryName = Path.GetFileName(filePath.DirectoryName); + if (fileDirectoryName.Length < propertyConfiguration.ResultAllInOneSubdirectoryLength + 3 || !filePath.Name.StartsWith(fileDirectoryName)) { if (wrapped) continue; directory = directories[directoryIndex]; - if (alternateResultAllInOne is null) - alternateDirectory = null; - else - alternateDirectory = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(directory)) ?? directory, alternateResultAllInOne, directoryName); } else { if (!wrapped) wrapped = true; - alternateDirectory = null; directory = Path.Combine(directories[directoryIndex], fileDirectoryName); } - if (ifCanUseId && sortedRecord.NameWithoutExtensionIsIdFormat && sortedRecord.Id is not null && fileHolder.DirectoryName is not null) + if (ifCanUseId && filePath.IsIntelligentIdFormat && filePath.Id is not null && filePath.DirectoryName is not null) { - paddedId = IDirectory.GetPaddedId(intMinValueLength, propertyConfiguration.Offset + i, sortedRecord.Id.Value); - paddedIdFile = Path.Combine(fileHolder.DirectoryName, $"{paddedId}{fileHolder.ExtensionLowered}"); + paddedId = IId.GetPaddedId(propertyConfiguration, i, filePath.Id.Value); + paddedIdFile = Path.Combine(filePath.DirectoryName, $"{paddedId}{filePath.ExtensionLowered}"); if (!File.Exists(paddedIdFile)) { - File.Move(fileHolder.FullName, paddedIdFile); - fileHolder = new(paddedIdFile); + File.Move(filePath.FullName, paddedIdFile); + fileInfo = new(paddedIdFile); + fileHolder = Models.FileHolder.Get(fileInfo); + filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); if (!paddedCheck) paddedCheck = true; } } - if (ifCanUseId) - checkFile = Path.Combine(directory, $"{sortedRecord.Id}{fileHolder.ExtensionLowered}"); + if (filePath.IsIntelligentIdFormat || !ifCanUseId) + checkFile = Path.Combine(directory, $"{filePath.NameWithoutExtension}{filePath.ExtensionLowered}"); else - checkFile = Path.Combine(directory, $"{fileHolder.NameWithoutExtension}{fileHolder.ExtensionLowered}"); - if ((sortedRecord.Id is not null && distinctIds.Contains(sortedRecord.Id.Value)) || distinct.Contains(checkFile)) { - if (string.IsNullOrEmpty(fileHolder.DirectoryName)) + if (filePath.Id is null) + throw new NullReferenceException(nameof(filePath.Id)); + intelligentId = IId.GetIntelligentId(propertyConfiguration, filePath.Id.Value, ignore); + checkFile = Path.Combine(directory, $"{intelligentId}{filePath.ExtensionLowered}"); + } + if ((filePath.Id is not null && distinctIds.Contains(filePath.Id.Value)) || distinct.Contains(checkFile)) + { + if (string.IsNullOrEmpty(filePath.DirectoryName)) continue; if (!copyDuplicates) continue; - alternateDirectory = null; for (int j = 1; j < int.MaxValue; j++) { fileInfo = new(checkFile); - if (!fileInfo.Exists || fileHolder.Length == fileInfo.Length && fileHolder.LastWriteTime == fileInfo.LastWriteTime) - checkFile = Path.Combine(directory, $"{fileHolder.NameWithoutExtension}.{j}dup{fileHolder.ExtensionLowered}"); + if (!fileInfo.Exists || filePath.Length == fileInfo.Length && filePath.LastWriteTicks == fileInfo.LastWriteTime.Ticks) + checkFile = Path.Combine(directory, $"{filePath.NameWithoutExtension}.{j}dup{filePath.ExtensionLowered}"); else - checkFile = Path.Combine(directory, $"{fileHolder.NameWithoutExtension}.{j}why{fileHolder.ExtensionLowered}"); - if (sortedRecord.Id is not null) + checkFile = Path.Combine(directory, $"{filePath.NameWithoutExtension}.{j}why{filePath.ExtensionLowered}"); + if (filePath.Id is not null) { - if (distinctIds.Contains(sortedRecord.Id.Value)) + if (distinctIds.Contains(filePath.Id.Value)) continue; - distinctIds.Add(sortedRecord.Id.Value); + distinctIds.Add(filePath.Id.Value); } if (distinct.Contains(checkFile)) continue; - alternateCheckFile = null; distinct.Add(checkFile); - results.Add(new(fileHolder, alternateCheckFile, checkFile)); + results.Add(new(filePath, checkFile)); if (!distinctDirectories.Contains(directory)) distinctDirectories.Add(directory); break; @@ -437,17 +375,9 @@ internal abstract partial class XDirectory continue; } distinct.Add(checkFile); - if (sortedRecord.Id is not null) - distinctIds.Add(sortedRecord.Id.Value); - if (string.IsNullOrEmpty(alternateDirectory)) - alternateCheckFile = null; - else - { - alternateCheckFile = Path.Combine(alternateDirectory, $"{sortedRecord.Id}{fileHolder.ExtensionLowered}.tsv"); - if (!distinctDirectories.Contains(alternateDirectory)) - distinctDirectories.Add(alternateDirectory); - } - results.Add(new(fileHolder, alternateCheckFile, checkFile)); + if (filePath.Id is not null) + distinctIds.Add(filePath.Id.Value); + results.Add(new(filePath, checkFile)); if (!distinctDirectories.Contains(directory)) distinctDirectories.Add(directory); } @@ -456,30 +386,28 @@ internal abstract partial class XDirectory return (distinctDirectories.ToArray(), results); } - internal static List CopyOrMove(List<(Models.FileHolder, string?, string)> toDoCollection, bool move, bool moveBack, Action? tick) + internal static List CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) { List results = []; FileInfo fileInfo; - foreach ((Models.FileHolder fileHolder, string? alternateFile, string to) in toDoCollection) + foreach ((FilePath filePath, string to) in toDoCollection) { tick?.Invoke(); fileInfo = new(to); - if (!fileInfo.Exists && alternateFile is not null) - _ = XPath.WriteAllText(alternateFile, fileHolder.FullName, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); if (fileInfo.Exists) { - if (fileHolder.Length != fileInfo.Length || fileHolder.LastWriteTime != fileInfo.LastWriteTime) + if (filePath.Length != fileInfo.Length || filePath.LastWriteTicks != fileInfo.LastWriteTime.Ticks) fileInfo.Delete(); else continue; } - results.Add(fileHolder.NameWithoutExtension); + results.Add(filePath.NameWithoutExtension); try { if (move || moveBack) - File.Move(fileHolder.FullName, to); + File.Move(filePath.FullName, to); else - File.Copy(fileHolder.FullName, to); + File.Copy(filePath.FullName, to); } catch (Exception) { } } diff --git a/Shared/Models/Stateless/Methods/XPath.cs b/Shared/Models/Stateless/Methods/XPath.cs index cdc8dd2..8fd7c42 100644 --- a/Shared/Models/Stateless/Methods/XPath.cs +++ b/Shared/Models/Stateless/Methods/XPath.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using View_by_Distance.Shared.Models.Properties; namespace View_by_Distance.Shared.Models.Stateless.Methods; @@ -283,24 +284,35 @@ internal abstract class XPath return (result, converted); } - internal static Dictionary GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? directories) + internal static (string, int) GetDirectoryNameAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath) + { + int converted; + string result; + if (filePath.Id is not null) + (result, converted) = GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, filePath.Id.Value.ToString()); + else + (result, converted) = GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, filePath.FileNameFirstSegment); + return (result, converted); + } + + internal static ReadOnlyDictionary GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups) { Dictionary results = []; + int converted = int.Parse($"1{new string('0', propertyConfiguration.ResultAllInOneSubdirectoryLength)}"); string directory; string checkDirectory; - int converted = int.Parse($"1{new string('0', propertyConfiguration.ResultAllInOneSubdirectoryLength)}"); int plusOne = converted + 1; List collection = []; - if (directories is not null) + if (jsonGroups is not null) { - foreach (string key in directories) + foreach (string jsonGroup in jsonGroups) { if (resultsFullGroupDirectory is null) continue; collection.Clear(); for (int i = 0; i < plusOne; i++) { - if (string.IsNullOrEmpty(key)) + if (string.IsNullOrEmpty(jsonGroup)) { if (i == converted) checkDirectory = Path.GetFullPath(Path.Combine(resultsFullGroupDirectory, new('-', propertyConfiguration.ResultAllInOneSubdirectoryLength))); @@ -309,7 +321,7 @@ internal abstract class XPath } else { - directory = Path.Combine(resultsFullGroupDirectory, key, propertyConfiguration.ResultAllInOne); + directory = Path.Combine(resultsFullGroupDirectory, jsonGroup); if (i == converted) checkDirectory = Path.GetFullPath(Path.Combine(directory, new('-', propertyConfiguration.ResultAllInOneSubdirectoryLength))); else @@ -319,13 +331,13 @@ internal abstract class XPath _ = Directory.CreateDirectory(checkDirectory); collection.Add(checkDirectory); } - if (!string.IsNullOrEmpty(key)) - results.Add(key, collection.ToArray()); + if (!string.IsNullOrEmpty(jsonGroup)) + results.Add(jsonGroup, collection.ToArray()); else results.Add(propertyConfiguration.ResultAllInOne, collection.ToArray()); } } - return results; + return new(results); } } \ No newline at end of file diff --git a/Tests/UnitTestHardCoded.cs b/Tests/UnitTestHardCoded.cs index 1f448c9..b4732c7 100644 --- a/Tests/UnitTestHardCoded.cs +++ b/Tests/UnitTestHardCoded.cs @@ -86,7 +86,7 @@ public partial class UnitTestHardCoded [TestMethod] public void TestMethodGetApproximateYears() { - string personDisplayDirectory = "D:/1-Images-A/Images-dd514b88-Results/A2)People/dd514b88/{}/^/Sydney Dupray^9"; + string personDisplayDirectory = "D:/1-Images-A/Images-4083e56a-Results/A2)People/4083e56a/{}/^/Sydney Dupray^9"; if (Directory.Exists(Directory.GetDirectoryRoot(personDisplayDirectory)) && Directory.Exists(personDisplayDirectory)) { char numberSign = '#'; @@ -189,7 +189,7 @@ public partial class UnitTestHardCoded [TestMethod] public void TestMethodRenameAbandoned() { - string directory = "D:/1-Images-A/Images-dd514b88-Results/A2)People/dd514b88/{}/!/Abandoned"; + string directory = "D:/1-Images-A/Images-4083e56a-Results/A2)People/4083e56a/{}/!/Abandoned"; if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory)) { string checkFile; @@ -209,7 +209,7 @@ public partial class UnitTestHardCoded [TestMethod] public void TestMethodRenameDelete() { - string directory = "D:/1-Images-A/Images-dd514b88-Results/A)Property/dd514b88/{}"; + string directory = "D:/1-Images-A/Images-4083e56a-Results/A)Property/4083e56a/{}"; if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory)) { string checkFile; @@ -229,7 +229,7 @@ public partial class UnitTestHardCoded [TestMethod] public void TestMethodRenameOld() { - string directory = "D:/1-Images-A/Images-dd514b88-Results/E)Distance/dd514b88/()"; + string directory = "D:/1-Images-A/Images-4083e56a-Results/E)Distance/4083e56a/()"; if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory)) { string checkFile; @@ -250,7 +250,7 @@ public partial class UnitTestHardCoded public void TestMethodRenameDup() { string directory; - directory = "D:/1-Images-A/Images-dd514b88-Results/E)Distance/dd514b88/()"; + directory = "D:/1-Images-A/Images-4083e56a-Results/E)Distance/4083e56a/()"; if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory)) { string checkFile; @@ -264,7 +264,7 @@ public partial class UnitTestHardCoded } Assert.IsTrue(true); } - directory = "D:/1-Images-A/Images-dd514b88-Results/A2)People/dd514b88/{}/!"; + directory = "D:/1-Images-A/Images-4083e56a-Results/A2)People/4083e56a/{}/!"; if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory)) { string checkFile; @@ -284,9 +284,9 @@ public partial class UnitTestHardCoded [TestMethod] public void TestMethodRename() { - // string directory = "D:/2-Images-B/Not-Copy-Copy-dd514b88"; - string directory = "D:/1-Images-A/Images-dd514b88"; - // string directory = "D:/2-Images-B/Not-Copy-Copy-dd514b88"; + // string directory = "D:/2-Images-B/Not-Copy-Copy-4083e56a"; + string directory = "D:/1-Images-A/Images-4083e56a"; + // string directory = "D:/2-Images-B/Not-Copy-Copy-4083e56a"; if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory)) { string[] directories = Directory.GetDirectories(directory, "*;*", SearchOption.AllDirectories); @@ -303,7 +303,7 @@ public partial class UnitTestHardCoded [TestMethod] public void TestMethodRenameForUnkown() { - string directory = "D:/1-Images-A/Images-dd514b88-Results/E)Distance/dd514b88/(RectInt-2023-06-19-less-0.99)"; + string directory = "D:/1-Images-A/Images-4083e56a-Results/E)Distance/4083e56a/(RectInt-2023-06-19-less-0.99)"; if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory)) { string[] files = Directory.GetFiles(directory, "*.unk", SearchOption.AllDirectories); @@ -316,7 +316,7 @@ public partial class UnitTestHardCoded [TestMethod] public void TestMethodRenameForTicks() { - string directory = "D:/1-Images-A/Images-dd514b88-Results/A2)People/dd514b88/([])/ged"; + string directory = "D:/1-Images-A/Images-4083e56a-Results/A2)People/4083e56a/([])/ged"; if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory)) { string checkName; diff --git a/Tests/UnitTestResize.cs b/Tests/UnitTestResize.cs index a3be45a..a70479a 100644 --- a/Tests/UnitTestResize.cs +++ b/Tests/UnitTestResize.cs @@ -154,11 +154,11 @@ public class UnitTestResize _ = resize.ToString(); bool isUniqueFileName = false; bool? isNotUniqueAndNeedsReview = null; - FileHolder sourceDirectoryFileHolder = new(".json"); + FileHolder sourceDirectoryFileHolder = IFileHolder.Get(".json"); string sourceDirectory = Path.GetFullPath(Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName)); - FileHolder fileHolder = new(Path.Combine(sourceDirectory, sourceFileName)); - (_, int? id) = IDirectory.GetId(_PropertyConfiguration.Offset, fileHolder); - Assert.IsNotNull(id); + FileHolder fileHolder = IFileHolder.Get(Path.Combine(sourceDirectory, sourceFileName)); + FilePath filePath = FilePath.Get(_PropertyConfiguration, fileHolder, index: null); + Assert.IsNotNull(filePath.Id); string relativePath = IPath.GetRelativePath(fileHolder.FullName, length); string propertyLogicSourceDirectory = Path.GetFullPath(Path.Combine(aPropertySingletonDirectory, sourceDirectoryName)); propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, propertyLogicSourceDirectory); @@ -166,7 +166,7 @@ public class UnitTestResize resize.SetAngleBracketCollection(cResultsFullGroupDirectory, sourceDirectory); resize.Update(cResultsFullGroupDirectory); blurHasher.Update(cResultsFullGroupDirectory); - item = new(sourceDirectoryFileHolder, relativePath, fileHolder, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, property, false, false, false); + item = new(filePath, sourceDirectoryFileHolder, relativePath, fileHolder, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, property, false, false, false); Assert.IsNotNull(item.ImageFileHolder); if (item.Property is null) { @@ -175,15 +175,15 @@ public class UnitTestResize } if (property is null || item.Property is null) throw new NullReferenceException(nameof(property)); - resizedFileHolder = resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber, id.Value); + resizedFileHolder = resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber, filePath.Id.Value); item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder); MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item); - Dictionary outputResolutionToResize = resize.GetResizeKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, item.Property, mappingFromItem); + Dictionary outputResolutionToResize = resize.GetResizeKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem); Assert.IsNotNull(mappingFromItem.ResizedFileHolder); resize.SaveResizedSubfile(_PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize); string blurHash = blurHasher.Encode(resizedFileHolder); Assert.IsNotNull(blurHash); - ReadOnlyDictionary metadataExtractorDirectories = metadata.GetMetadataCollection(subFileTuples, parseExceptions, changesFrom, mappingFromItem); + ReadOnlyDictionary metadataExtractorDirectories = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem); string json = JsonSerializer.Serialize(metadataExtractorDirectories, ReadOnlyDictionaryStringMetadataExtractorDirectorySourceGenerationContext.Default.ReadOnlyDictionaryStringMetadataExtractorDirectory); File.WriteAllText("../../../.json", json); MetadataExtractor.GeoLocation? geoLocation = Metadata.Models.Stateless.Methods.IMetadata.GeoLocation(metadataExtractorDirectories); diff --git a/TestsWithFaceRecognitionDotNet/UnitTestFace.cs b/TestsWithFaceRecognitionDotNet/UnitTestFace.cs index db1f880..873bd8e 100644 --- a/TestsWithFaceRecognitionDotNet/UnitTestFace.cs +++ b/TestsWithFaceRecognitionDotNet/UnitTestFace.cs @@ -227,11 +227,11 @@ public class UnitTestFace _ = resize.ToString(); bool isUniqueFileName = false; bool? isNotUniqueAndNeedsReview = null; - FileHolder sourceDirectoryFileHolder = new(".json"); + FileHolder sourceDirectoryFileHolder = IFileHolder.Get(".json"); string sourceDirectory = Path.GetFullPath(Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName)); - FileHolder fileHolder = new(Path.Combine(sourceDirectory, sourceFileName)); - (_, int? id) = IDirectory.GetId(_PropertyConfiguration.Offset, fileHolder); - Assert.IsNotNull(id); + FileHolder fileHolder = IFileHolder.Get(Path.Combine(sourceDirectory, sourceFileName)); + FilePath filePath = FilePath.Get(_PropertyConfiguration, fileHolder, index: null); + Assert.IsNotNull(filePath.Id); string relativePath = IPath.GetRelativePath(fileHolder.FullName, length); string propertyLogicSourceDirectory = Path.GetFullPath(Path.Combine(aPropertySingletonDirectory, sourceDirectoryName)); propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, propertyLogicSourceDirectory); @@ -239,7 +239,7 @@ public class UnitTestFace resize.SetAngleBracketCollection(cResultsFullGroupDirectory, sourceDirectory); resize.Update(cResultsFullGroupDirectory); blurHasher.Update(cResultsFullGroupDirectory); - item = new(sourceDirectoryFileHolder, relativePath, fileHolder, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, property, false, false, false); + item = new(filePath, sourceDirectoryFileHolder, relativePath, fileHolder, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, property, false, false, false); Assert.IsNotNull(item.ImageFileHolder); if (item.Property is null) { @@ -248,16 +248,16 @@ public class UnitTestFace } if (property is null || item.Property is null) throw new NullReferenceException(nameof(property)); - resizedFileHolder = resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber, id.Value); + resizedFileHolder = resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber, filePath.Id.Value); item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder); MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item); IReadOnlyList directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(resizedFileHolder.FullName); - Dictionary outputResolutionToResize = resize.GetResizeKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, item.Property, mappingFromItem); + Dictionary outputResolutionToResize = resize.GetResizeKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem); Assert.IsNotNull(mappingFromItem.ResizedFileHolder); resize.SaveResizedSubfile(_PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize); string blurHash = blurHasher.Encode(resizedFileHolder); Assert.IsNotNull(blurHash); - ReadOnlyDictionary? metadataExtractorDirectories = metadata.GetMetadataCollection(subFileTuples, parseExceptions, changesFrom, mappingFromItem); + ReadOnlyDictionary? metadataExtractorDirectories = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem); string json = JsonSerializer.Serialize(metadataExtractorDirectories, ReadOnlyDictionaryStringMetadataExtractorDirectorySourceGenerationContext.Default.ReadOnlyDictionaryStringMetadataExtractorDirectory); File.WriteAllText("../../../.json", json); Image image = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName);