diff --git a/Delete-By-Relative/DeleteByRelative.cs b/Delete-By-Relative/DeleteByRelative.cs index f927b24..168d27d 100644 --- a/Delete-By-Relative/DeleteByRelative.cs +++ b/Delete-By-Relative/DeleteByRelative.cs @@ -59,7 +59,7 @@ public class DeleteByRelative throw new NullReferenceException(nameof(alongSideDirectory)); string deleteLog = Path.Combine(alongSideDirectory, $"{directoryName}-{ticks}.tsv"); File.WriteAllLines(deleteLog, deleteFiles); - if (deleteFiles.Any()) + if (deleteFiles.Count > 0) { log.Information($"Ready to delete {deleteFiles.Count} file(s)? See <{deleteLog}>"); for (int y = 0; y < int.MaxValue; y++) diff --git a/Distance/Models/_E_Distance.cs b/Distance/Models/_E_Distance.cs index 3c8f2de..c280d6c 100644 --- a/Distance/Models/_E_Distance.cs +++ b/Distance/Models/_E_Distance.cs @@ -1,4 +1,5 @@ using ShellProgressBar; +using System.Collections.ObjectModel; using System.Text.Json; using View_by_Distance.Distance.Models.Stateless; using View_by_Distance.FaceRecognitionDotNet; @@ -122,7 +123,7 @@ public partial class E_Distance (Face, double?)[] results; List<(Face Face, double? Length)> collection = GetValues(mappingFromItem, intersectFaces, modelsFaceEncoding); results = (from l in collection where l.Length < _RangeDistanceToleranceAverage orderby l.Length select l).Take(1).ToArray(); - if (results.Any()) + if (results.Length > 0) { (Face _, double? length) = results.First(); _Debug.Add(length); @@ -199,7 +200,7 @@ public partial class E_Distance } } - public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, MappingFromItem mappingFromItem, List faces, List> locationContainers) + public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, MappingFromItem mappingFromItem, List faces, ReadOnlyCollection> locationContainers) { string? json; string fileName; @@ -219,7 +220,7 @@ public partial class E_Distance if (locationContainer.FromDistanceContent && _DuplicateMappedFaceFiles.Contains(fileName)) continue; checkFaces.Clear(); - if (!locationContainer.Directories.Any()) + if (locationContainer.Directories.Count == 0) { if (locationContainer.FromDistanceContent) throw new NullReferenceException(nameof(locationContainer.Directories)); @@ -232,7 +233,7 @@ public partial class E_Distance MoveUnableToMatch(locationContainer.File); continue; } - if (filteredFaces.Any()) + if (filteredFaces.Length > 0) checkFaces.AddRange(GetMatchingFacesByFaceEncoding(filteredFaces, json)); if (checkFaces.Count == 1) _Debug.Add(0); @@ -242,14 +243,14 @@ public partial class E_Distance modelsFaceEncoding = JsonSerializer.Deserialize(json); if (modelsFaceEncoding is null) throw new NotSupportedException(); - if (filteredFaces.Any()) + if (filteredFaces.Length > 0) { intersectFaces = Shared.Models.Stateless.Methods.ILocation.FilterByIntersect(filteredFaces, _RectangleIntersectMinimum, locationContainer.WholePercentages); - if (intersectFaces.Any()) + if (intersectFaces.Count > 0) checkFaces.AddRange(GetClosestFaceByDistanceIgnoringTolerance(mappingFromItem, intersectFaces, modelsFaceEncoding)); } } - if (!checkFaces.Any()) + if (checkFaces.Count == 0) { if (_DistanceMoveUnableToMatch) MoveUnableToMatch(locationContainer.File); @@ -279,7 +280,7 @@ public partial class E_Distance { lock (_AllMappedFaceFiles) matches = (from l in _AllMappedFaceFiles where l != locationContainer.File && Path.GetFileName(l) == fileName select l).ToArray(); - if (locationContainer.FromDistanceContent && matches.Any()) + if (locationContainer.FromDistanceContent && matches.Length > 0) AppendMatchingDuplicates(locationContainer.File, matches); } if (!locationContainer.FromDistanceContent) @@ -296,14 +297,14 @@ public partial class E_Distance if (_Log is null) throw new NullReferenceException(nameof(_Log)); double?[] debug = (from l in _Debug where l is null or not 0 select l).ToArray(); - if (debug.Any()) + if (debug.Length > 0) { string debugMessage = $"{_Debug.Count - debug.Length} - {debug.Min()} - {_Debug.Max()}"; _Log.Info(debugMessage); } - if (_DuplicateMappedFaceFiles.Any()) + if (_DuplicateMappedFaceFiles.Count > 0) _Log.Info($"Renamed {_DuplicateMappedFaceFiles.Count} to *.dup file(s)"); - if (_Moved.Any() || _Renamed.Any()) + if (_Moved.Count > 0 || _Renamed.Count > 0) throw new NotImplementedException("Restart!"); _Debug.Clear(); _Moved.Clear(); @@ -313,7 +314,7 @@ public partial class E_Distance _DuplicateMappedFaceFiles.Clear(); } - public List GetMissingFaceDistanceContainer(int maxDegreeOfParallelism, long ticks, string dFacesCollectionDirectory, Dictionary> missingIdThenWholePercentagesToPersonContainers) + public List GetMissingFaceDistanceContainer(int maxDegreeOfParallelism, long ticks, string dFacesCollectionDirectory, Dictionary>> missingIdThenWholePercentagesToPersonContainers) { List results = new(); string[] files; @@ -324,7 +325,7 @@ public partial class E_Distance FaceDistance faceDistance; List<(int id, string json)> collection = new(); FaceDistanceContainer faceDistanceContainer; - foreach (KeyValuePair> keyValuePair in missingIdThenWholePercentagesToPersonContainers) + foreach (KeyValuePair>> keyValuePair in missingIdThenWholePercentagesToPersonContainers) { files = Directory.GetFiles(dFacesCollectionDirectory, $"{keyValuePair.Key}*.json", SearchOption.TopDirectoryOnly); if (files.Length != 1) @@ -530,16 +531,16 @@ public partial class E_Distance FaceDistance faceDistanceEncoding = filteredFaceDistanceContainers[i].FaceDistance; Face face = filteredFaceDistanceContainers[i].Face; List sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, i, faceDistanceEncoding); - if (!sortingCollection.Any()) + if (sortingCollection.Count == 0) return; List sortingContainers = GetSortingContainers(mapConfiguration, distanceLimits, face, faceDistanceEncoding, sortingCollection); - if (sortingContainers.Any()) + if (sortingContainers.Count > 0) { lock (collection) collection.AddRange(sortingContainers); } }); - if (!collection.Any()) + if (collection.Count == 0) results = Array.Empty(); else { diff --git a/Drag-Drop-Explorer/DragDropExplorer.cs b/Drag-Drop-Explorer/DragDropExplorer.cs index d083457..fceb6cd 100644 --- a/Drag-Drop-Explorer/DragDropExplorer.cs +++ b/Drag-Drop-Explorer/DragDropExplorer.cs @@ -125,7 +125,7 @@ public partial class DragDropExplorer : Form { try { - if (e.Data is null || e.Data.GetData(DataFormats.FileDrop) is not string[] paths || !paths.Any()) + if (e.Data is null || e.Data.GetData(DataFormats.FileDrop) is not string[] paths || paths.Length == 0) { _FirstTextBox.Text = string.Empty; _PathTextBox.Text = string.Empty; diff --git a/Drag-Drop-Move/DragDropMove.cs b/Drag-Drop-Move/DragDropMove.cs index 02823cb..d770271 100644 --- a/Drag-Drop-Move/DragDropMove.cs +++ b/Drag-Drop-Move/DragDropMove.cs @@ -179,7 +179,7 @@ public partial class DragDropMove : Form { try { - if (e.Data is not null && e.Data.GetData(DataFormats.FileDrop) is string[] paths && paths.Any()) + if (e.Data is not null && e.Data.GetData(DataFormats.FileDrop) is string[] paths && paths.Length > 0) MovePaths(paths); else { diff --git a/Face/Models/_D_Face.cs b/Face/Models/_D_Face.cs index a12d951..440f163 100644 --- a/Face/Models/_D_Face.cs +++ b/Face/Models/_D_Face.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; @@ -239,7 +240,7 @@ public class D_Face List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary? FaceParts)> collection; FaceRecognition faceRecognition = new(_PropertyConfiguration.NumberOfJitters.Value, _PropertyConfiguration.NumberOfTimesToUpsample.Value, _Model, _ModelParameter, _PredictorModel); collection = faceRecognition.GetCollection(unknownImage, locations, includeFaceEncoding: true, includeFaceParts: true); - if (!collection.Any()) + if (collection.Count == 0) results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null)); else { @@ -268,7 +269,7 @@ public class D_Face #pragma warning restore CA1416 - private static List> GetLocationContainers(string outputResolution, List> locationContainers, Dictionary outputResolutionToResize, List faces) + private static List> GetLocationContainers(string outputResolution, ReadOnlyCollection> locationContainers, Dictionary outputResolutionToResize, List faces) { List> results = new(); string? json; @@ -309,12 +310,12 @@ public class D_Face results.Add(new(locationContainer.FromDistanceContent, locationContainer.File, locationContainer.PersonKey, locationContainer.Id, locationContainer.WholePercentages, locationContainer.Directories, rectangle.Value, location)); } } - if (results.Any()) + if (results.Count > 0) outputResolutionCheck = null; return results; } - public List GetFaces(string outputResolution, string dResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, List>? locationContainers, List? mappingFromPhotoPrismCollection) + public List GetFaces(string outputResolution, string dResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, ReadOnlyCollection>? locationContainers, List? mappingFromPhotoPrismCollection) { List? results; if (string.IsNullOrEmpty(dResultsFullGroupDirectory)) @@ -339,7 +340,7 @@ public class D_Face results = null; else if (!fileInfo.Exists) results = null; - else if (_CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime) + else if (_CheckDFaceAndUpWriteDates && dateTimes.Count > 0 && dateTimes.Max() > fileInfo.LastWriteTime) results = null; else { @@ -366,14 +367,14 @@ public class D_Face locations = (from l in collection where l is not null select l.Location).ToList(); else locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(collection, results, mappingFromPhotoPrismCollection, _RectangleIntersectMinimum); - if (results is null || (locations is not null && locations.Any())) + if (results is null || (locations is not null && locations.Count > 0)) { results = GetFaces(outputResolution, property, mappingFromItem, outputResolutionToResize, locations); - if (!results.Any()) + if (results.Count == 0) File.Move(mappingFromItem.ResizedFileHolder.FullName, $"{mappingFromItem.ResizedFileHolder.FullName}.err"); else { - bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; + bool updateDateWhenMatches = dateTimes.Count > 0 && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull); if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) @@ -419,7 +420,7 @@ public class D_Face save = true; else if (!fileInfo.Exists) save = true; - else if (_CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime) + else if (_CheckDFaceAndUpWriteDates && dateTimes.Count > 0 && dateTimes.Max() > fileInfo.LastWriteTime) save = true; results.Add(new(face, fileInfo, Path.Combine(directory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{_HiddenFileNameExtension}"), save)); } diff --git a/FaceRecognitionDotNet/Dlib/Python/FaceRecognitionModelV1.cs b/FaceRecognitionDotNet/Dlib/Python/FaceRecognitionModelV1.cs index ce35715..5736a75 100644 --- a/FaceRecognitionDotNet/Dlib/Python/FaceRecognitionModelV1.cs +++ b/FaceRecognitionDotNet/Dlib/Python/FaceRecognitionModelV1.cs @@ -96,7 +96,7 @@ internal sealed class FaceRecognitionModelV1 throw new ApplicationException(); } - if (faceChipsArray.Any()) + if (faceChipsArray.Count > 0) { foreach (Array>? array in faceChipsArray) { diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 7909e1e..171bd76 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -128,7 +128,7 @@ public partial class DlibDotNet _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, propertyConfiguration.ResultSingleton)); string a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration.PropertyConfiguration, nameof(A2_People), "([])"); personContainers = new(IPersonContainer.GetPersonContainers(storage, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension)); - if (configuration.JLinks.Length > 0) + if (configuration.JLinks.Where(l => !string.IsNullOrEmpty(l)).Any()) { string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration.PropertyConfiguration, nameof(A2_People), "{}"); _JLinkResolvedDirectories.AddRange(Map.Models.Stateless.Methods.IMapLogic.GetJLinkDirectories(configuration.GenealogicalDataCommunicationFile, configuration.JLinks, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), a2PeopleSingletonDirectory, a2PeopleContentDirectory)); @@ -201,7 +201,7 @@ public partial class DlibDotNet private static void Verify(Models.Configuration configuration) { - if (!configuration.OutputResolutions.Any() || string.IsNullOrEmpty(configuration.OutputResolutions[0]) || !configuration.ValidResolutions.Contains(configuration.OutputResolutions[0])) + if (configuration.OutputResolutions.Length == 0 || string.IsNullOrEmpty(configuration.OutputResolutions[0]) || !configuration.ValidResolutions.Contains(configuration.OutputResolutions[0])) throw new NullReferenceException($"{nameof(configuration.OutputResolutions)} must be fileNameToCollection valid outputResolution!"); if ((from l in configuration.OutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) throw new Exception($"One or more {nameof(configuration.OutputResolutions)} are not in the ValidResolutions list!"); @@ -228,7 +228,7 @@ public partial class DlibDotNet private void VerifyExtra(List args, Property.Models.Configuration propertyConfiguration, Models.Configuration configuration) { string[] sourceDirectoryNames; - if (!args.Any()) + if (args.Count == 0) sourceDirectoryNames = Array.Empty(); else { @@ -249,7 +249,7 @@ public partial class DlibDotNet } } string[] resizeMatch = (from l in sourceDirectoryNames where configuration.ValidResolutions.Contains(l) select l).ToArray(); - if (resizeMatch.Any()) + if (resizeMatch.Length > 0) throw new Exception("Input directory should be the source and not fileNameToCollection resized directory!"); if (configuration.LocationDigits != Shared.Models.Stateless.ILocation.Digits) throw new Exception("Configuration has to match interface!"); @@ -294,7 +294,7 @@ public partial class DlibDotNet return result; } - private void SetMapping(MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem, List? mappingFromPhotoPrismCollection, List faces) + private void SetMapping(MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, ReadOnlyCollection> locationContainers, MappingFromItem mappingFromItem, List? mappingFromPhotoPrismCollection, List faces) { double? α; int? eyeα; @@ -311,6 +311,7 @@ public partial class DlibDotNet MappingFromLocation? mappingFromLocation; bool? isFocusModel = GetIsFocusModel(item.Property); bool ignoreXMatches = _JLinkResolvedDirectories.Count > 0; + ReadOnlyCollection locationContainersFiles = new((from l in locationContainers select l.File).ToArray()); foreach (Shared.Models.Face face in faces) { if (item.Property?.Id is null || face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) @@ -337,16 +338,16 @@ public partial class DlibDotNet mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle); isUsed = mapLogic.IsUsed(ignoreXMatches, item.Property.Id.Value, mappingFromLocation); inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation); - isFocusPerson = mapLogic.IsFocusPerson(_JLinkResolvedDirectories, item.Property.Id.Value, mappingFromLocation); + isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, _JLinkResolvedDirectories, item.Property.Id.Value, mappingFromLocation); mappingFromFilter = new(isFocusModel, isFocusPerson, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection, isUsed); } mapping = new(mappingFromItem, mappingFromFilter, mappingFromLocation, mappingFromPhotoPrismCollection); - _ = mapLogic.UpdateMappingFromPerson(mapping); + _ = mapLogic.UpdateMappingFromPerson(locationContainersFiles, mapping); face.SetMapping(mapping); } } - private Mapping GetMapping(MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem, List<(string, long)> jLinkResolvedDirectories) + private Mapping GetMapping(MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem) { Mapping result; bool? isUsed; @@ -361,7 +362,7 @@ public partial class DlibDotNet MappingFromFilter mappingFromFilter; MappingFromLocation? mappingFromLocation; bool? isFocusModel = GetIsFocusModel(item.Property); - bool ignoreXMatches = jLinkResolvedDirectories.Count > 0; + bool ignoreXMatches = _JLinkResolvedDirectories.Count > 0; if (item.Property?.Id is null) { isUsed = null; @@ -377,7 +378,7 @@ public partial class DlibDotNet mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle); isUsed = mapLogic.IsUsed(ignoreXMatches, item.Property.Id.Value, mappingFromLocation); inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation); - isFocusPerson = mapLogic.IsFocusPerson(jLinkResolvedDirectories, item.Property.Id.Value, mappingFromLocation); + isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, _JLinkResolvedDirectories, item.Property.Id.Value, mappingFromLocation); mappingFromFilter = new(isFocusModel, isFocusPerson, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection, isUsed); } result = new(mappingFromItem, mappingFromFilter, mappingFromLocation, mappingFromPhotoPrismCollection: null); @@ -408,7 +409,6 @@ public partial class DlibDotNet private void FullParallelForWork(A_Property propertyLogic, B_Metadata metadata, - ReadOnlyDictionary>> idToLocationContainers, MapLogic mapLogic, string outputResolution, bool outputResolutionHasNumber, @@ -434,6 +434,7 @@ public partial class DlibDotNet List> metadataCollection; string[] changesFrom = new string[] { nameof(A_Property) }; FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber); + ReadOnlyCollection> locationContainers = mapLogic.GetLocationContainers(item); if (item.Property is null || item.Property.Id is null || item.Any()) { LogItemPropertyIsNull(item); @@ -495,17 +496,12 @@ public partial class DlibDotNet else { List? mappingFromPhotoPrismCollection; - List>? locationContainers; - if (item.Property?.Id is null) - locationContainers = null; - else - _ = idToLocationContainers.TryGetValue(item.Property.Id.Value, out locationContainers); if (!fileNameToCollection.TryGetValue(mappingFromItem.Id, out mappingFromPhotoPrismCollection)) mappingFromPhotoPrismCollection = null; faces = _Faces.GetFaces(outputResolution, dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, locationContainers, mappingFromPhotoPrismCollection); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.GetFaces)); - SetMapping(mapLogic, item, isFocusRelativePath, isIgnoreRelativePath, mappingFromItem, mappingFromPhotoPrismCollection, faces); + SetMapping(mapLogic, item, isFocusRelativePath, isIgnoreRelativePath, locationContainers, mappingFromItem, mappingFromPhotoPrismCollection, faces); List<(Shared.Models.Face, FileInfo?, string, bool Saved)> faceCollection = _Faces.SaveFaces(_FaceParts.FileNameExtension, dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, faces); if (_Configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) _FaceParts.CopyFacesAndSaveFaceLandmarkImage(facePartsCollectionDirectory, mappingFromItem, faceCollection); @@ -535,7 +531,6 @@ public partial class DlibDotNet private int FullParallelWork(int maxDegreeOfParallelism, A_Property propertyLogic, B_Metadata metadata, - ReadOnlyDictionary>> idToLocationContainers, MapLogic mapLogic, string outputResolution, bool outputResolutionHasNumber, @@ -558,7 +553,7 @@ public partial class DlibDotNet string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory)); bool? isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath); string facePartsCollectionDirectory = _Configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions.Contains(outputResolution) ? _FaceParts.GetFacePartsDirectory(_Configuration.PropertyConfiguration, d2ResultsFullGroupDirectory, item: filteredItems.First(), includeNameWithoutExtension: false) : string.Empty; - bool? isIgnoreRelativePath = !_Configuration.IgnoreRelativePaths.Any() ? null : _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory); + bool? isIgnoreRelativePath = _Configuration.IgnoreRelativePaths.Length == 0 ? null : _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory); using ProgressBar progressBar = new(filteredItems.Length, message, options); _ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) => { @@ -566,7 +561,6 @@ public partial class DlibDotNet { FullParallelForWork(propertyLogic, metadata, - idToLocationContainers, mapLogic, outputResolution, outputResolutionHasNumber, @@ -582,7 +576,7 @@ public partial class DlibDotNet isFocusRelativePath, isIgnoreRelativePath, facePartsCollectionDirectory); - if (i == 0 || sourceDirectoryChanges.Any()) + if (i == 0 || sourceDirectoryChanges.Count > 0) progressBar.Tick(); } catch (Exception ex) @@ -619,7 +613,7 @@ public partial class DlibDotNet if (duplicates.Contains(metadataIdLines[i].Id)) metadataIdLines.RemoveAt(i); } - if (metadataIdLines.Any()) + if (metadataIdLines.Count > 0) { text = string.Join(Environment.NewLine, from l in metadataIdLines orderby l.Id select l.Line); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, text, updateDateWhenMatches: true, compareBeforeWrite: true); @@ -683,7 +677,7 @@ public partial class DlibDotNet return new(cResultsFullGroupDirectory, c2ResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory); } - private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, int t, Container[] containers, A_Property propertyLogic, B_Metadata metadata, Dictionary> fileNameToCollection, ReadOnlyDictionary>> idToLocationContainers, MapLogic mapLogic) + private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, int t, Container[] containers, A_Property propertyLogic, B_Metadata metadata, Dictionary> fileNameToCollection, MapLogic mapLogic) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); @@ -715,12 +709,12 @@ public partial class DlibDotNet for (int i = 0; i < containers.Length; i++) { container = containers[i]; - if (!container.Items.Any()) + if (container.Items.Count == 0) continue; if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) continue; filteredItems = Shared.Models.Stateless.Methods.IContainer.GetFilterItems(_Configuration.PropertyConfiguration, container); - if (!filteredItems.Any()) + if (filteredItems.Length == 0) continue; sourceDirectoryChanges.Clear(); anyNullOrNoIsUniqueFileName = filteredItems.Any(l => !l.IsUniqueFileName); @@ -732,7 +726,6 @@ public partial class DlibDotNet exceptionCount = FullParallelWork(maxDegreeOfParallelism, propertyLogic, metadata, - idToLocationContainers, mapLogic, outputResolution, outputResolutionHasNumber, @@ -749,7 +742,7 @@ public partial class DlibDotNet _Exceptions.Add(container.SourceDirectory); continue; } - if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any()) + if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Length > 0) { for (int y = 0; y < int.MaxValue; y++) { @@ -786,7 +779,7 @@ public partial class DlibDotNet { distanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh, useFiltersCounter); filteredFaceDistanceContainers = E_Distance.FilteredFaceDistanceContainers(mapLogic, faceDistanceContainers, skipOlderThan, distanceLimits); - if (filteredFaceDistanceContainers.Any()) + if (filteredFaceDistanceContainers.Length == 0) _Log.Information("All images have been filtered!"); else { @@ -800,7 +793,7 @@ public partial class DlibDotNet if (filteredFaceDistanceContainers.Length > 0) { int updated = mapLogic.UpdateFromSortingContainers(_Configuration.SaveIndividually, distanceLimits, sortingContainers); - List saveContainers = mapLogic.GetSaveContainers(_Configuration.SaveIndividually, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, mappingCollection, idToWholePercentagesToMapping, useFiltersCounter, sortingContainers.Any()); + List saveContainers = mapLogic.GetSaveContainers(_Configuration.SaveIndividually, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, mappingCollection, idToWholePercentagesToMapping, useFiltersCounter, sortingContainers.Length > 0); mapLogic.SaveContainers(_Configuration.SaveIndividually, filteredFaceDistanceContainers.Length, updated, saveContainers); } } @@ -810,10 +803,10 @@ public partial class DlibDotNet { E_Distance.SetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, distinctFilteredFaces); FaceDistanceContainer[] faceDistanceContainers = E_Distance.GetFaceDistanceContainers(distinctFilteredFaces); - Dictionary> missingIdThenWholePercentagesToPersonContainers = mapLogic.GetMissing(idToWholePercentagesToMapping); + Dictionary>> missingIdThenWholePercentagesToPersonContainers = mapLogic.GetMissing(idToWholePercentagesToMapping); List missingFaceDistanceContainers = _Distance.GetMissingFaceDistanceContainer(_AppSettings.MaxDegreeOfParallelism, ticks, dFacesCollectionDirectory, missingIdThenWholePercentagesToPersonContainers); List faceDistanceEncodings = E_Distance.GetFaceDistanceEncodings(faceDistanceContainers, missingFaceDistanceContainers); - if (faceDistanceContainers.Any()) + if (faceDistanceContainers.Length > 0) SaveFaceDistances(ticks, mapLogic, mappingCollection, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, idToWholePercentagesToMapping, faceDistanceEncodings, faceDistanceContainers); } @@ -823,7 +816,7 @@ public partial class DlibDotNet string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent); string d2FacePartsContentCollectionDirectory = Path.Combine(d2ResultsFullGroupDirectory, "[()]"); string dFacesCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultCollection, _Configuration.PropertyConfiguration.ResultAllInOne); - if (distinctFilteredMappingCollection.Any()) + if (distinctFilteredMappingCollection.Length > 0) { Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(d2FacePartsContentDirectory, ticks); if (Directory.Exists(d2FacePartsContentCollectionDirectory)) @@ -852,7 +845,7 @@ public partial class DlibDotNet string result; if (_Log is null) throw new NullReferenceException(nameof(_Log)); - if (!files.Any()) + if (files.Length == 0) throw new NotSupportedException(); string? sourceDirectory = Path.GetDirectoryName(files.First()); if (string.IsNullOrEmpty(sourceDirectory)) @@ -893,108 +886,6 @@ public partial class DlibDotNet return result; } - private static void LookForAbandoned(List distinctFilteredIds, string directory, string directoryName) - { - string fileNameWithoutExtension; - bool nameWithoutExtensionIsIdFormat; - List renameCollection = new(); - bool nameWithoutExtensionIsPaddedIdFormat; - int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex(); - 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 = Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension); - nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileNameWithoutExtension, sortOrderOnlyLengthIndex); - if (!nameWithoutExtensionIsIdFormat && !nameWithoutExtensionIsPaddedIdFormat) - continue; - if (distinctFilteredIdsValues.Contains(fileNameWithoutExtension)) - continue; - renameCollection.Add(file); - } - if (renameCollection.Any()) - { - if (directoryName.Length == 2) - IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[0]}abd{directoryName[^1]}"); - else if (directoryName.Length == 4) - IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[..2]}abd{directoryName[^2..]}"); - else - throw new NotSupportedException(); - } - } - - private static void LookForAbandoned(string bResultsFullGroupDirectory, List distinctFilteredIds) - { - string[] directories = Directory.GetDirectories(bResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); - foreach (string directory in directories) - { - string? directoryName = Path.GetFileName(directory); - if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4)) - continue; - LookForAbandoned(distinctFilteredIds, directory, directoryName); - } - } - - private void LookForAbandoned(ReadOnlyDictionary>> idToLocationContainers, List distinctFilteredIds) - { - List renameCollection = new(); - foreach (KeyValuePair>> keyValuePair in idToLocationContainers) - { - if (distinctFilteredIds.Contains(keyValuePair.Key)) - continue; - foreach (LocationContainer locationContainer in keyValuePair.Value) - { - if (locationContainer.File.Contains('!')) - continue; - renameCollection.Add(locationContainer.File); - } - } - if (renameCollection.Any()) - IDirectory.MoveFiles(renameCollection, _Configuration.PropertyConfiguration.ResultContent, "(abd)"); - } - - private void LookForAbandoned(string bResultsFullGroupDirectory, Container[] containers, ReadOnlyDictionary>> idToLocationContainers) - { - string[] directories; - string? directoryName; - string cResultsFullGroupDirectory; - string dResultsFullGroupDirectory; - string c2ResultsFullGroupDirectory; - string d2ResultsFullGroupDirectory; - List distinctFilteredIds = Shared.Models.Stateless.Methods.IContainer.GetFilteredDistinctIds(_Configuration.PropertyConfiguration, containers); - LookForAbandoned(idToLocationContainers, distinctFilteredIds); - LookForAbandoned(bResultsFullGroupDirectory, distinctFilteredIds); - foreach (string outputResolution in _Configuration.OutputResolutions) - { - (cResultsFullGroupDirectory, c2ResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution); - directories = Directory.GetDirectories(cResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); - foreach (string directory in directories) - { - directoryName = Path.GetFileName(directory); - if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4)) - continue; - LookForAbandoned(distinctFilteredIds, directory, directoryName); - } - directories = Directory.GetDirectories(dResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); - foreach (string directory in directories) - { - directoryName = Path.GetFileName(directory); - if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4)) - continue; - LookForAbandoned(distinctFilteredIds, directory, directoryName); - } - directories = Directory.GetDirectories(d2ResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); - foreach (string directory in directories) - { - directoryName = Path.GetFileName(directory); - if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4)) - continue; - LookForAbandoned(distinctFilteredIds, directory, directoryName); - } - } - } - private Mapping[] GetMappings(Property.Models.Configuration propertyConfiguration, Container[] containers, MapLogic mapLogic, bool distinctItems) { Mapping[] results; @@ -1011,7 +902,7 @@ public partial class DlibDotNet List mappingCollection = new(); foreach (Container container in containers) { - if (!container.Items.Any()) + if (container.Items.Count == 0) continue; filteredItems = Shared.Models.Stateless.Methods.IContainer.GetFilterItems(propertyConfiguration, container); if (!filteredItems.Any()) @@ -1019,7 +910,7 @@ public partial class DlibDotNet containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems); focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory)); isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath); - isIgnoreRelativePath = !_Configuration.IgnoreRelativePaths.Any() ? null : _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory); + isIgnoreRelativePath = _Configuration.IgnoreRelativePaths.Length == 0 ? null : _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory); foreach (Item item in filteredItems) { if (item.Property?.Id is null || item.ResizedFileHolder is null) @@ -1042,7 +933,7 @@ public partial class DlibDotNet } if (!anyValidFaces) { - mapping = GetMapping(mapLogic, item, isFocusRelativePath, isIgnoreRelativePath, mappingFromItem, _JLinkResolvedDirectories); + mapping = GetMapping(mapLogic, item, isFocusRelativePath, isIgnoreRelativePath, mappingFromItem); mappingCollection.Add(mapping); } } @@ -1071,7 +962,7 @@ public partial class DlibDotNet if (!found) notFound.Add(item); } - if (notFound.Any()) + if (notFound.Count > 0) throw new NotSupportedException(); #endif string model; @@ -1140,6 +1031,44 @@ public partial class DlibDotNet } } + private static bool GetRunToDoCollectionFirst(long ticks, string rootDirectory, FileSystemInfo fileSystemInfo) + { + bool result = false; + string[] directories; + string seasonDirectory; + DirectoryInfo directoryInfo; + DateTime dateTime = new(ticks); + (int season, string seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear); + string[] checkDirectories = new string[] + { + Path.Combine(rootDirectory, "Ancestry"), + Path.Combine(rootDirectory, "Facebook"), + Path.Combine(rootDirectory, "LinkedIn"), + rootDirectory, + }; + foreach (string checkDirectory in checkDirectories) + { + if (!Directory.Exists(checkDirectory)) + _ = Directory.CreateDirectory(checkDirectory); + seasonDirectory = Path.Combine(checkDirectory, $"{dateTime.Year}.{season} {seasonName} {Path.GetFileName(checkDirectory)}"); + if (!Directory.Exists(seasonDirectory)) + _ = Directory.CreateDirectory(seasonDirectory); + if (result) + continue; + directories = Directory.GetDirectories(checkDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string directory in directories) + { + directoryInfo = new(directory); + if (directoryInfo.LastWriteTime > fileSystemInfo.LastWriteTime) + { + result = true; + break; + } + } + } + return result; + } + private void Search(long ticks, ReadOnlyCollection personContainers, string argZero, string propertyRoot) { int t; @@ -1170,8 +1099,8 @@ public partial class DlibDotNet a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])"); eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), _Configuration.PropertyConfiguration.ResultContent); string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), _Configuration.PropertyConfiguration.ResultSingleton); - TimeSpan eLastWriteTimeTimeSpan = new(ticks - new DirectoryInfo(eDistanceContentDirectory).LastWriteTime.Ticks); - if (eLastWriteTimeTimeSpan.TotalDays > 1) + bool runToDoCollectionFirst = GetRunToDoCollectionFirst(ticks, _Configuration.PropertyConfiguration.RootDirectory, new DirectoryInfo(eDistanceContentDirectory)); + if (runToDoCollectionFirst) mapLogic = null; else mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, personContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); @@ -1180,7 +1109,7 @@ public partial class DlibDotNet if (outputResolution.Any(l => char.IsNumber(l))) continue; configurationOutputResolutionsHas = true; - if (eLastWriteTimeTimeSpan.TotalDays < 1) + if (!runToDoCollectionFirst) break; ProgressBar progressBar; (cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution); @@ -1249,16 +1178,21 @@ public partial class DlibDotNet B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory); mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, personContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers); - ReadOnlyDictionary>> idToLocationContainers = mapLogic.GetIdToLocationContainers(); - FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, fileNameToCollection, idToLocationContainers, mapLogic); - if (_Configuration.LookForAbandoned) - LookForAbandoned(bResultsFullGroupDirectory, containers, idToLocationContainers); - _Distance.Clear(); + FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, fileNameToCollection, mapLogic); List distinctFilteredItems = Shared.Models.Stateless.Methods.IContainer.GetItems(_Configuration.PropertyConfiguration, containers, distinctItems: true, filterItems: true); + if (_Configuration.LookForAbandoned) + { + foreach (string outputResolution in _Configuration.OutputResolutions) + { + (cResultsFullGroupDirectory, _, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution); + mapLogic.LookForAbandoned(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, containers, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory); + } + } + _Distance.Clear(); Verify(eDistanceContentDirectory, distinctFilteredItems); List distinctFilteredFaces = Map.Models.Stateless.Methods.IMapLogic.GetFaces(distinctFilteredItems); Mapping[] distinctFilteredMappingCollection = GetMappings(_Configuration.PropertyConfiguration, containers, mapLogic, distinctItems: true); - int totalNotMapped = mapLogic.UpdateMappingFromPerson(distinctFilteredMappingCollection); + int totalNotMapped = mapLogic.UpdateMappingFromPerson(_Configuration.PropertyConfiguration, distinctFilteredMappingCollection); string json = JsonSerializer.Serialize(distinctFilteredMappingCollection); File.WriteAllText(Path.Combine(eDistanceContentDirectory, $"{ticks}.json"), json); foreach (string outputResolution in _Configuration.OutputResolutions) @@ -1268,7 +1202,7 @@ public partial class DlibDotNet personKeyToIds = mapLogic.GetPersonKeyToIds(); if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && _Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) mapLogic.SaveShortcutsForOutputResolutionsPreMapLogic(eDistanceContentDirectory, personKeyToIds, distinctFilteredMappingCollection); - if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && _Configuration.JLinks.Length > 0 && _Configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions.Contains(outputResolution)) + if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && _Configuration.JLinks.Where(l => !string.IsNullOrEmpty(l)).Any() && _Configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions.Contains(outputResolution)) mapLogic.SaveFilteredOriginalImagesFromJLinks(_Configuration.JLinks, personContainers, a2PeopleContentDirectory, personKeyToIds, distinctFilteredMappingCollection, totalNotMapped); (cResultsFullGroupDirectory, c2ResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution); if (_ArgZeroIsConfigurationRootDirectory @@ -1277,7 +1211,7 @@ public partial class DlibDotNet && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) && _Exceptions.Count == 0) MapLogic(ticks, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, fPhotoPrismContentDirectory, mapLogic, outputResolution, personKeyToIds, distinctFilteredFaces, distinctFilteredMappingCollection, totalNotMapped); - if (_Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Any() && distinctFilteredMappingCollection.Any()) + if (_Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Count > 0 && distinctFilteredMappingCollection.Length > 0) _Random.Random(_Configuration.PropertyConfiguration, outputResolution, personKeyToIds, distinctFilteredMappingCollection); if (_IsEnvironment.Development) continue; diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index ace89cc..1c9e436 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -84,6 +84,7 @@ public class Configuration [Display(Name = "Save Sorting Without Person"), Required] public bool? SaveSortingWithoutPerson { get; set; } [Display(Name = "Skip Not Skip Directories"), Required] public string[] SkipNotSkipDirectories { get; set; } [Display(Name = "Skip Older Than Days"), Required] public int? SkipOlderThanDays { get; set; } + [Display(Name = "Skip Person With More Then"), Required] public int? SkipPersonWithMoreThen { get; set; } [Display(Name = "Skip Search"), Required] public bool? SkipSearch { get; set; } [Display(Name = "SortingMaximumPerFaceShould be High"), Required] public int? SortingMaximumPerFaceShouldBeHigh { get; set; } [Display(Name = "Sorting Maximum Per Key"), Required] public int? SortingMaximumPerKey { get; set; } @@ -314,6 +315,7 @@ public class Configuration configuration.SaveSortingWithoutPerson.Value, configuration.SkipNotSkipDirectories, configuration.SkipOlderThanDays, + configuration.SkipPersonWithMoreThen, configuration.SkipSearch.Value, configuration.SortingMaximumPerFaceShouldBeHigh.Value, configuration.SortingMaximumPerKey.Value, diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index a9b9b7e..da65529 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -14,15 +14,14 @@ public class Configuration public bool CheckJsonForDistanceResults { init; get; } public string[] CopyFacesAndSaveFaceLandmarkForOutputResolutions { init; get; } public int CrossDirectoryMaxItemsInDistanceCollection { init; get; } - public bool DeletePossibleDuplicates { get; internal set; } public int DistanceFactor { init; get; } public bool DistanceMoveUnableToMatch { init; get; } public int DistancePixelDistanceTolerance { init; get; } public bool DistanceRenameToMatch { init; get; } public int EyeThreshold { init; get; } public int FaceAreaPermyriad { init; get; } - public int FaceDistanceHiddenImageFactor { init; get; } public int FaceConfidencePercent { init; get; } + public int FaceDistanceHiddenImageFactor { init; get; } public int FaceDistancePermyriad { init; get; } public string FocusDirectory { init; get; } public string FocusModel { init; get; } @@ -72,22 +71,24 @@ public class Configuration public string[] SaveFaceDistancesForOutputResolutions { init; get; } public string[] SaveFaceLandmarkForOutputResolutions { init; get; } public string[] SaveFilteredOriginalImagesFromJLinksForOutputResolutions { init; get; } - public bool SaveIndividually { init; get; } public bool SaveFullYearOfRandomFiles { init; get; } + public bool SaveIndividually { init; get; } public string[] SaveMappedForOutputResolutions { init; get; } public string[] SaveRandomForOutputResolutions { init; get; } public bool SaveResizedSubfiles { init; get; } public string[] SaveShortcutsForOutputResolutions { init; get; } public bool SaveSortingWithoutPerson { init; get; } public string[] SkipNotSkipDirectories { init; get; } - public bool SkipSearch { init; get; } public int? SkipOlderThanDays { init; get; } + public int? SkipPersonWithMoreThen { init; get; } + public bool SkipSearch { init; get; } public int SortingMaximumPerFaceShouldBeHigh { init; get; } public int SortingMaximumPerKey { init; get; } public int SortingMinimumToUseSigma { init; get; } public bool TestDistanceResults { init; get; } public int UseFilterTries { init; get; } public string[] ValidResolutions { init; get; } + public bool DeletePossibleDuplicates { get; internal set; } [JsonConstructor] public Configuration(Property.Models.Configuration propertyConfiguration, @@ -162,6 +163,7 @@ public class Configuration bool saveSortingWithoutPerson, string[] skipNotSkipDirectories, int? skipOlderThanDays, + int? skipPersonWithMoreThen, bool skipSearch, int sortingMaximumPerFaceShouldBeHigh, int sortingMaximumPerKey, @@ -182,8 +184,8 @@ public class Configuration DistanceRenameToMatch = distanceRenameToMatch; EyeThreshold = eyeThreshold; FaceAreaPermyriad = faceAreaPermyriad; - FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor; FaceConfidencePercent = faceConfidencePercent; + FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor; FaceDistancePermyriad = faceDistancePermyriad; FocusDirectory = focusDirectory; FocusModel = focusModel; @@ -233,8 +235,8 @@ public class Configuration SaveFaceDistancesForOutputResolutions = saveFaceDistancesForOutputResolutions; SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions; SaveFilteredOriginalImagesFromJLinksForOutputResolutions = saveFilteredOriginalImagesFromJLinksForOutputResolutions; - SaveIndividually = saveIndividually; SaveFullYearOfRandomFiles = saveFullYearOfRandomFiles; + SaveIndividually = saveIndividually; SaveMappedForOutputResolutions = saveMappedForOutputResolutions; SaveRandomForOutputResolutions = saveRandomForOutputResolutions; SaveResizedSubfiles = saveResizedSubfiles; @@ -242,6 +244,7 @@ public class Configuration SaveSortingWithoutPerson = saveSortingWithoutPerson; SkipNotSkipDirectories = skipNotSkipDirectories; SkipOlderThanDays = skipOlderThanDays; + SkipPersonWithMoreThen = skipPersonWithMoreThen; SkipSearch = skipSearch; SortingMaximumPerFaceShouldBeHigh = sortingMaximumPerFaceShouldBeHigh; SortingMaximumPerKey = sortingMaximumPerKey; diff --git a/Instance/Models/_F_Random.cs b/Instance/Models/_F_Random.cs index d7a4dae..ef03684 100644 --- a/Instance/Models/_F_Random.cs +++ b/Instance/Models/_F_Random.cs @@ -85,7 +85,7 @@ internal class F_Random relativePaths.Add(mapping.MappingFromItem.RelativePath); distinctCollection.Add(mapping.MappingFromItem.Id); } - if (relativePaths.Any()) + if (relativePaths.Count > 0) { for (int i = 0; i < 366; i++) { diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index 58ad2cb..ff616dc 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -13,18 +13,18 @@ namespace View_by_Distance.Map.Models; public class MapLogic : Shared.Models.Methods.IMapLogic { - protected readonly List _NotMappedPersonContainers; - protected readonly ReadOnlyDictionary> _SkipCollection; - protected readonly ReadOnlyDictionary> _SkipNotSkipCollection; - protected readonly ReadOnlyDictionary _PersonKeyToPersonContainer; - protected readonly List> _LocationContainers; - protected readonly ReadOnlyDictionary> _IdThenWholePercentagesToPersonContainers; - private readonly long _Ticks; private readonly Serilog.ILogger? _Log; private readonly Configuration? _Configuration; private readonly string _EDistanceContentTicksDirectory; + private readonly ReadOnlyDictionary _PersonKeyToCount; + private readonly List _NotMappedPersonContainers; + private readonly ReadOnlyDictionary> _SkipCollection; + private readonly ReadOnlyDictionary> _SkipNotSkipCollection; + private readonly ReadOnlyDictionary _PersonKeyToPersonContainer; private readonly Shared.Models.Properties.IPropertyConfiguration _PropertyConfiguration; + private readonly ReadOnlyDictionary>> _IdToLocationContainers; + private readonly ReadOnlyDictionary>> _IdThenWholePercentagesToPersonContainers; public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, ReadOnlyCollection personContainers, long ticks, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) { @@ -34,56 +34,83 @@ public class MapLogic : Shared.Models.Methods.IMapLogic _PropertyConfiguration = propertyConfiguration; if (_Log is null) { } - string json; - string fullPath; - List>? collection; - Dictionary> skipCollection = new(); + ReadOnlyDictionary readOnlyPersonKeyToCount; List notMappedPersonContainers = new(); - Dictionary> skipNotSkipCollection = new(); + Dictionary> skipCollection = new(); + Dictionary> skipNotSkipCollection = new(); Dictionary personKeyToPersonContainer = new(); List> locationContainers = new(); string? rootDirectoryParent = Path.GetDirectoryName(propertyConfiguration.RootDirectory); string eDistanceContentTicksDirectory = Path.Combine(eDistanceContentDirectory, $"({ticks})"); - Dictionary> idThenWholePercentagesToPersonContainers = new(); - Dictionary>> idToLocationContainers = new(); + ReadOnlyDictionary>> idThenWholePercentagesToPersonContainers; if (string.IsNullOrEmpty(rootDirectoryParent)) throw new NullReferenceException(nameof(rootDirectoryParent)); if (!Directory.Exists(eDistanceContentDirectory)) _ = Directory.CreateDirectory(eDistanceContentDirectory); - if (configuration is not null) + if (configuration is null) { - Stateless.MapLogic.Set(maxDegreeOfParallelism, - configuration, - ticks, - personContainers, - a2PeopleSingletonDirectory, - eDistanceContentDirectory, - personKeyToPersonContainer, - notMappedPersonContainers, - skipCollection, - skipNotSkipCollection, - locationContainers, - idThenWholePercentagesToPersonContainers); + readOnlyPersonKeyToCount = new(new Dictionary()); + idThenWholePercentagesToPersonContainers = new(new Dictionary>>()); } - foreach (string propertyContentCollectionFile in propertyConfiguration.PropertyContentCollectionFiles) + else { - fullPath = Path.GetFullPath(string.Concat(rootDirectoryParent, propertyContentCollectionFile)); - if (fullPath.Contains(propertyConfiguration.RootDirectory)) - continue; - if (!File.Exists(fullPath)) - continue; - json = File.ReadAllText(fullPath); - collection = JsonSerializer.Deserialize>>(json); - if (collection is null) - throw new NullReferenceException(nameof(collection)); + ReadOnlyDictionary readOnlyPersonKeyFormattedToPersonContainer; + ReadOnlyDictionary> readOnlyPersonKeyToPersonContainerCollection; + Stateless.MapLogic.SetSkipCollections(configuration, personContainers, a2PeopleSingletonDirectory, skipCollection, skipNotSkipCollection); + List records = Stateless.MapLogic.SetPersonCollectionsAndGetRecords(configuration, ticks, personContainers, eDistanceContentDirectory); + locationContainers.AddRange(Stateless.MapLogic.GetLocationContainers(maxDegreeOfParallelism, configuration, ticks, personContainers, eDistanceContentDirectory, skipCollection, records)); + int lossCount = records.Count - locationContainers.Count; + ReadOnlyCollection personKeyFormattedIdThenWholePercentagesCollection = Stateless.MapLogic.GetPersonKeyFormattedIdThenWholePercentages(configuration, ticks, records); + int unableToMatchCount = records.Count - personKeyFormattedIdThenWholePercentagesCollection.Count; + if (lossCount != 0 || unableToMatchCount != 0) + { + if (lossCount != 0 || unableToMatchCount != 0) + { } + } + // + { + Dictionary personKeyToCount = new(); + Dictionary personKeyFormattedToPersonContainer = new(); + Dictionary> personKeyToPersonContainerCollection = new(); + List<(Stateless.MapLogic.PersonKeyFormattedIdThenWholePercentages, PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer = new(); + Stateless.MapLogic.SetKeyValuePairsAndAddToCollections(configuration, + personContainers, + personKeyToPersonContainer, + personKeyFormattedIdThenWholePercentagesCollection, + personKeyToCount, + personKeyFormattedToPersonContainer, + personKeyToPersonContainerCollection, + possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); + readOnlyPersonKeyToCount = new(personKeyToCount); + readOnlyPersonKeyFormattedToPersonContainer = new(personKeyFormattedToPersonContainer); + readOnlyPersonKeyToPersonContainerCollection = new(personKeyToPersonContainerCollection); + if (possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Count > 0) + Stateless.MapLogic.PossiblyRebuildPersonContainers(configuration, + a2PeopleSingletonDirectory, + possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); + } + Stateless.MapLogic.SetPersonKeyToPersonContainer(configuration, + personContainers, + readOnlyPersonKeyToCount, + personKeyToPersonContainer, + readOnlyPersonKeyToPersonContainerCollection); + idThenWholePercentagesToPersonContainers = Stateless.MapLogic.GetIdThenWholePercentagesToPersonContainers(configuration, + readOnlyPersonKeyFormattedToPersonContainer, + personKeyFormattedIdThenWholePercentagesCollection); + notMappedPersonContainers.AddRange(Stateless.MapLogic.GetNotMappedPersonContainers(configuration, + ticks, + personContainers, + readOnlyPersonKeyToCount)); } - _SkipCollection = new(skipCollection); - _LocationContainers = locationContainers; - _SkipNotSkipCollection = new(skipNotSkipCollection); + _PersonKeyToCount = readOnlyPersonKeyToCount; _PersonKeyToPersonContainer = new(personKeyToPersonContainer); _EDistanceContentTicksDirectory = eDistanceContentTicksDirectory; - _NotMappedPersonContainers = notMappedPersonContainers.OrderByDescending(l => l.Key).ToList(); - _IdThenWholePercentagesToPersonContainers = new(idThenWholePercentagesToPersonContainers); + _SkipCollection = Stateless.MapLogic.ConvertSkip(skipCollection); + Stateless.MapLogic.CheckCollection(propertyConfiguration, rootDirectoryParent); + _IdThenWholePercentagesToPersonContainers = idThenWholePercentagesToPersonContainers; + _SkipNotSkipCollection = Stateless.MapLogic.ConvertSkipNotSkip(skipNotSkipCollection); + _IdToLocationContainers = Stateless.MapLogic.ConvertLocationContainers(locationContainers); + _NotMappedPersonContainers = new(notMappedPersonContainers.OrderByDescending(l => l.Key).ToArray()); } public override string ToString() @@ -92,16 +119,19 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return result; } - public ReadOnlyDictionary>> GetIdToLocationContainers() + public ReadOnlyCollection> GetLocationContainers(Item item) { - Dictionary>> results = new(); - foreach (LocationContainer locationContainer in _LocationContainers) + LocationContainer[] results; + if (item.Property?.Id is null) + results = Array.Empty>(); + else { - if (!results.ContainsKey(locationContainer.Id)) - results.Add(locationContainer.Id, new()); - results[locationContainer.Id].Add(locationContainer); + List>? locationContainers; + if (_IdToLocationContainers.TryGetValue(item.Property.Id.Value, out locationContainers)) + results = locationContainers.ToArray(); + else + results = Array.Empty>(); } - _LocationContainers.Clear(); return new(results); } @@ -113,9 +143,9 @@ public class MapLogic : Shared.Models.Methods.IMapLogic List? collection; PersonBirthday personBirthday; List shouldMove = new(); - foreach (KeyValuePair> idToCollection in _IdThenWholePercentagesToPersonContainers) + foreach (KeyValuePair>> idToCollection in _IdThenWholePercentagesToPersonContainers) { - foreach (KeyValuePair wholePercentagesToPersonContainers in idToCollection.Value) + foreach (KeyValuePair> wholePercentagesToPersonContainers in idToCollection.Value) { foreach (PersonContainer personContainer in wholePercentagesToPersonContainers.Value) { @@ -137,28 +167,26 @@ public class MapLogic : Shared.Models.Methods.IMapLogic } } } - if (shouldMove.Any()) + if (shouldMove.Count > 0) throw new Exception(string.Join(Environment.NewLine, shouldMove)); return results; } - (bool, Dictionary?) Shared.Models.Methods.IMapLogic.GetWholePercentagesToPersonContainers(int id) + (bool, ReadOnlyDictionary>?) Shared.Models.Methods.IMapLogic.GetWholePercentagesToPersonContainers(int id) { - bool result = _IdThenWholePercentagesToPersonContainers.TryGetValue(id, out Dictionary? wholePercentagesToPersonContainers); + bool result = _IdThenWholePercentagesToPersonContainers.TryGetValue(id, out ReadOnlyDictionary>? wholePercentagesToPersonContainers); return new(result, wholePercentagesToPersonContainers); } - public int UpdateMappingFromPerson(Mapping mapping) + public int UpdateMappingFromPerson(ReadOnlyCollection? locationContainersFiles, Mapping mapping) { - if (_Configuration is null) - throw new NullReferenceException(nameof(_Configuration)); int result = 0; long personKey; const int zero = 0; string mappingSegmentB; PersonBirthday personBirthday; - PersonContainer[]? personContainers; - Dictionary? wholePercentagesToPersonContainers; + ReadOnlyCollection? personContainers; + ReadOnlyDictionary>? wholePercentagesToPersonContainers; for (int i = 1; i < 2; i++) { if (mapping.MappingFromLocation is null) @@ -184,20 +212,31 @@ public class MapLogic : Shared.Models.Methods.IMapLogic personBirthday = personContainer.Birthdays[zero]; personKey = personBirthday.Value.Ticks; mappingSegmentB = Stateless.MapLogic.GetMappingSegmentB(_Ticks, personBirthday, personContainer.ApproximateYears, mapping.MappingFromItem); - mapping.UpdateMappingFromPerson(personContainer.ApproximateYears, personContainer.DisplayDirectoryName, personBirthday, mappingSegmentB); + if (locationContainersFiles is null) + { + if (mapping.MappingFromPerson is null || mapping.MappingFromPerson.LocationContainersFiles.Count == 0) + locationContainersFiles = new(Array.Empty()); + else + locationContainersFiles = mapping.MappingFromPerson.LocationContainersFiles; + } + mapping.UpdateMappingFromPerson(locationContainersFiles, personContainer.ApproximateYears, personContainer.DisplayDirectoryName, personBirthday, mappingSegmentB); } } return result; } - public int UpdateMappingFromPerson(Mapping[] mappingCollection) + public int UpdateMappingFromPerson(Property.Models.Configuration propertyConfiguration, Mapping[] mappingCollection) { int result = 0; + ReadOnlyCollection? locationContainersFiles = null; foreach (Mapping mapping in mappingCollection) { if (mapping.MappingFromLocation is null) continue; - result += UpdateMappingFromPerson(mapping); + result += UpdateMappingFromPerson(locationContainersFiles, mapping); + if (mapping.MappingFromPerson is null || mapping.MappingFromPerson.LocationContainersFiles.Count == 0) + continue; + Stateless.MapLogic.MoveToDecade(propertyConfiguration, mapping.MappingFromItem, mapping.MappingFromPerson); } return result; } @@ -564,8 +603,8 @@ public class MapLogic : Shared.Models.Methods.IMapLogic Sorting sorting; FaceDistance faceDistanceLength; List? wholePercentagesCollection; - bool skipNotSkipCollectionAny = _SkipNotSkipCollection.Any(); - Dictionary? wholePercentagesToPersonContainers; + bool skipNotSkipCollectionAny = _SkipNotSkipCollection.Count > 0; + ReadOnlyDictionary>? wholePercentagesToPersonContainers; for (int j = 0; j < faceDistanceLengths.Count; j++) { if (faceDistanceEncoding.WholePercentages is null) @@ -615,14 +654,14 @@ public class MapLogic : Shared.Models.Methods.IMapLogic string mappingSegmentB; string personKeyFormatted; PersonBirthday personBirthday; - PersonContainer[]? personContainers; List wholePercentagesCollectionForA; List wholePercentagesCollectionForB; Dictionary keyToCount = new(); Dictionary keyToSegmentC = new(); + ReadOnlyCollection? personContainers; Dictionary> idToWholePercentagesCollectionForA = new(); Dictionary> idToWholePercentagesCollectionForB = new(); - Dictionary? wholePercentagesToPersonContainers; + ReadOnlyDictionary>? wholePercentagesToPersonContainers; int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - _Ticks).TotalSeconds); string message = $") {sortingContainers.Length:000} Update From Sorting Container(s) - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; @@ -707,11 +746,11 @@ public class MapLogic : Shared.Models.Methods.IMapLogic WindowsShortcut windowsShortcut; Dictionary? wholePercentagesToMapping; string by = nameof(Shared.Models.Stateless.IMapLogic.ManualCopy); - Dictionary? wholePercentagesToPeronContainerCollection; + ReadOnlyDictionary>? wholePercentagesToPeronContainerCollection; string successful = $"_ {nameof(Shared.Models.Stateless.IMapLogic.ManualCopy).Humanize(LetterCasing.Title)} Successful"; foreach (KeyValuePair personKeyToPersonContainer in _PersonKeyToPersonContainer) { - if (personKeyToPersonContainer.Value.Key is null || personKeyToPersonContainer.Value.Birthdays is null || !personKeyToPersonContainer.Value.Birthdays.Any() || personKeyToPersonContainer.Value.PersonDirectory is null) + if (personKeyToPersonContainer.Value.Key is null || personKeyToPersonContainer.Value.Birthdays is null || personKeyToPersonContainer.Value.Birthdays.Length == 0 || personKeyToPersonContainer.Value.PersonDirectory is null) continue; personBirthday = personKeyToPersonContainer.Value.Birthdays[zero]; foreach (string personDisplayDirectoryAllFile in personKeyToPersonContainer.Value.DisplayDirectoryAllFiles) @@ -786,49 +825,37 @@ public class MapLogic : Shared.Models.Methods.IMapLogic if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); List results = new(); + int count; long personKey; string directory; string? directoryName; PersonContainer? personContainer; - Dictionary personKeyToCount = new(); - for (int i = 1; i < 3; i++) + foreach (Mapping mapping in mappingCollection) { - foreach (Mapping mapping in mappingCollection) - { - if (mapping.MappingFromLocation is null || mapping.MappingFromPerson is null) - continue; - if (mapping.By is null or Shared.Models.Stateless.IMapLogic.Sorting) - continue; - if (string.IsNullOrEmpty(mapping.MappingFromPerson.SegmentB)) - throw new NotSupportedException(); - if (string.IsNullOrEmpty(mapping.MappingFromPerson.DisplayDirectoryName)) - throw new NotSupportedException(); - personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks; - if (mapping.MappingFromItem.ResizedFileHolder.DirectoryName is null || !mapping.MappingFromItem.ResizedFileHolder.Exists) - continue; - directoryName = Path.GetDirectoryName(mapping.MappingFromItem.RelativePath); - if (directoryName is null) - throw new NotSupportedException(); - if (!_PersonKeyToPersonContainer.TryGetValue(personKey, out personContainer)) - continue; - if (personContainer.PersonDirectory is null || !_Configuration.PersonCharacters.Contains(personContainer.PersonDirectory.Char)) - continue; - if (i == 1) - { - if (!personKeyToCount.ContainsKey(personKey)) - personKeyToCount.Add(personKey, 0); - personKeyToCount[personKey]++; - } - else if (i == 2) - { - directory = Path.Combine(a2PeopleSingletonDirectory, personContainer.PersonDirectory.Char.ToString(), personContainer.PersonDirectory.Group, personContainer.DisplayDirectoryName, personKeyToCount[personKey].ToString("0000")); - if (results.Contains(directory)) - continue; - results.Add(directory); - } - else - throw new NotSupportedException(); - } + if (mapping.MappingFromLocation is null || mapping.MappingFromPerson is null) + continue; + if (mapping.By is null or Shared.Models.Stateless.IMapLogic.Sorting) + continue; + if (string.IsNullOrEmpty(mapping.MappingFromPerson.SegmentB)) + throw new NotSupportedException(); + if (string.IsNullOrEmpty(mapping.MappingFromPerson.DisplayDirectoryName)) + throw new NotSupportedException(); + personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks; + if (mapping.MappingFromItem.ResizedFileHolder.DirectoryName is null || !mapping.MappingFromItem.ResizedFileHolder.Exists) + continue; + directoryName = Path.GetDirectoryName(mapping.MappingFromItem.RelativePath); + if (directoryName is null) + throw new NotSupportedException(); + if (!_PersonKeyToCount.TryGetValue(personKey, out count)) + continue; + if (!_PersonKeyToPersonContainer.TryGetValue(personKey, out personContainer)) + continue; + if (personContainer.PersonDirectory is null || !_Configuration.PersonCharacters.Contains(personContainer.PersonDirectory.Char)) + continue; + directory = Path.Combine(a2PeopleSingletonDirectory, personContainer.PersonDirectory.Char.ToString(), personContainer.PersonDirectory.Group, personContainer.DisplayDirectoryName, count.ToString("0000")); + if (results.Contains(directory)) + continue; + results.Add(directory); } return results; } @@ -1008,7 +1035,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic foreach ((long personKey, string displayDirectoryName) in collection) { matches = (from l in personContainers where l.Key == personKey && l.ApproximateYears.HasValue select l).ToArray(); - if (!matches.Any()) + if (matches.Length == 0) continue; personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personKey); if (!displayDirectoryName.Contains(personKeyFormatted)) @@ -1230,7 +1257,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic personDirectory = Path.Combine(directory, "No Faces"); fileName = Path.Combine(personDirectory, $"{item.ResizedFileHolder.Name}.lnk"); collection.Add(new(item.ResizedFileHolder.FullName, personDirectory, item.ImageFileHolder.LastWriteTime.Value, fileName, face.Mapping.MappingFromItem.Id.ToString(), MakeAllHidden: false)); - if (face.Mapping.MappingFromItem.ContainerDateTimes.Any() && !distinct.Contains(item.ResizedFileHolder.DirectoryName)) + if (face.Mapping.MappingFromItem.ContainerDateTimes.Length > 0 && !distinct.Contains(item.ResizedFileHolder.DirectoryName)) { distinct.Add(item.ResizedFileHolder.DirectoryName); directoriesAndDateTimes.Add(new(item.ResizedFileHolder.DirectoryName, face.Mapping.MappingFromItem.ContainerDateTimes)); @@ -1246,7 +1273,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic continue; if (mapping.By is null or Shared.Models.Stateless.IMapLogic.Sorting || mapping.MappingFromPerson?.ApproximateYears is null) { - if (mapping.MappingFromItem.ContainerDateTimes.Any() && !distinct.Contains(mapping.MappingFromItem.ResizedFileHolder.DirectoryName)) + if (mapping.MappingFromItem.ContainerDateTimes.Length > 0 && !distinct.Contains(mapping.MappingFromItem.ResizedFileHolder.DirectoryName)) { distinct.Add(mapping.MappingFromItem.ResizedFileHolder.DirectoryName); directoriesAndDateTimes.Add(new(mapping.MappingFromItem.ResizedFileHolder.DirectoryName, mapping.MappingFromItem.ContainerDateTimes)); @@ -1270,7 +1297,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic throw new NotSupportedException(); personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday); personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks; - if (mapping.MappingFromItem.ContainerDateTimes.Any() && !distinct.Contains(mapping.MappingFromItem.ResizedFileHolder.DirectoryName)) + if (mapping.MappingFromItem.ContainerDateTimes.Length > 0 && !distinct.Contains(mapping.MappingFromItem.ResizedFileHolder.DirectoryName)) { distinct.Add(mapping.MappingFromItem.ResizedFileHolder.DirectoryName); directoriesAndDateTimes.Add(new(mapping.MappingFromItem.ResizedFileHolder.DirectoryName, mapping.MappingFromItem.ContainerDateTimes)); @@ -1322,17 +1349,17 @@ public class MapLogic : Shared.Models.Methods.IMapLogic } foreach ((string directory, DateTime[] dateTimes) in directoriesAndDateTimes) { - if (!dateTimes.Any()) + if (dateTimes.Length == 0) continue; Directory.SetCreationTime(directory, dateTimes[0]); Directory.SetLastWriteTime(directory, dateTimes[1]); } } - public Dictionary> GetMissing(Dictionary> idToWholePercentagesToMapping) + public Dictionary>> GetMissing(Dictionary> idToWholePercentagesToMapping) { - Dictionary> results = new(); - foreach (KeyValuePair> idToCollection in _IdThenWholePercentagesToPersonContainers) + Dictionary>> results = new(); + foreach (KeyValuePair>> idToCollection in _IdThenWholePercentagesToPersonContainers) { if (idToWholePercentagesToMapping.ContainsKey(idToCollection.Key)) continue; @@ -1344,9 +1371,9 @@ public class MapLogic : Shared.Models.Methods.IMapLogic public bool IsUsed(bool ignoreXMatches, int id, MappingFromLocation mappingFromLocation) { bool result; - PersonContainer[]? personContainers; + ReadOnlyCollection? personContainers; List? wholePercentagesCollection; - Dictionary? wholePercentagesToPersonContainers; + ReadOnlyDictionary>? wholePercentagesToPersonContainers; result = _SkipCollection.TryGetValue(id, out wholePercentagesCollection) && wholePercentagesCollection.Contains(mappingFromLocation.WholePercentages); if (!result && _IdThenWholePercentagesToPersonContainers.TryGetValue(id, out wholePercentagesToPersonContainers)) { @@ -1360,19 +1387,15 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return result; } - public bool InSkipCollection(int id, MappingFromLocation mappingFromLocation) - { - bool result; - result = _SkipCollection.TryGetValue(id, out List? wholePercentagesCollection) && wholePercentagesCollection.Contains(mappingFromLocation.WholePercentages); - return result; - } + public bool InSkipCollection(int id, MappingFromLocation mappingFromLocation) => + _SkipCollection.TryGetValue(id, out List? wholePercentagesCollection) && wholePercentagesCollection.Contains(mappingFromLocation.WholePercentages); - public bool? IsFocusPerson(List<(string Directory, long PersonKey)> jLinkResolvedDirectories, int id, MappingFromLocation mappingFromLocation) + public bool? IsFocusPerson(int? skipPersonWithMoreThen, List<(string Directory, long PersonKey)> jLinkResolvedDirectories, int id, MappingFromLocation mappingFromLocation) { bool? result; - PersonContainer[]? personContainers; - Dictionary? wholePercentagesToPersonContainers; - if (jLinkResolvedDirectories.Count == 0) + ReadOnlyCollection? personContainers; + ReadOnlyDictionary>? wholePercentagesToPersonContainers; + if (skipPersonWithMoreThen is null && jLinkResolvedDirectories.Count == 0) result = null; else if (!_IdThenWholePercentagesToPersonContainers.TryGetValue(id, out wholePercentagesToPersonContainers)) result = null; @@ -1383,7 +1406,14 @@ public class MapLogic : Shared.Models.Methods.IMapLogic result = false; foreach (PersonContainer personContainer in personContainers) { - if (jLinkResolvedDirectories.Any(l => personContainer.Key == l.PersonKey)) + if (personContainer.Key is null) + continue; + if (skipPersonWithMoreThen is not null && _PersonKeyToCount.TryGetValue(personContainer.Key.Value, out int count) && count > 2 && count < skipPersonWithMoreThen.Value) + { + result = true; + break; + } + if (jLinkResolvedDirectories.Any(l => personContainer.Key.Value == l.PersonKey)) { result = true; break; @@ -1393,4 +1423,55 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return result; } + private void LookForAbandoned(Property.Models.Configuration propertyConfiguration, List distinctFilteredIds) + { + List renameCollection = new(); + foreach (KeyValuePair>> keyValuePair in _IdToLocationContainers) + { + if (distinctFilteredIds.Contains(keyValuePair.Key)) + continue; + foreach (LocationContainer locationContainer in keyValuePair.Value) + { + if (locationContainer.File.Contains('!')) + continue; + renameCollection.Add(locationContainer.File); + } + } + if (renameCollection.Count > 0) + IDirectory.MoveFiles(renameCollection, propertyConfiguration.ResultContent, "(abd)"); + } + + public void LookForAbandoned(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, Container[] containers, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory) + { + string[] directories; + string? directoryName; + List distinctFilteredIds = IContainer.GetFilteredDistinctIds(propertyConfiguration, containers); + LookForAbandoned(propertyConfiguration, distinctFilteredIds); + Stateless.MapLogic.LookForAbandoned(bResultsFullGroupDirectory, distinctFilteredIds); + directories = Directory.GetDirectories(cResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string directory in directories) + { + directoryName = Path.GetFileName(directory); + if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4)) + continue; + Stateless.MapLogic.LookForAbandoned(distinctFilteredIds, directory, directoryName); + } + directories = Directory.GetDirectories(dResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string directory in directories) + { + directoryName = Path.GetFileName(directory); + if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4)) + continue; + Stateless.MapLogic.LookForAbandoned(distinctFilteredIds, directory, directoryName); + } + directories = Directory.GetDirectories(d2ResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string directory in directories) + { + directoryName = Path.GetFileName(directory); + if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4)) + continue; + Stateless.MapLogic.LookForAbandoned(distinctFilteredIds, directory, directoryName); + } + } + } \ No newline at end of file diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index dd6cdf5..33f6fa7 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -4,6 +4,7 @@ using System.Collections.ObjectModel; using System.Diagnostics; using System.Drawing; using System.Globalization; +using System.Text.Json; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Stateless.Methods; using WindowsShortcutFactory; @@ -13,53 +14,77 @@ namespace View_by_Distance.Map.Models.Stateless; internal abstract class MapLogic { - private record Record(string PersonKeyFormatted, + internal record Record(string PersonKeyFormatted, string[] PersonDisplayDirectoryNames, bool IsDefault, string MappedFaceFile); - private record TicksDirectory(string Directory, - string DirectoryName, - long DirectoryTicks, - float? TotalDays); + internal record TicksDirectory(string Directory, + string DirectoryName, + DateTime DirectoryDateTime, + DateTime AlternateDirectoryDateTime, + float? TotalDays); - private record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted, - string[] PersonDisplayDirectoryNames, - bool IsDefault, - string MappedFaceFile, - int Id, - int WholePercentages); + internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted, + string[] PersonDisplayDirectoryNames, + bool IsDefault, + string MappedFaceFile, + int Id, + int WholePercentages); - private static void SetPersonCollections(Configuration configuration, ReadOnlyCollection personContainers, string? a2PeopleSingletonDirectory, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List personKeyFormattedCollection, Dictionary> skipCollection, Dictionary> skipNotSkipCollection) + internal static void SetSkipCollections(Configuration configuration, ReadOnlyCollection personContainers, string? a2PeopleSingletonDirectory, Dictionary> skipCollection, Dictionary> skipNotSkipCollection) { int? id; + string fileName; int? wholePercentages; - string personKeyFormatted; - string newestPersonKeyFormatted; - bool skipNotSkipDirectoriesAny = configuration.SkipNotSkipDirectories.Any(); - string[] checkDirectories = (from l in configuration.SkipNotSkipDirectories select Path.GetFullPath(string.Concat(a2PeopleSingletonDirectory, l))).ToArray(); + List distinctFiles = new(); + List distinctFileName = new(); + 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) { if (!personDisplayDirectoryAllFile.EndsWith(configuration.FacesFileNameExtension)) continue; - (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, personDisplayDirectoryAllFile); - if (id is null || wholePercentages is null) + if (distinctFiles.Contains(personDisplayDirectoryAllFile)) continue; - if (!skipNotSkipDirectoriesAny || !checkDirectories.Any(l => personDisplayDirectoryAllFile.StartsWith(l))) - { - if (!skipCollection.ContainsKey(id.Value)) - skipCollection.Add(id.Value, new()); - skipCollection[id.Value].Add(wholePercentages.Value); - } - else - { - if (!skipNotSkipCollection.ContainsKey(id.Value)) - skipNotSkipCollection.Add(id.Value, new()); - skipNotSkipCollection[id.Value].Add(wholePercentages.Value); - } + distinctFiles.Add(personDisplayDirectoryAllFile); } + } + foreach (string distinctFile in distinctFiles) + { + fileName = Path.GetFileName(distinctFile); + if (distinctFileName.Contains(fileName)) + { + if (!distinctFile.EndsWith(".dup") && !File.Exists($"{distinctFile}.dup")) + File.Move(distinctFile, $"{distinctFile}.dup"); + continue; + } + (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, distinctFile); + if (id is null || wholePercentages is null) + continue; + if (!skipNotSkipDirectoriesAny || !checkDirectories.Any(l => distinctFile.StartsWith(l))) + { + if (!skipCollection.ContainsKey(id.Value)) + skipCollection.Add(id.Value, new()); + skipCollection[id.Value].Add((distinctFile, wholePercentages.Value)); + } + else + { + if (!skipNotSkipCollection.ContainsKey(id.Value)) + skipNotSkipCollection.Add(id.Value, new()); + skipNotSkipCollection[id.Value].Add((distinctFile, wholePercentages.Value)); + } + } + } + + private static void SetPersonCollections(Configuration configuration, ReadOnlyCollection personContainers, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List personKeyFormattedCollection) + { + string personKeyFormatted; + string newestPersonKeyFormatted; + foreach (PersonContainer personContainer in personContainers) + { if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Birthdays.Length == 0) continue; foreach (PersonBirthday personBirthday in personContainer.Birthdays) @@ -220,201 +245,222 @@ internal abstract class MapLogic } } - private static List DeleteEmptyDirectoriesAndGetCollection(Configuration configuration, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List personKeyFormattedCollection, List ticksDirectories, string message) + private static List DeleteEmptyDirectoriesAndGetCollection(Configuration configuration, long ticks, string eDistanceContentDirectory, ReadOnlyDictionary personKeyFormattedToNewestPersonKeyFormatted, ReadOnlyCollection personKeyFormattedCollection) { List results = new(); int? id; + bool check; bool isDefault; + string message; string[] files; string fileName; + int totalSeconds; DateTime dateTime; TimeSpan timeSpan; - bool check = false; int? wholePercentages; - string checkDirectory; + string? checkDirectory; + ProgressBar progressBar; string[] yearDirectories; string personKeyFormatted; string? personFirstInitial; bool isReservedDirectoryName; List distinct = new(); - string[] personKeyDirectories; string[] personNameDirectories; string? newestPersonKeyFormatted; string[] personNameLinkDirectories; string? personFirstInitialDirectory; string[] personDisplayDirectoryNames; + List ticksDirectories; + string[] personKeyFormattedDirectories; string manualCopyHumanized = nameof(Shared.Models.Stateless.IMapLogic.ManualCopy).Humanize(LetterCasing.Title); string forceSingleImageHumanized = nameof(Shared.Models.Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title); ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; - using ProgressBar progressBar = new(ticksDirectories.Count, message, options); - foreach (TicksDirectory ticksDirectory in ticksDirectories) + for (int i = 1; i < 3; i++) { - progressBar.Tick(); - personKeyDirectories = Directory.GetDirectories(ticksDirectory.Directory, "*", SearchOption.TopDirectoryOnly); - foreach (string personKeyDirectory in personKeyDirectories) + check = false; + results.Clear(); + distinct.Clear(); + ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(eDistanceContentDirectory); + totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); + message = $"{i}) {ticksDirectories.Count:000} compile from and clean ticks Director(ies) - B - {totalSeconds} total second(s)"; + progressBar = new(ticksDirectories.Count, message, options); + foreach (TicksDirectory ticksDirectory in ticksDirectories) { - personKeyFormatted = Path.GetFileName(personKeyDirectory); - isReservedDirectoryName = personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Sorting)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Mapping)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.ManualCopy)); - if (!isReservedDirectoryName && personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Individually))) + if (i == 1) + progressBar.Tick(); + personKeyFormattedDirectories = Directory.GetDirectories(ticksDirectory.Directory, "*", SearchOption.TopDirectoryOnly); + foreach (string personKeyFormattedDirectory in personKeyFormattedDirectories) { - Individually(configuration, ticksDirectory, personKeyDirectory); - throw new Exception($"B) Move personKey directories up one from {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} and delete {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} directory!"); - } - _ = personKeyFormattedToNewestPersonKeyFormatted.TryGetValue(personKeyFormatted, out newestPersonKeyFormatted); - if (personKeyFormattedToNewestPersonKeyFormatted.Count > 0 && newestPersonKeyFormatted is null) - { - timeSpan = new TimeSpan(DateTime.Now.Ticks - ticksDirectory.DirectoryTicks); - if (timeSpan.TotalDays > 7) - throw new Exception($"{configuration.MappingDefaultName} are only allowed within x days!"); - } - yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly); - foreach (string yearDirectory in yearDirectories) - { - files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly); - personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly); - foreach (string file in files) - File.Delete(file); - foreach (string personNameDirectory in personNameDirectories) + personKeyFormatted = Path.GetFileName(personKeyFormattedDirectory); + isReservedDirectoryName = personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Sorting)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Mapping)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.ManualCopy)); + if (!isReservedDirectoryName && personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Individually))) { - personDisplayDirectoryNames = IPath.GetDirectoryNames(personNameDirectory); - if (!personDisplayDirectoryNames.Any()) + Individually(configuration, ticksDirectory, personKeyFormattedDirectory); + throw new Exception($"B) Move personKey directories up one from {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} and delete {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} directory!"); + } + _ = personKeyFormattedToNewestPersonKeyFormatted.TryGetValue(personKeyFormatted, out newestPersonKeyFormatted); + if (personKeyFormattedToNewestPersonKeyFormatted.Count > 0 && newestPersonKeyFormatted is null) + { + timeSpan = new TimeSpan(DateTime.Now.Ticks - ticksDirectory.DirectoryDateTime.Ticks); + if (timeSpan.TotalDays > 6) + throw new Exception($"{configuration.MappingDefaultName} are only allowed within x days!"); + } + yearDirectories = Directory.GetDirectories(personKeyFormattedDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string yearDirectory in yearDirectories) + { + if (check && !Directory.Exists(yearDirectory)) continue; - isDefault = personDisplayDirectoryNames[^1].First() == 'X' && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]); - if (isDefault && personDisplayDirectoryNames[^1].Length == 1) + files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly); + personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string file in files) + File.Delete(file); + foreach (string personNameDirectory in personNameDirectories) { - if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length || !DateTime.TryParseExact(personKeyFormatted, configuration.PersonBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) + personDisplayDirectoryNames = IPath.GetDirectoryNames(personNameDirectory); + if (!personDisplayDirectoryNames.Any()) continue; - checkDirectory = Path.Combine(yearDirectory, $"X]{dateTime.Ticks}"); - if (Directory.Exists(checkDirectory)) - { - Directory.Delete(yearDirectory, recursive: true); - continue; - } - Directory.Move(personNameDirectory, checkDirectory); - if (!check) - check = true; - continue; - } - files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly); - if (isReservedDirectoryName && files.Any()) - throw new Exception($"Move personKey directories up one from {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} and delete {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} directory!"); - if (personKeyFormatted == manualCopyHumanized && files.Any()) - throw new Exception($"Move personKey directories up one from {manualCopyHumanized} and delete {manualCopyHumanized} directory!"); - if (personKeyFormatted == forceSingleImageHumanized && files.Any()) - throw new Exception($"Move personKey directories up one from {forceSingleImageHumanized} and delete {forceSingleImageHumanized} directory!"); - if (!isDefault) - { - if (personKeyFormattedToNewestPersonKeyFormatted.Count > 0 && newestPersonKeyFormatted is null) - RenameUnknown(files); - else if (newestPersonKeyFormatted is not null && personKeyFormatted != newestPersonKeyFormatted) + isDefault = personDisplayDirectoryNames[^1].First() == 'X' && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]); + if (isDefault && personDisplayDirectoryNames[^1].Length == 1) { + if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length || !DateTime.TryParseExact(personKeyFormatted, configuration.PersonBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) + continue; + checkDirectory = Path.Combine(yearDirectory, $"X]{dateTime.Ticks}"); + if (Directory.Exists(checkDirectory)) + { + Directory.Delete(yearDirectory, recursive: true); + continue; + } + Directory.Move(personNameDirectory, checkDirectory); if (!check) check = true; - MovedToNewestPersonKeyFormatted(personKeyFormatted, newestPersonKeyFormatted, ticksDirectory, personKeyDirectory); continue; } - } - if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length) - continue; - if (personDisplayDirectoryNames[^1].Length == 1 || isDefault || !personKeyFormattedCollection.Contains(personKeyFormatted)) - personFirstInitialDirectory = personNameDirectory; - else - { - personFirstInitial = personDisplayDirectoryNames[^1][..1]; - if (personFirstInitial.All(l => char.IsDigit(l))) + if (isDefault && (ticksDirectory.DirectoryDateTime.Hour != 0 || ticksDirectory.DirectoryDateTime.Minute != 0 || ticksDirectory.DirectoryDateTime.Second != 0)) { - foreach (string file in files) - File.Delete(file); - files = Directory.GetFiles(personNameDirectory, "*", SearchOption.AllDirectories); - foreach (string file in files) - File.Delete(file); - _ = IPath.DeleteEmptyDirectories(personNameDirectory); - continue; - } - personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial.ToString()); - if (Directory.Exists(personFirstInitialDirectory)) - throw new Exception("Forgot to ..."); - Directory.Move(personNameDirectory, personFirstInitialDirectory); - files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); - } - foreach (string mappedFaceFile in files) - { - if (mappedFaceFile.EndsWith(".lnk")) - continue; - (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFaceFile); - if (id is null || wholePercentages is null) - continue; - fileName = Path.GetFileName(mappedFaceFile); - if (distinct.Contains(fileName)) - { - if (!File.Exists($"{mappedFaceFile}.dup")) - File.Move(mappedFaceFile, $"{mappedFaceFile}.dup"); - continue; - } - distinct.Add(fileName); - results.Add(new(personKeyFormatted, personDisplayDirectoryNames, isDefault, mappedFaceFile)); - } - personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); - foreach (string personNameLinkDirectory in personNameLinkDirectories) - { - files = Directory.GetFiles(personNameLinkDirectory, "*", SearchOption.TopDirectoryOnly); - foreach (string file in files) - { - if (!file.EndsWith(".lnk")) + checkDirectory = Path.GetDirectoryName(ticksDirectory.Directory); + if (checkDirectory is null) continue; - File.Delete(file); + checkDirectory = Path.Combine(checkDirectory, $"({ticksDirectory.AlternateDirectoryDateTime.Ticks})"); + if (!Directory.Exists(checkDirectory)) + _ = Directory.CreateDirectory(checkDirectory); + checkDirectory = Path.Combine(checkDirectory, personKeyFormatted); + if (!Directory.Exists(checkDirectory)) + { + Directory.Move(personKeyFormattedDirectory, checkDirectory); + if (!check) + check = true; + break; + } } - _ = IPath.DeleteEmptyDirectories(personNameLinkDirectory); + files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly); + if (isReservedDirectoryName && files.Length > 0) + throw new Exception($"Move personKey directories up one from {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} and delete {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} directory!"); + if (personKeyFormatted == manualCopyHumanized && files.Length > 0) + throw new Exception($"Move personKey directories up one from {manualCopyHumanized} and delete {manualCopyHumanized} directory!"); + if (personKeyFormatted == forceSingleImageHumanized && files.Length > 0) + throw new Exception($"Move personKey directories up one from {forceSingleImageHumanized} and delete {forceSingleImageHumanized} directory!"); + if (!isDefault) + { + if (personKeyFormattedToNewestPersonKeyFormatted.Count > 0 && newestPersonKeyFormatted is null) + RenameUnknown(files); + else if (newestPersonKeyFormatted is not null && personKeyFormatted != newestPersonKeyFormatted) + { + if (!check) + check = true; + MovedToNewestPersonKeyFormatted(personKeyFormatted, newestPersonKeyFormatted, ticksDirectory, personKeyFormattedDirectory); + continue; + } + } + if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length) + continue; + if (personDisplayDirectoryNames[^1].Length == 1 || isDefault || !personKeyFormattedCollection.Contains(personKeyFormatted)) + personFirstInitialDirectory = personNameDirectory; + else + { + personFirstInitial = personDisplayDirectoryNames[^1][..1]; + if (personFirstInitial.All(l => char.IsDigit(l))) + { + foreach (string file in files) + File.Delete(file); + files = Directory.GetFiles(personNameDirectory, "*", SearchOption.AllDirectories); + foreach (string file in files) + File.Delete(file); + _ = IPath.DeleteEmptyDirectories(personNameDirectory); + continue; + } + personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial.ToString()); + if (Directory.Exists(personFirstInitialDirectory)) + throw new Exception("Forgot to ..."); + Directory.Move(personNameDirectory, personFirstInitialDirectory); + files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); + } + foreach (string mappedFaceFile in files) + { + if (mappedFaceFile.EndsWith(".lnk")) + continue; + (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFaceFile); + if (id is null || wholePercentages is null) + continue; + fileName = Path.GetFileName(mappedFaceFile); + if (distinct.Contains(fileName)) + { + if (!mappedFaceFile.EndsWith(".dup") && !File.Exists($"{mappedFaceFile}.dup")) + File.Move(mappedFaceFile, $"{mappedFaceFile}.dup"); + continue; + } + distinct.Add(fileName); + results.Add(new(personKeyFormatted, personDisplayDirectoryNames, isDefault, mappedFaceFile)); + } + personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string personNameLinkDirectory in personNameLinkDirectories) + { + files = Directory.GetFiles(personNameLinkDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string file in files) + { + if (!file.EndsWith(".lnk")) + continue; + File.Delete(file); + } + _ = IPath.DeleteEmptyDirectories(personNameLinkDirectory); + } + _ = IPath.DeleteEmptyDirectories(personFirstInitialDirectory); } - _ = IPath.DeleteEmptyDirectories(personFirstInitialDirectory); + _ = IPath.DeleteEmptyDirectories(yearDirectory); } - _ = IPath.DeleteEmptyDirectories(yearDirectory); + _ = IPath.DeleteEmptyDirectories(personKeyFormattedDirectory); } - _ = IPath.DeleteEmptyDirectories(personKeyDirectory); + _ = IPath.DeleteEmptyDirectories(ticksDirectory.Directory); + _ = IPath.DeleteEmptyDirectories(ticksDirectory.Directory); } - _ = IPath.DeleteEmptyDirectories(ticksDirectory.Directory); - _ = IPath.DeleteEmptyDirectories(ticksDirectory.Directory); + progressBar.Dispose(); + if (check) + continue; + break; } - if (check) - throw new Exception("PersonKey director(ies) where renamed. Please restart!"); return results; } - private static PersonContainer[] GetDistinctPersonContainers(List personContainers) - { - List results = new(); - List distinctCheck = new(); - foreach (PersonContainer personContainer in personContainers) - { - if (personContainer.Key is null || distinctCheck.Contains(personContainer.Key.Value)) - continue; - results.Add(personContainer); - } - return results.ToArray(); - } - - private static void SetKeyValuePairsAndAddToCollections(Configuration configuration, ReadOnlyCollection personContainers, Dictionary> personKeyToPersonContainerCollection, Dictionary personKeyFormattedToPersonContainer, List personKeyFormattedIdThenWholePercentagesCollection, Dictionary personKeyToPersonContainer, Dictionary> idThenWholePercentagesToPersonContainers, List<(PersonKeyFormattedIdThenWholePercentages, PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) + internal static void SetKeyValuePairsAndAddToCollections(Configuration configuration, ReadOnlyCollection personContainers, Dictionary personKeyToPersonContainer, ReadOnlyCollection personKeyFormattedIdThenWholePercentagesCollection, Dictionary personKeyToCount, Dictionary personKeyFormattedToPersonContainer, Dictionary> personKeyToPersonContainerCollection, List<(PersonKeyFormattedIdThenWholePercentages, PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) { PersonBirthday? personBirthday; - PersonContainer[] distinctPersonContainers; + Dictionary>> idThenWholePercentagesToPersonContainers = new(); (long, PersonContainer)[] collection = GetDistinctCollection(configuration, personContainers, personKeyToPersonContainerCollection, personKeyFormattedToPersonContainer); foreach ((long personKey, PersonContainer personContainer) in collection) personKeyToPersonContainer.Add(personKey, personContainer); - Dictionary>> idThenWholePercentagesToPersonContainerCollection = new(); - if (personKeyFormattedIdThenWholePercentagesCollection.Any()) + if (personKeyFormattedIdThenWholePercentagesCollection.Count > 0) { string group; char[] matches; char status, sex, first; - PersonContainer personContainer; PersonDirectory personDirectory; + PersonContainer? personContainer; string personDisplayDirectoryName; foreach (PersonKeyFormattedIdThenWholePercentages personKeyFormattedIdThenWholePercentages in personKeyFormattedIdThenWholePercentagesCollection) { personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormattedIdThenWholePercentages.PersonKeyFormatted); if (personBirthday is null) - continue; - if (!personKeyFormattedToPersonContainer.ContainsKey(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted)) + throw new Exception(); + if (!personKeyFormattedToPersonContainer.TryGetValue(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, out personContainer)) { personDisplayDirectoryName = personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryNames[^1]; matches = configuration.PersonCharacters.Where(l => personDisplayDirectoryName.Contains(l)).ToArray(); @@ -426,23 +472,85 @@ internal abstract class MapLogic personContainer = new(configuration.PersonCharacters.ToArray(), personBirthday, personDisplayDirectoryName, personDirectory); personKeyFormattedToPersonContainer.Add(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, personContainer); } - if (!idThenWholePercentagesToPersonContainerCollection.ContainsKey(personKeyFormattedIdThenWholePercentages.Id)) - idThenWholePercentagesToPersonContainerCollection.Add(personKeyFormattedIdThenWholePercentages.Id, new()); - if (!idThenWholePercentagesToPersonContainerCollection[personKeyFormattedIdThenWholePercentages.Id].ContainsKey(personKeyFormattedIdThenWholePercentages.WholePercentages)) - idThenWholePercentagesToPersonContainerCollection[personKeyFormattedIdThenWholePercentages.Id].Add(personKeyFormattedIdThenWholePercentages.WholePercentages, new()); - idThenWholePercentagesToPersonContainerCollection[personKeyFormattedIdThenWholePercentages.Id][personKeyFormattedIdThenWholePercentages.WholePercentages].Add(personKeyFormattedToPersonContainer[personKeyFormattedIdThenWholePercentages.PersonKeyFormatted]); - possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Add(new(personKeyFormattedIdThenWholePercentages, personKeyFormattedToPersonContainer[personKeyFormattedIdThenWholePercentages.PersonKeyFormatted])); + if (personContainer.Key is null) + throw new Exception(); + if (!personKeyToCount.ContainsKey(personContainer.Key.Value)) + personKeyToCount.Add(personContainer.Key.Value, 0); + personKeyToCount[personContainer.Key.Value]++; + possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Add(new(personKeyFormattedIdThenWholePercentages, personContainer)); } } - foreach (KeyValuePair>> keyValuePair in idThenWholePercentagesToPersonContainerCollection) + } + + private static Dictionary>> GetAll(Configuration configuration, ReadOnlyDictionary personKeyFormattedToPersonContainer, ReadOnlyCollection personKeyFormattedIdThenWholePercentagesCollection) + { + Dictionary>> results = new(); + PersonBirthday? personBirthday; + PersonContainer? personContainer; + List? personContainers; + Dictionary>? idTo; + if (personKeyFormattedIdThenWholePercentagesCollection.Count > 0) { - idThenWholePercentagesToPersonContainers.Add(keyValuePair.Key, new()); - foreach (KeyValuePair> innerKeyValuePair in keyValuePair.Value) + foreach (PersonKeyFormattedIdThenWholePercentages personKeyFormattedIdThenWholePercentages in personKeyFormattedIdThenWholePercentagesCollection) { - distinctPersonContainers = GetDistinctPersonContainers(innerKeyValuePair.Value); - idThenWholePercentagesToPersonContainers[keyValuePair.Key].Add(innerKeyValuePair.Key, distinctPersonContainers); + personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormattedIdThenWholePercentages.PersonKeyFormatted); + if (personBirthday is null) + throw new Exception(); + if (!personKeyFormattedToPersonContainer.TryGetValue(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, out personContainer)) + throw new Exception(); + if (!results.TryGetValue(personKeyFormattedIdThenWholePercentages.Id, out idTo)) + { + results.Add(personKeyFormattedIdThenWholePercentages.Id, new()); + if (!results.TryGetValue(personKeyFormattedIdThenWholePercentages.Id, out idTo)) + throw new Exception(); + } + if (!idTo.TryGetValue(personKeyFormattedIdThenWholePercentages.WholePercentages, out personContainers)) + { + idTo.Add(personKeyFormattedIdThenWholePercentages.WholePercentages, new()); + if (!idTo.TryGetValue(personKeyFormattedIdThenWholePercentages.WholePercentages, out personContainers)) + throw new Exception(); + } + personContainers.Add(personContainer); } - }; + } + return results; + } + + private static ReadOnlyDictionary>> GetReadOnly(Dictionary>> idThenWholePercentagesToPersonContainerCollection) + { + Dictionary>> results = new(); + List distinct = new(); + List personContainers; + Dictionary> keyValuePairs; + foreach (KeyValuePair>> idTo in idThenWholePercentagesToPersonContainerCollection) + { + keyValuePairs = new(); + foreach (KeyValuePair> wholePercentagesTo in idThenWholePercentagesToPersonContainerCollection[idTo.Key]) + { + distinct.Clear(); + personContainers = new(); + foreach (PersonContainer personContainer in wholePercentagesTo.Value) + { + if (personContainer.Key is null) + throw new Exception(); + if (distinct.Contains(personContainer.Key.Value)) + continue; + personContainers.Add(personContainer); + } + keyValuePairs.Add(wholePercentagesTo.Key, new(personContainers)); + } + results.Add(idTo.Key, new(keyValuePairs)); + } + return new(results); + } + + internal static ReadOnlyDictionary>> GetIdThenWholePercentagesToPersonContainers(Configuration configuration, ReadOnlyDictionary personKeyFormattedToPersonContainer, ReadOnlyCollection personKeyFormattedIdThenWholePercentagesCollection) + { + ReadOnlyDictionary>> results; + Dictionary>> idThenWholePercentagesToPersonContainerCollection; + idThenWholePercentagesToPersonContainerCollection = GetAll(configuration, personKeyFormattedToPersonContainer, personKeyFormattedIdThenWholePercentagesCollection); + results = GetReadOnly(idThenWholePercentagesToPersonContainerCollection); + return results; } private static (long, PersonContainer)[] GetDistinctCollection(Configuration configuration, IEnumerable personContainers, Dictionary> personKeyToPersonContainerCollection, Dictionary personKeyFormattedToPersonContainer) @@ -469,15 +577,15 @@ internal abstract class MapLogic errors.Add(keyValuePair.Value[zero].DisplayDirectoryName); collection.Add(new(keyValuePair.Key, keyValuePair.Value[zero])); } - if (errors.Any()) + if (errors.Count > 0) throw new Exception(string.Join(Environment.NewLine, errors)); results = (from l in collection orderby l.PersonKey descending select (l.PersonKey, l.PersonContainer)).ToArray(); return results; } - private static int SetCollectionsAndGetUnableToConvertCount(Configuration configuration, long ticks, List personKeyFormattedIdThenWholePercentagesCollection, List collection) + internal static ReadOnlyCollection GetPersonKeyFormattedIdThenWholePercentages(Configuration configuration, long ticks, List collection) { - int result = 0; + List results = new(); int? id; int? wholePercentages; string personDisplayDirectoryName; @@ -492,10 +600,7 @@ internal abstract class MapLogic progressBar.Tick(); (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, record.MappedFaceFile); if (id is null || wholePercentages is null) - { - result++; continue; - } if (!idToWholePercentagesCollection.ContainsKey(id.Value)) idToWholePercentagesCollection.Add(id.Value, new()); wholePercentagesCollection = idToWholePercentagesCollection[id.Value]; @@ -504,12 +609,12 @@ internal abstract class MapLogic personDisplayDirectoryName = record.PersonDisplayDirectoryNames[^1]; if (string.IsNullOrEmpty(personDisplayDirectoryName)) continue; - personKeyFormattedIdThenWholePercentagesCollection.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryNames, record.IsDefault, record.MappedFaceFile, id.Value, wholePercentages.Value)); + results.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryNames, record.IsDefault, record.MappedFaceFile, id.Value, wholePercentages.Value)); } - return result; + return new(results); } - private static List GetNonSpecificPeopleCollection(Configuration configuration, long ticks, List personKeys) + private static List GetNonSpecificPeopleCollection(Configuration configuration, long ticks, List personKeys, ReadOnlyDictionary personKeyToCount) { List results = new(); bool check; @@ -529,6 +634,8 @@ internal abstract class MapLogic break; if (personKeys.Contains(personKey)) continue; + if (personKeyToCount.ContainsKey(personKey)) + continue; for (int j = 1; j < 24; j++) { if (personKeys.Contains(personKey + (oneHour * j))) @@ -536,6 +643,11 @@ internal abstract class MapLogic check = true; break; } + if (personKeyToCount.ContainsKey(personKey + (oneHour * j))) + { + check = true; + break; + } } if (check) continue; @@ -548,7 +660,7 @@ internal abstract class MapLogic return results; } - private static List GetNotMappedPersonContainers(Configuration configuration, long ticks, ReadOnlyCollection personContainers, long[] personKeyCollection) + internal static List GetNotMappedPersonContainers(Configuration configuration, long ticks, ReadOnlyCollection personContainers, ReadOnlyDictionary personKeyToCount) { List results = new(); List notMappedAndNotNamedPersonKeys = new(); @@ -560,7 +672,7 @@ internal abstract class MapLogic continue; if (personKeys.Contains(personContainer.Key.Value)) continue; - if (personKeyCollection.Contains(personContainer.Key.Value)) + if (personKeyToCount.ContainsKey(personContainer.Key.Value)) continue; if (string.IsNullOrEmpty(personContainer.DisplayDirectoryName) || personContainer.DisplayDirectoryName == configuration.MappingDefaultName) notMappedAndNotNamedPersonKeys.Add(personContainer); @@ -569,7 +681,7 @@ internal abstract class MapLogic } results.AddRange(notMappedAndNotNamedPersonKeys); if (results.Count == 0) - results.AddRange(GetNonSpecificPeopleCollection(configuration, ticks, personKeys)); + results.AddRange(GetNonSpecificPeopleCollection(configuration, ticks, personKeys, personKeyToCount)); return results; } @@ -585,40 +697,40 @@ internal abstract class MapLogic return result; } - private static void SetPersonKeyToPersonContainer(Configuration configuration, ReadOnlyCollection personContainers, long[] personKeyCollection, Dictionary personKeyToPersonContainer, Dictionary> personKeyToPersonContainerCollection) + internal static void SetPersonKeyToPersonContainer(Configuration configuration, ReadOnlyCollection personContainers, ReadOnlyDictionary personKeyToCount, Dictionary personKeyToPersonContainer, ReadOnlyDictionary> personKeyToPersonContainerCollection) { string? displayDirectoryName; foreach (PersonContainer personContainer in personContainers) { - if (personContainer.Key is null || !personKeyCollection.Contains(personContainer.Key.Value)) + if (personContainer.Key is null || !personKeyToCount.ContainsKey(personContainer.Key.Value)) continue; displayDirectoryName = GetDisplayDirectoryName(personKeyToPersonContainer, personContainer.Key.Value); if (displayDirectoryName is not null && (displayDirectoryName == personContainer.DisplayDirectoryName || (displayDirectoryName[0] == personContainer.DisplayDirectoryName[0] && (displayDirectoryName.Length == 1 || personContainer.DisplayDirectoryName.Length == 1)))) continue; personKeyToPersonContainer.Add(personContainer.Key.Value, personContainer); } - if (personKeyCollection.Any()) + if (personKeyToCount.Count > 0) { const int zero = 0; int? approximateYears = null; PersonBirthday? personBirthday; PersonContainer personContainer; displayDirectoryName = configuration.MappingDefaultName; - foreach (long personKey in personKeyCollection) + foreach (KeyValuePair keyValuePair in personKeyToCount) { - if (personKeyToPersonContainer.ContainsKey(personKey)) + if (personKeyToPersonContainer.ContainsKey(keyValuePair.Key)) continue; - personBirthday = IPersonBirthday.GetPersonBirthday(personKey); - if (!personKeyToPersonContainerCollection.ContainsKey(personKey)) - personContainer = new(approximateYears, personBirthday, displayDirectoryName, personKey); + personBirthday = IPersonBirthday.GetPersonBirthday(keyValuePair.Key); + if (!personKeyToPersonContainerCollection.ContainsKey(keyValuePair.Key)) + personContainer = new(approximateYears, personBirthday, displayDirectoryName, keyValuePair.Key); else - personContainer = new(approximateYears, personBirthday, personKeyToPersonContainerCollection[personKey][zero].PersonDirectory, displayDirectoryName, personKey); - personKeyToPersonContainer.Add(personKey, personContainer); + personContainer = new(approximateYears, personBirthday, personKeyToPersonContainerCollection[keyValuePair.Key][zero].PersonDirectory, displayDirectoryName, keyValuePair.Key); + personKeyToPersonContainer.Add(keyValuePair.Key, personContainer); } } } - static void PossiblyRebuildPersonContainers(Configuration configuration, string? a2PeopleSingletonDirectory, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List<(PersonKeyFormattedIdThenWholePercentages, PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) + internal static void PossiblyRebuildPersonContainers(Configuration configuration, string? a2PeopleSingletonDirectory, List<(PersonKeyFormattedIdThenWholePercentages, PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) { bool[] matches; string fileName; @@ -648,7 +760,7 @@ internal abstract class MapLogic 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 (personKeyFormattedToNewestPersonKeyFormatted.Count > 0 && personContainer.DisplayDirectoryAllFiles.Length != 0 && deleteCollection.Length == 0) + if (personContainer.DisplayDirectoryAllFiles.Length != 0 && deleteCollection.Length == 0) throw new NotSupportedException(); if (!Directory.Exists(personKeyFormattedDirectory)) _ = Directory.CreateDirectory(personKeyFormattedDirectory); @@ -676,6 +788,7 @@ internal abstract class MapLogic List results = new(); float? totalDays; string ticksDirectoryName; + DateTime directoryDateTime; DirectoryInfo directoryInfo; long? lastDirectoryTicks = null; DateTime dateTime = DateTime.Now; @@ -693,16 +806,17 @@ internal abstract class MapLogic throw new NotSupportedException(); } directoryInfo = new(ticksDirectory); + directoryDateTime = new DateTime(directoryTicks); if (directoryInfo.CreationTime.Ticks != directoryTicks) Directory.SetCreationTime(ticksDirectory, new DateTime(directoryTicks)); if (directoryInfo.LastWriteTime.Ticks != directoryTicks) Directory.SetLastWriteTime(ticksDirectory, new DateTime(directoryTicks)); totalDays = lastDirectoryTicks is null || new TimeSpan(dateTime.Ticks - directoryTicks).TotalDays < 1 ? null : (float)new TimeSpan(directoryTicks - lastDirectoryTicks.Value).TotalDays; - results.Add(new(ticksDirectory, ticksDirectoryName, directoryTicks, totalDays)); + results.Add(new(ticksDirectory, ticksDirectoryName, new(directoryTicks), new DateTime(directoryDateTime.Year, directoryDateTime.Month, directoryDateTime.Day + 1), totalDays)); lastDirectoryTicks = directoryTicks; } string[] compare = (from l in results where l.TotalDays is not null and < 3.95f select l.Directory).ToArray(); - if (compare.Any()) + if (compare.Length > 0) throw new Exception($"Please Consolidate <{string.Join(Environment.NewLine, compare)}>"); return results; } @@ -769,11 +883,13 @@ internal abstract class MapLogic return results; } - private static void ParallelFor(Configuration configuration, string eDistanceContentDirectory, List> locationContainers, long personKey, string file) + private static void ParallelFor(Configuration configuration, string eDistanceContentDirectory, Dictionary> skipCollection, List> locationContainers, long personKey, string file) { + string[] fileMatches; const string lnk = ".lnk"; int? id, wholePercentages; IReadOnlyList directories; + List<(string File, int WholePercentages)>? wholePercentagesCollection; bool fromDistanceContent = !file.EndsWith(lnk) && file.Contains(eDistanceContentDirectory); if (!file.EndsWith(lnk)) (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, file); @@ -781,6 +897,15 @@ internal abstract class MapLogic (id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, file[..^4]); if (id is null || wholePercentages is null) return; + if (skipCollection.TryGetValue(id.Value, out wholePercentagesCollection)) + { + fileMatches = (from l in wholePercentagesCollection where l.WholePercentages == wholePercentages select l.File).ToArray(); + foreach (string fileMatch in fileMatches) + { + if (!fileMatch.EndsWith(".dup") && !File.Exists($"{fileMatch}.dup")) + File.Move(fileMatch, $"{fileMatch}.dup"); + } + } if (file.EndsWith(lnk) || (!configuration.DistanceMoveUnableToMatch && !configuration.DistanceRenameToMatch) || !File.Exists(file)) directories = new List(); else @@ -816,7 +941,7 @@ internal abstract class MapLogic } } - private static void LookForPossibleDuplicates(Configuration configuration, List> locationContainers) + private static void LookForPossibleDuplicates(Configuration configuration, ReadOnlyCollection> locationContainers) { string key; float? percent; @@ -848,7 +973,7 @@ internal abstract class MapLogic } distinct.Add(key, new(locationContainer.File, locationContainer.WholePercentages)); } - if (!configuration.DeletePossibleDuplicates && duplicates.Any()) + if (!configuration.DeletePossibleDuplicates && duplicates.Count > 0) OpenPossibleDuplicates(configuration, duplicates); else { @@ -862,11 +987,11 @@ internal abstract class MapLogic } } - private static List> GetLocationContainers(int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection personContainers, string eDistanceContentDirectory, List records) + internal static List> GetLocationContainers(int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection personContainers, string eDistanceContentDirectory, Dictionary> skipCollection, List records) { List> results = new(); List<(long PersonKey, string File)> collection = GetCollection(configuration, personContainers, records); - if (collection.Any() && (configuration.DistanceMoveUnableToMatch || configuration.DistanceRenameToMatch)) + if (collection.Count > 0 && (configuration.DistanceMoveUnableToMatch || configuration.DistanceRenameToMatch)) { int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") Building Mapped Face Files Collection - {totalSeconds} total second(s)"; @@ -876,48 +1001,21 @@ internal abstract class MapLogic _ = Parallel.For(0, collection.Count, parallelOptions, (i, state) => { progressBar.Tick(); - ParallelFor(configuration, eDistanceContentDirectory, results, collection[i].PersonKey, collection[i].File); + ParallelFor(configuration, eDistanceContentDirectory, skipCollection, results, collection[i].PersonKey, collection[i].File); }); } - LookForPossibleDuplicates(configuration, results); + LookForPossibleDuplicates(configuration, new(results)); return results; } - internal static void Set(int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection personContainers, string? a2PeopleSingletonDirectory, string eDistanceContentDirectory, Dictionary personKeyToPersonContainer, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> skipNotSkipCollection, List> locationContainers, Dictionary> idThenWholePercentagesToPersonContainers) + internal static List SetPersonCollectionsAndGetRecords(Configuration configuration, long ticks, ReadOnlyCollection personContainers, string eDistanceContentDirectory) { - string message; - int totalSeconds; - List nullablePersonKeyCollection = new(); + List results; List personKeyFormattedCollection = new(); Dictionary personKeyFormattedToNewestPersonKeyFormatted = new(); - Dictionary personKeyFormattedToPersonContainer = new(); - Dictionary> personKeyToPersonContainerCollection = new(); - List ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(eDistanceContentDirectory); - List personKeyFormattedIdThenWholePercentagesCollection = new(); - List<(PersonKeyFormattedIdThenWholePercentages, PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer = new(); - SetPersonCollections(configuration, personContainers, a2PeopleSingletonDirectory, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection, skipCollection, skipNotSkipCollection); - totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); - message = $") {ticksDirectories.Count:000} compile from and clean ticks Director(ies) - B - {totalSeconds} total second(s)"; - List records = DeleteEmptyDirectoriesAndGetCollection(configuration, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection, ticksDirectories, message); - locationContainers.AddRange(GetLocationContainers(maxDegreeOfParallelism, configuration, ticks, personContainers, eDistanceContentDirectory, records)); - int unableToMatchCount = SetCollectionsAndGetUnableToConvertCount(configuration, ticks, personKeyFormattedIdThenWholePercentagesCollection, records); - SetKeyValuePairsAndAddToCollections(configuration, personContainers, personKeyToPersonContainerCollection, personKeyFormattedToPersonContainer, personKeyFormattedIdThenWholePercentagesCollection, personKeyToPersonContainer, idThenWholePercentagesToPersonContainers, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); - totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); - message = $") {records.Count:000} message from ticks Director(ies) - D - {unableToMatchCount} Unable To Match Count / {records.Count} Collection - {totalSeconds} total second(s)"; - ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; - using (ProgressBar progressBar = new(records.Count, message, options)) - { - foreach (KeyValuePair> keyValuePair in idThenWholePercentagesToPersonContainers) - { - progressBar.Tick(); - foreach (KeyValuePair keyValue in keyValuePair.Value) - nullablePersonKeyCollection.AddRange(from l in keyValue.Value select l.Key); - } - } - long[] personKeyCollection = (from l in nullablePersonKeyCollection where l is not null select l.Value).Distinct().ToArray(); - PossiblyRebuildPersonContainers(configuration, a2PeopleSingletonDirectory, personKeyFormattedToNewestPersonKeyFormatted, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); - SetPersonKeyToPersonContainer(configuration, personContainers, personKeyCollection, personKeyToPersonContainer, personKeyToPersonContainerCollection); - notMappedPersonContainers.AddRange(GetNotMappedPersonContainers(configuration, ticks, personContainers, personKeyCollection)); + SetPersonCollections(configuration, personContainers, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection); + results = DeleteEmptyDirectoriesAndGetCollection(configuration, ticks, eDistanceContentDirectory, new(personKeyFormattedToNewestPersonKeyFormatted), new(personKeyFormattedCollection)); + return results; } private static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, long dateTimeOriginalThenMinimumDateTimeTicks, bool? isWrongYear) @@ -1365,4 +1463,169 @@ internal abstract class MapLogic return new(by, isByMapping, isBySorting); } + internal static void CheckCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string? rootDirectoryParent) + { + string json; + string fullPath; + List>? collection; + foreach (string propertyContentCollectionFile in propertyConfiguration.PropertyContentCollectionFiles) + { + fullPath = Path.GetFullPath(string.Concat(rootDirectoryParent, propertyContentCollectionFile)); + if (fullPath.Contains(propertyConfiguration.RootDirectory)) + continue; + if (!File.Exists(fullPath)) + continue; + json = File.ReadAllText(fullPath); + collection = JsonSerializer.Deserialize>>(json); + if (collection is null) + throw new NullReferenceException(nameof(collection)); + } + } + + internal static void LookForAbandoned(List distinctFilteredIds, string directory, string directoryName) + { + string fileNameWithoutExtension; + bool nameWithoutExtensionIsIdFormat; + List renameCollection = new(); + bool nameWithoutExtensionIsPaddedIdFormat; + int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex(); + 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) + continue; + if (distinctFilteredIdsValues.Contains(fileNameWithoutExtension)) + continue; + renameCollection.Add(file); + } + if (renameCollection.Count > 0) + { + if (directoryName.Length == 2) + IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[0]}abd{directoryName[^1]}"); + else if (directoryName.Length == 4) + IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[..2]}abd{directoryName[^2..]}"); + else + throw new NotSupportedException(); + } + } + + internal static void LookForAbandoned(string bResultsFullGroupDirectory, List distinctFilteredIds) + { + string[] directories = Directory.GetDirectories(bResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string directory in directories) + { + string? directoryName = Path.GetFileName(directory); + if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4)) + continue; + LookForAbandoned(distinctFilteredIds, directory, directoryName); + } + } + + internal static ReadOnlyDictionary> ConvertSkip(Dictionary> skipCollection) + { + Dictionary> results = new(); + List? wholePercentagesCollection; + foreach (KeyValuePair> keyValuePair in skipCollection) + { + if (!results.TryGetValue(keyValuePair.Key, out wholePercentagesCollection)) + { + results.Add(keyValuePair.Key, new()); + if (!results.TryGetValue(keyValuePair.Key, out wholePercentagesCollection)) + throw new Exception(); + } + foreach ((string _, int wholePercentage) in keyValuePair.Value) + wholePercentagesCollection.Add(wholePercentage); + } + return new(results); + } + + internal static ReadOnlyDictionary> ConvertSkipNotSkip(Dictionary> skipNotSkipCollection) + { + Dictionary> results = new(); + List? wholePercentagesCollection; + foreach (KeyValuePair> keyValuePair in skipNotSkipCollection) + { + if (!results.TryGetValue(keyValuePair.Key, out wholePercentagesCollection)) + { + results.Add(keyValuePair.Key, new()); + if (!results.TryGetValue(keyValuePair.Key, out wholePercentagesCollection)) + throw new Exception(); + } + foreach ((string _, int wholePercentage) in keyValuePair.Value) + wholePercentagesCollection.Add(wholePercentage); + } + return new(results); + } + + internal static ReadOnlyDictionary>> ConvertLocationContainers(List> locationContainers) + { + Dictionary>> results = new(); + foreach (LocationContainer locationContainer in locationContainers) + { + if (!results.ContainsKey(locationContainer.Id)) + results.Add(locationContainer.Id, new()); + results[locationContainer.Id].Add(locationContainer); + } + return new(results); + } + + internal static void MoveToDecade(Property.Models.Configuration propertyConfiguration, MappingFromItem mappingFromItem, MappingFromPerson mappingFromPerson) + { + string year; + DateTime dateTime; + FileInfo fileInfo; + string halfDecade; + string checkDirectory; + string? yearDirectory; + string yearDirectoryName; + string? personNameDirectory; + string personNameDirectoryName; + string? personKeyFormattedDirectory; + string? personKeyFormattedDirectoryName; + foreach (string locationContainersFile in mappingFromPerson.LocationContainersFiles) + { + fileInfo = new(locationContainersFile); + if (!fileInfo.Exists) + continue; + personNameDirectory = Path.GetDirectoryName(locationContainersFile); + if (string.IsNullOrEmpty(personNameDirectory)) + continue; + personNameDirectoryName = Path.GetFileName(personNameDirectory); + yearDirectory = Path.GetDirectoryName(personNameDirectory); + if (string.IsNullOrEmpty(yearDirectory)) + continue; + yearDirectoryName = Path.GetFileName(yearDirectory); + personKeyFormattedDirectory = Path.GetDirectoryName(yearDirectory); + if (string.IsNullOrEmpty(personKeyFormattedDirectory)) + continue; + personKeyFormattedDirectoryName = Path.GetFileName(personKeyFormattedDirectory); + if (personKeyFormattedDirectoryName.Length != propertyConfiguration.PersonBirthdayFormat.Length) + break; + if (mappingFromItem.DateTimeOriginal is null) + { + dateTime = mappingFromItem.MinimumDateTime; + year = mappingFromItem.MinimumDateTime.Year.ToString(); + halfDecade = year[3] > '4' ? $"#{year[..3]}+" : $"#{year[..3]}-"; + } + else + { + dateTime = mappingFromItem.DateTimeOriginal.Value; + year = mappingFromItem.DateTimeOriginal.Value.Year.ToString(); + halfDecade = year[3] > '4' ? $"^{year[..3]}+" : $"^{year[..3]}-"; + } + if (fileInfo.CreationTime != dateTime) + File.SetCreationTime(locationContainersFile, dateTime); + if (halfDecade == yearDirectoryName) + continue; + checkDirectory = Path.Combine(personKeyFormattedDirectory, halfDecade, personNameDirectoryName); + if (!Directory.Exists(checkDirectory)) + _ = Directory.CreateDirectory(checkDirectory); + File.Move(locationContainersFile, Path.Combine(checkDirectory, Path.Combine(checkDirectory, Path.GetFileName(locationContainersFile)))); + } + } + } \ No newline at end of file diff --git a/PhotoPrism/Models/_F_PhotoPrism.cs b/PhotoPrism/Models/_F_PhotoPrism.cs index c04bce5..1328c0d 100644 --- a/PhotoPrism/Models/_F_PhotoPrism.cs +++ b/PhotoPrism/Models/_F_PhotoPrism.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Drawing; using System.Text; using System.Text.Json; @@ -18,7 +19,7 @@ public class F_PhotoPrism { string json = File.ReadAllText(fileName); JsonElement[]? jsonElements = JsonSerializer.Deserialize(json); - if (jsonElements is null || !jsonElements.Any()) + if (jsonElements is null || jsonElements.Length == 0) results = Array.Empty(); else { @@ -37,7 +38,7 @@ public class F_PhotoPrism Marker[]? results; string file = Path.Combine(fPhotoPrismSingletonDirectory, "markers.json"); JsonProperty[] jsonProperties = GetJsonProperty(file); - if (!jsonProperties.Any()) + if (jsonProperties.Length == 0) results = null; else results = JsonSerializer.Deserialize(jsonProperties.Last().Value); @@ -79,7 +80,7 @@ public class F_PhotoPrism List? results; string file = Path.Combine(fPhotoPrismSingletonDirectory, "files.json"); JsonProperty[] jsonProperties = GetJsonProperty(file); - if (!jsonProperties.Any()) + if (jsonProperties.Length == 0) results = null; else { @@ -140,7 +141,7 @@ public class F_PhotoPrism return results; } - private static void PopulateSubjects(string mappingDefaultName, string personBirthdayFormat, List subjects, StringBuilder stringBuilder, PersonContainer[] personContainers, (MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, float Percent)[] sortedCollection) + private static void PopulateSubjects(string mappingDefaultName, string personBirthdayFormat, List subjects, StringBuilder stringBuilder, ReadOnlyCollection personContainers, (MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, float Percent)[] sortedCollection) { long? personKey; const int zero = 0; @@ -150,7 +151,7 @@ public class F_PhotoPrism { foreach (PersonContainer personContainer in personContainers) { - if (personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) + if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Birthdays.Length == 0) continue; if (IPerson.IsDefaultName(mappingDefaultName, personContainer.DisplayDirectoryName)) continue; @@ -181,11 +182,11 @@ public class F_PhotoPrism List subjects = new(); DateTime dateTime = new(ticks); int dlibLocationWholePercentages; - PersonContainer[]? personContainers; StringBuilder stringBuilder = new(); RectangleF? dlibPercentagesRectangle; + ReadOnlyCollection? personContainers; float rectangleIntersectMinimum = rectangleIntersectMinimums.Min(); - Dictionary? wholePercentagesToPersonContainers; + ReadOnlyDictionary>? wholePercentagesToPersonContainers; (MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, float Percent)[] sortedCollection; List<(MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, float Percent)> collection = new(); foreach (Face face in distinctFilteredFaces) @@ -220,12 +221,12 @@ public class F_PhotoPrism collection.Add(new(mappingFromPhotoPrism, marker, percent.Value)); } } - if (!collection.Any()) + if (collection.Count == 0) continue; sortedCollection = collection.OrderByDescending(l => l.Percent).ToArray(); PopulateSubjects(mappingDefaultName, personBirthdayFormat, subjects, stringBuilder, personContainers, sortedCollection); } - if (subjects.Any()) + if (subjects.Count > 0) { directory = Path.Combine(fPhotoPrismContentDirectory, dateTime.ToString("yyyy-MM-dd")); if (!Directory.Exists(directory)) diff --git a/Property/Models/Configuration.cs b/Property/Models/Configuration.cs index 3c119b0..6863d16 100644 --- a/Property/Models/Configuration.cs +++ b/Property/Models/Configuration.cs @@ -97,11 +97,11 @@ public class Configuration : Shared.Models.Properties.IPropertyConfiguration { if (propertyConfiguration is null) throw new NullReferenceException(nameof(propertyConfiguration)); - if (propertyConfiguration.IgnoreExtensions is null || !propertyConfiguration.IgnoreExtensions.Any()) + if (propertyConfiguration.IgnoreExtensions is null || propertyConfiguration.IgnoreExtensions.Length == 0) throw new NullReferenceException(nameof(propertyConfiguration.IgnoreExtensions)); if (propertyConfiguration.PropertyContentCollectionFiles is null) throw new NullReferenceException(nameof(propertyConfiguration.PropertyContentCollectionFiles)); - if (propertyConfiguration.ValidImageFormatExtensions is null || !propertyConfiguration.ValidImageFormatExtensions.Any()) + if (propertyConfiguration.ValidImageFormatExtensions is null || propertyConfiguration.ValidImageFormatExtensions.Length == 0) throw new NullReferenceException(nameof(propertyConfiguration.ValidImageFormatExtensions)); if (propertyConfiguration is null) throw new NullReferenceException(nameof(propertyConfiguration)); diff --git a/Set-Created-Date/SetCreatedDate.cs b/Set-Created-Date/SetCreatedDate.cs index 5f51511..c4b5ff4 100644 --- a/Set-Created-Date/SetCreatedDate.cs +++ b/Set-Created-Date/SetCreatedDate.cs @@ -45,7 +45,7 @@ public class SetCreatedDate Verify(); List lines = SetCreatedDateFilesInDirectories(log); File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines); - if (!lines.Any()) + if (lines.Count == 0) _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); } diff --git a/Shared/.kanbn/tasks/family-tree-as-markdown-files.md b/Shared/.kanbn/archive/family-tree-as-markdown-files.md similarity index 83% rename from Shared/.kanbn/tasks/family-tree-as-markdown-files.md rename to Shared/.kanbn/archive/family-tree-as-markdown-files.md index 6a431cf..2c5e31d 100644 --- a/Shared/.kanbn/tasks/family-tree-as-markdown-files.md +++ b/Shared/.kanbn/archive/family-tree-as-markdown-files.md @@ -1,10 +1,11 @@ --- -created: "2023-07-21T18:26:38.899Z" -updated: "2023-07-21T18:26:38.900Z" +created: 2023-07-21T18:26:38.899Z +updated: 2023-07-21T18:26:38.900Z assigned: "" progress: 0 -type: "kanbn" -completed: "2023-07-21T04:34:47.650Z" +type: kanbn +completed: 2023-07-21T04:34:47.650Z +column: Done --- # Family Tree as Markdown Files diff --git a/Shared/.kanbn/archive/run-scan-originals.md b/Shared/.kanbn/archive/run-scan-originals.md new file mode 100644 index 0000000..a4b6595 --- /dev/null +++ b/Shared/.kanbn/archive/run-scan-originals.md @@ -0,0 +1,15 @@ +--- +created: 2023-07-21T18:26:38.916Z +updated: 2023-07-21T18:26:38.917Z +assigned: "" +progress: 0 +status: 4-Done +type: kanbn +column: Done +--- + +# Run Scan Originals + +## Sub-tasks + +- [x] run-scan-originals diff --git a/Shared/.kanbn/index.md b/Shared/.kanbn/index.md index c72cc3b..a26816c 100644 --- a/Shared/.kanbn/index.md +++ b/Shared/.kanbn/index.md @@ -32,20 +32,21 @@ taskTemplate: '^+^_${overdue ? ''^R'' : ''''}${name}^: ${relations ? (''\n^-^/^g - [nef-support](tasks/nef-support.md) - [set-date-taken-when-missing](tasks/set-date-taken-when-missing.md) - [set-focus-person-based-on-number-of-matched](tasks/set-focus-person-based-on-number-of-matched.md) +- [move-images-in-distance-directories-to-decade-match-minimum-decade-match-maximum-decade-match-none](tasks/move-images-in-distance-directories-to-decade-match-minimum-decade-match-maximum-decade-match-none.md) ## In Progress +- [merge-kristy-files](tasks/merge-kristy-files.md) - [look-for-family-from-jlink-in-x-mapped](tasks/look-for-family-from-jlink-in-x-mapped.md) -- [review-what-system-does-when-duplicate-matched-with-x-and-non-x](tasks/review-what-system-does-when-duplicate-matched-with-x-and-non-x.md) -- [move-over-2023-california-pictures](tasks/move-over-2023-california-pictures.md) ## Done - [eof-error](tasks/eof-error.md) -- [run-scan-originals](tasks/run-scan-originals.md) - [shrink-percent](tasks/shrink-percent.md) -- [merge-kristy-files](tasks/merge-kristy-files.md) -- [family-tree-as-markdown-files](tasks/family-tree-as-markdown-files.md) +- [move-over-2023-california-pictures](tasks/move-over-2023-california-pictures.md) +- [verify-person-key-collection-fixed-x-issue](tasks/verify-person-key-collection-fixed-x-issue.md) - [genealogical-data-communication-as-golden](tasks/genealogical-data-communication-as-golden.md) +- [review-what-system-does-when-duplicate-matched-with-x-and-non-x](tasks/review-what-system-does-when-duplicate-matched-with-x-and-non-x.md) +- [add-facebook-and-linked-in-txt-to-ged](tasks/add-facebook-and-linked-in-txt-to-ged.md) - [setup-photo-prism-again-in-wsl-docker](tasks/setup-photo-prism-again-in-wsl-docker.md) - [rename-files-to-padded-number-string](tasks/rename-files-to-padded-number-string.md) diff --git a/Shared/.kanbn/tasks/add-facebook-and-linked-in-txt-to-ged.md b/Shared/.kanbn/tasks/add-facebook-and-linked-in-txt-to-ged.md new file mode 100644 index 0000000..72f635d --- /dev/null +++ b/Shared/.kanbn/tasks/add-facebook-and-linked-in-txt-to-ged.md @@ -0,0 +1,11 @@ +--- +created: 2023-08-05T17:50:34.233Z +updated: 2023-08-05T23:12:26.511Z +assigned: "" +progress: 0 +tags: [] +started: 2023-08-05T17:50:34.233Z +completed: 2023-08-05T23:12:26.511Z +--- + +# Add Facebook and LinkedIn *.txt to *.ged diff --git a/Shared/.kanbn/tasks/look-for-family-from-jlink-in-x-mapped.md b/Shared/.kanbn/tasks/look-for-family-from-jlink-in-x-mapped.md index f9465e8..3f2377a 100644 --- a/Shared/.kanbn/tasks/look-for-family-from-jlink-in-x-mapped.md +++ b/Shared/.kanbn/tasks/look-for-family-from-jlink-in-x-mapped.md @@ -1,6 +1,6 @@ --- created: 2023-07-31T19:08:57.684Z -updated: 2023-08-01T06:13:54.468Z +updated: 2023-08-06T03:40:58.576Z assigned: "" progress: 0 tags: [] diff --git a/Shared/.kanbn/tasks/merge-kristy-files.md b/Shared/.kanbn/tasks/merge-kristy-files.md index 70e046b..aaff237 100644 --- a/Shared/.kanbn/tasks/merge-kristy-files.md +++ b/Shared/.kanbn/tasks/merge-kristy-files.md @@ -1,12 +1,11 @@ --- created: 2023-07-21T18:26:38.910Z -updated: 2023-08-05T08:33:35.448Z +updated: 2023-08-05T17:43:51.430Z assigned: "" -progress: 0 -status: 2-Todo -type: kanbn -started: 2023-07-08T21:44:14.665Z -completed: 2023-08-05T08:33:35.448Z +progress: 0.5 +tags: [] +started: 2023-07-06T00:00:00.000Z +completed: 2023-08-03T00:00:00.000Z --- # Merge Kristy Files @@ -26,3 +25,4 @@ return new(result, (from l in results orderby l.FileHolder.DirectoryName?.EndsWi - [x] Set created date - [x] Verify - [x] Move to production ... +- [ ] Cleanup D:/7-Question/- Scans.* diff --git a/Shared/.kanbn/tasks/move-images-in-distance-directories-to-decade-match-minimum-decade-match-maximum-decade-match-none.md b/Shared/.kanbn/tasks/move-images-in-distance-directories-to-decade-match-minimum-decade-match-maximum-decade-match-none.md new file mode 100644 index 0000000..add4776 --- /dev/null +++ b/Shared/.kanbn/tasks/move-images-in-distance-directories-to-decade-match-minimum-decade-match-maximum-decade-match-none.md @@ -0,0 +1,9 @@ +--- +created: 2023-08-06T00:25:42.224Z +updated: 2023-08-06T00:25:42.220Z +assigned: "" +progress: 0 +tags: [] +--- + +# Move images in Distance directories to {Decade}MatchMinimum {Decade}MatchMaximum {Decade}MatchNone diff --git a/Shared/.kanbn/tasks/move-over-2023-california-pictures.md b/Shared/.kanbn/tasks/move-over-2023-california-pictures.md index c44b221..e1d19b9 100644 --- a/Shared/.kanbn/tasks/move-over-2023-california-pictures.md +++ b/Shared/.kanbn/tasks/move-over-2023-california-pictures.md @@ -1,10 +1,11 @@ --- created: 2023-08-05T08:33:59.693Z -updated: 2023-08-05T08:33:59.689Z +updated: 2023-08-05T17:38:11.824Z assigned: "" progress: 0 tags: [] started: 2023-08-05T08:33:59.693Z +completed: 2023-08-05T17:38:11.824Z --- # Move over 2023 California Pictures diff --git a/Shared/.kanbn/tasks/rename-files-to-padded-number-string.md b/Shared/.kanbn/tasks/rename-files-to-padded-number-string.md index 3056623..c610774 100644 --- a/Shared/.kanbn/tasks/rename-files-to-padded-number-string.md +++ b/Shared/.kanbn/tasks/rename-files-to-padded-number-string.md @@ -9,13 +9,14 @@ type: "kanbn" # Rename Files to Padded Number String +- [?] ~~Go Back to Index for Sort~~ +- [?] ~~New file for index to to id~~ +- [?] ~~Count backwards~~ +- [?] ~~Maybe skip some for scan images~~ +- [?] [Set Date Taken When Missing](set-date-taken-when-missing.md) + ## Sub-tasks -- [ ] ~~Go Back to Index for Sort~~ -- [ ] ~~New file for index to to id~~ -- [ ] ~~Count backwards~~ -- [ ] ~~Maybe skip some for scan images~~ -- [Set Date Taken When Missing](set-date-taken-when-missing.md) - [x] Rename production with padding names starting with one directory - [x] Need equivalent to NameWithoutExtensionIsIdFormat method - [x] Verify nothing broke (run from resize original now ... ?) diff --git a/Shared/.kanbn/tasks/review-what-system-does-when-duplicate-matched-with-x-and-non-x.md b/Shared/.kanbn/tasks/review-what-system-does-when-duplicate-matched-with-x-and-non-x.md index 1168da0..44d9099 100644 --- a/Shared/.kanbn/tasks/review-what-system-does-when-duplicate-matched-with-x-and-non-x.md +++ b/Shared/.kanbn/tasks/review-what-system-does-when-duplicate-matched-with-x-and-non-x.md @@ -1,10 +1,13 @@ --- created: 2023-08-05T08:33:05.117Z -updated: 2023-08-05T08:33:22.874Z +updated: 2023-08-06T05:44:59.047Z assigned: "" progress: 0 tags: [] -started: 2023-08-05T00:00:00.000Z +started: 2023-08-04T00:00:00.000Z +completed: 2023-08-06T05:44:59.047Z --- # Review what system does when duplicate matched with X] and non X] + +AlternateDirectoryDateTime helps but not full proof diff --git a/Shared/.kanbn/tasks/run-scan-originals.md b/Shared/.kanbn/tasks/run-scan-originals.md deleted file mode 100644 index 4a3c689..0000000 --- a/Shared/.kanbn/tasks/run-scan-originals.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -created: "2023-07-21T18:26:38.916Z" -updated: "2023-07-21T18:26:38.917Z" -assigned: "" -progress: 0 -status: "4-Done" -type: "kanbn" ---- - -# Run Scan Originals - -## Sub-tasks - -- [x] run-scan-originals diff --git a/Shared/.kanbn/tasks/verify-person-key-collection-fixed-x-issue.md b/Shared/.kanbn/tasks/verify-person-key-collection-fixed-x-issue.md new file mode 100644 index 0000000..a443385 --- /dev/null +++ b/Shared/.kanbn/tasks/verify-person-key-collection-fixed-x-issue.md @@ -0,0 +1,11 @@ +--- +created: 2023-08-06T01:04:57.884Z +updated: 2023-08-06T06:55:09.617Z +assigned: "" +progress: 0 +tags: [] +started: 2023-08-06T01:04:57.884Z +completed: 2023-08-06T06:55:09.617Z +--- + +# Verify personKeyCollection fixed X] issue diff --git a/Shared/Models/Mapping.cs b/Shared/Models/Mapping.cs index fdb705b..e9dc39c 100644 --- a/Shared/Models/Mapping.cs +++ b/Shared/Models/Mapping.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Text.Json; using System.Text.Json.Serialization; @@ -49,11 +50,11 @@ public class Mapping : Properties.IMapping _SegmentC = !saveIndividually ? null : sortingContainer.Sorting.DistancePermyriad.ToString(); } - public void UpdateMappingFromPerson(int? approximateYears, string displayDirectoryName, PersonBirthday personBirthday, string segmentB) + public void UpdateMappingFromPerson(ReadOnlyCollection locationContainersFiles, int? approximateYears, string displayDirectoryName, PersonBirthday personBirthday, string segmentB) { _SortingContainer = null; _By = Stateless.IMapLogic.Mapping; - _MappingFromPerson = new(approximateYears, displayDirectoryName, personBirthday, segmentB); + _MappingFromPerson = new(approximateYears, displayDirectoryName, locationContainersFiles, personBirthday, segmentB); } public void UpdateMappingFromPerson(int? approximateYears, string displayDirectoryName, PersonBirthday personBirthday, string segmentB, string segmentC, SortingContainer sortingContainer) @@ -61,7 +62,8 @@ public class Mapping : Properties.IMapping _SegmentC = segmentC; _By = Stateless.IMapLogic.Sorting; _SortingContainer = sortingContainer; - _MappingFromPerson = new(approximateYears, displayDirectoryName, personBirthday, segmentB); + ReadOnlyCollection locationContainersFiles = new(Array.Empty()); + _MappingFromPerson = new(approximateYears, displayDirectoryName, locationContainersFiles, personBirthday, segmentB); } } \ No newline at end of file diff --git a/Shared/Models/MappingFromPerson.cs b/Shared/Models/MappingFromPerson.cs index c466a1c..fd72d27 100644 --- a/Shared/Models/MappingFromPerson.cs +++ b/Shared/Models/MappingFromPerson.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Text.Json; using System.Text.Json.Serialization; @@ -8,14 +9,16 @@ public class MappingFromPerson : Properties.IMappingFromPerson public int? ApproximateYears { init; get; } public string DisplayDirectoryName { init; get; } + public ReadOnlyCollection LocationContainersFiles { init; get; } public PersonBirthday PersonBirthday { init; get; } public string SegmentB { init; get; } [JsonConstructor] - public MappingFromPerson(int? approximateYears, string displayDirectoryName, PersonBirthday personBirthday, string segmentB) + public MappingFromPerson(int? approximateYears, string displayDirectoryName, ReadOnlyCollection locationContainersFiles, PersonBirthday personBirthday, string segmentB) { ApproximateYears = approximateYears; DisplayDirectoryName = displayDirectoryName; + LocationContainersFiles = locationContainersFiles; PersonBirthday = personBirthday; SegmentB = segmentB; } diff --git a/Shared/Models/Methods/IMapLogic.cs b/Shared/Models/Methods/IMapLogic.cs index 93a33a2..ad192c9 100644 --- a/Shared/Models/Methods/IMapLogic.cs +++ b/Shared/Models/Methods/IMapLogic.cs @@ -1,8 +1,10 @@ +using System.Collections.ObjectModel; + namespace View_by_Distance.Shared.Models.Methods; public interface IMapLogic { - (bool, Dictionary?) GetWholePercentagesToPersonContainers(int id); + (bool, ReadOnlyDictionary>?) GetWholePercentagesToPersonContainers(int id); } \ No newline at end of file diff --git a/Shared/Models/Properties/IMapping.cs b/Shared/Models/Properties/IMapping.cs index 5093be5..05c351b 100644 --- a/Shared/Models/Properties/IMapping.cs +++ b/Shared/Models/Properties/IMapping.cs @@ -1,3 +1,5 @@ +using System.Collections.ObjectModel; + namespace View_by_Distance.Shared.Models.Properties; public interface IMapping diff --git a/Shared/Models/Properties/IMappingFromPerson.cs b/Shared/Models/Properties/IMappingFromPerson.cs index a3a3f06..4e9c718 100644 --- a/Shared/Models/Properties/IMappingFromPerson.cs +++ b/Shared/Models/Properties/IMappingFromPerson.cs @@ -1,3 +1,5 @@ +using System.Collections.ObjectModel; + namespace View_by_Distance.Shared.Models.Properties; public interface IMappingFromPerson @@ -5,6 +7,7 @@ public interface IMappingFromPerson public int? ApproximateYears { init; get; } public string DisplayDirectoryName { init; get; } + public ReadOnlyCollection LocationContainersFiles { init; get; } public PersonBirthday PersonBirthday { init; get; } public string SegmentB { init; get; } diff --git a/Shared/Models/Stateless/Methods/Container.cs b/Shared/Models/Stateless/Methods/Container.cs index 525cb07..299cb82 100644 --- a/Shared/Models/Stateless/Methods/Container.cs +++ b/Shared/Models/Stateless/Methods/Container.cs @@ -63,7 +63,7 @@ internal abstract class Container { foreach (Models.Container container in containers) { - if (!container.Items.Any()) + if (container.Items.Count == 0) continue; if (!argZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) continue; @@ -169,7 +169,7 @@ internal abstract class Container Dictionary> directoryToItems = new(); foreach (string[] files in filesCollection) { - if (!files.Any()) + if (files.Length == 0) continue; directory = Path.GetDirectoryName(files.First()); if (directory is null) @@ -199,7 +199,7 @@ internal abstract class Container } foreach (KeyValuePair> keyValuePair in directoryToItems) { - if (!keyValuePair.Value.Any()) + if (keyValuePair.Value.Count == 0) continue; container = new(keyValuePair.Key, keyValuePair.Value); results.Add(container); @@ -233,10 +233,10 @@ internal abstract class Container Models.Item[] filteredItems; foreach (Models.Container container in containers) { - if (!container.Items.Any()) + if (container.Items.Count == 0) continue; filteredItems = GetFilterItems(propertyConfiguration, container); - if (!filteredItems.Any()) + if (filteredItems.Length == 0) continue; foreach (Models.Item item in filteredItems) { @@ -257,7 +257,7 @@ internal abstract class Container IEnumerable filteredItems; foreach (Models.Container container in containers) { - if (!container.Items.Any()) + if (container.Items.Count == 0) continue; if (!filterItems) filteredItems = container.Items; diff --git a/Shared/Models/Stateless/Methods/Face.cs b/Shared/Models/Stateless/Methods/Face.cs index 149f669..e43f94b 100644 --- a/Shared/Models/Stateless/Methods/Face.cs +++ b/Shared/Models/Stateless/Methods/Face.cs @@ -56,7 +56,7 @@ internal abstract class Face { Models.Face? result; List results = GetFaces(jsonFileFullName, maximum: 1); - if (!results.Any()) + if (results.Count == 0) throw new Exception(); result = results[0]; return result; diff --git a/Shared/Models/Stateless/Methods/FaceFileSystem.cs b/Shared/Models/Stateless/Methods/FaceFileSystem.cs index f8c16e1..82d1dff 100644 --- a/Shared/Models/Stateless/Methods/FaceFileSystem.cs +++ b/Shared/Models/Stateless/Methods/FaceFileSystem.cs @@ -17,7 +17,7 @@ internal abstract class FaceFileSystem else { string[] files = Directory.GetFiles(parentDirectoryName, Path.GetFileName(fullFileName), SearchOption.AllDirectories); - if (!files.Any()) + if (files.Length == 0) throw new Exception($"File [{fileInfo.Name}] <{fullFileName}> doesn't exist (deep search)!"); else { diff --git a/Shared/Models/Stateless/Methods/FileHolder.cs b/Shared/Models/Stateless/Methods/FileHolder.cs index 99570a6..7bae4b7 100644 --- a/Shared/Models/Stateless/Methods/FileHolder.cs +++ b/Shared/Models/Stateless/Methods/FileHolder.cs @@ -30,7 +30,7 @@ internal abstract class FileHolder next = Directory.GetFiles(path, searchPattern); } catch { } - if (next is not null && next.Any()) + if (next is not null && next.Length > 0) yield return new(path, next); try { diff --git a/Shared/Models/Stateless/Methods/IPerson.cs b/Shared/Models/Stateless/Methods/IPerson.cs index 908af6d..f6b80e6 100644 --- a/Shared/Models/Stateless/Methods/IPerson.cs +++ b/Shared/Models/Stateless/Methods/IPerson.cs @@ -37,9 +37,9 @@ public interface IPerson hour == 17 ? "Dead-Male-No" : throw new NotImplementedException(personDisplayDirectoryName); - bool TestStatic_IsDefaultName(string mappingDefaultName, string value) => - IsDefaultName(mappingDefaultName, value); - static bool IsDefaultName(string mappingDefaultName, string value) => - value == mappingDefaultName || (value.Length > 1 && value[0] == 'X' && value[1] == ']'); + bool TestStatic_IsDefaultName(string mappingDefaultName, string personDisplayDirectoryName) => + IsDefaultName(mappingDefaultName, personDisplayDirectoryName); + static bool IsDefaultName(string mappingDefaultName, string personDisplayDirectoryName) => + personDisplayDirectoryName == mappingDefaultName || (personDisplayDirectoryName.Length > 1 && personDisplayDirectoryName[0] == 'X' && personDisplayDirectoryName[1] == ']'); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/PersonContainer.cs b/Shared/Models/Stateless/Methods/PersonContainer.cs index aa347e8..15c8a30 100644 --- a/Shared/Models/Stateless/Methods/PersonContainer.cs +++ b/Shared/Models/Stateless/Methods/PersonContainer.cs @@ -103,7 +103,7 @@ internal abstract class PersonContainer 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(); - if (!orderedPersonBirthdays.Any()) + if (orderedPersonBirthdays.Length == 0) personKey = collection[zero].PersonBirthday.Value.Ticks; else { @@ -113,7 +113,7 @@ internal abstract class PersonContainer } personKeyDirectory = Path.Combine(personDisplayDirectory, personKeyFormatted); files = Directory.GetFiles(personKeyDirectory, "*", SearchOption.AllDirectories); - if (!files.Any()) + if (files.Length == 0) continue; personDisplayDirectoryAllFiles.AddRange(files.Where(l => l.EndsWith(".rel"))); personContainer = new(approximateYears, orderedPersonBirthdays, personDisplayDirectoryAllFiles.ToArray(), personDisplayDirectoryName, personKey, personDirectory); @@ -127,7 +127,7 @@ internal abstract class PersonContainer string? result; if (approximateYears is null) throw new NotSupportedException(); - if (!collection.Any()) + if (collection.Count == 0) throw new NotSupportedException(); const int zero = 0; int? updateApproximateYears; @@ -225,7 +225,7 @@ internal abstract class PersonContainer { innerGroupDirectoryName = Path.GetFileName(innerGroupDirectory); segments = innerGroupDirectoryName.Split('-'); - if (!segments.Any()) + if (segments.Length == 0) throw new NotSupportedException("Misplaced directory!"); if (segments.Length != 3) continue; @@ -285,7 +285,7 @@ internal abstract class PersonContainer _ = Directory.CreateDirectory(a2PeopleSingletonDirectoryChar); } string[] groupDirectories = Directory.GetDirectories(a2PeopleSingletonDirectory, "*", SearchOption.TopDirectoryOnly); - if (!groupDirectories.Any()) + if (groupDirectories.Length == 0) results = new(); else results = GetPersonContainersGroups(personBirthdayFormat, facesFileNameExtension, personCharacters, groupDirectories); diff --git a/Shared/Models/Stateless/Methods/Property.cs b/Shared/Models/Stateless/Methods/Property.cs index 85b8868..fdb0f31 100644 --- a/Shared/Models/Stateless/Methods/Property.cs +++ b/Shared/Models/Stateless/Methods/Property.cs @@ -40,10 +40,10 @@ internal abstract class Property || (l.Length == 7 && l.Substring(1, 4) == year && l[5] == '.') select l ).ToArray(); - if (!results.Any()) + if (results.Length == 0) result = null; else - result = !matches.Any(); + result = matches.Length == 0; return new(result, results); } @@ -203,7 +203,7 @@ internal abstract class Property } long threeStandardDeviationHigh; long min; - if (!ticksCollection.Any()) + if (ticksCollection.Count == 0) min = 0; else min = ticksCollection.Min(); @@ -263,7 +263,7 @@ internal abstract class Property bool result = false; foreach (Models.Container container in containers) { - if (!container.Items.Any()) + if (container.Items.Count == 0) continue; if ((from l in container.Items where l.Any() select true).Any()) { diff --git a/Shared/Models/Stateless/Methods/XDirectory.cs b/Shared/Models/Stateless/Methods/XDirectory.cs index b7fee50..69d6a31 100644 --- a/Shared/Models/Stateless/Methods/XDirectory.cs +++ b/Shared/Models/Stateless/Methods/XDirectory.cs @@ -97,7 +97,7 @@ internal abstract partial class XDirectory } } } - if (renameCollection.Any()) + if (renameCollection.Count > 0) IDirectory.MoveFiles(renameCollection, "{}", "{abd}"); return renameCollection.Count; } @@ -139,7 +139,7 @@ internal abstract partial class XDirectory continue; matches.Add(possible); } - if (matches.Count == 1 || (matches.Any() && lengths.Distinct().Count() == 1 && creationTimes.Distinct().Count() == 1)) + if (matches.Count == 1 || (matches.Count > 0 && lengths.Distinct().Count() == 1 && creationTimes.Distinct().Count() == 1)) result = matches.First(); return result; } @@ -167,7 +167,7 @@ internal abstract partial class XDirectory results.Add(new(file, uniqueFileName, isNotUniqueAndNeedsReview, new(), null)); else { - if (!collection.Any()) + if (collection.Count == 0) results.Add(new(file, uniqueFileName, isNotUniqueAndNeedsReview, collection, null)); else if (uniqueFileName && collection.Count == 1) results.Add(new(file, uniqueFileName, isNotUniqueAndNeedsReview, collection, collection.First())); diff --git a/Shared/Models/Stateless/Methods/XPath.cs b/Shared/Models/Stateless/Methods/XPath.cs index 170a5c8..a5aead1 100644 --- a/Shared/Models/Stateless/Methods/XPath.cs +++ b/Shared/Models/Stateless/Methods/XPath.cs @@ -32,7 +32,7 @@ internal abstract class XPath bool result; List results = new(); DeleteEmptyDirectories(rootDirectory, results); - result = results.Any(); + result = results.Count > 0; return result; } @@ -64,7 +64,7 @@ internal abstract class XPath { DeleteEmptyDirectories(directory, check); deletedDirectories.AddRange(check); - if (check.Any()) + if (check.Count > 0) DeleteEmptyDirectories(directory, deletedDirectories); } }