diff --git a/Distance/Models/_E_Distance.cs b/Distance/Models/_E_Distance.cs index 82bc0fd..6d76b83 100644 --- a/Distance/Models/_E_Distance.cs +++ b/Distance/Models/_E_Distance.cs @@ -324,7 +324,7 @@ public partial class E_Distance : IDistance _DuplicateMappedFaceFiles.Clear(); } - public static void SaveFaceDistances(Property.Models.Configuration configuration, SortingContainer[] sortingContainers) + public static void SaveFaceDistances(Property.Models.Configuration configuration, ReadOnlyCollection sortingContainers) { string eDistanceContentCollectionDirectory = IResult.GetResultsDateGroupDirectory(configuration, nameof(E_Distance), "([])"); if (!Directory.Exists(eDistanceContentCollectionDirectory)) @@ -341,9 +341,13 @@ public partial class E_Distance : IDistance List faces = new(); foreach (Face face in distinctFilteredFaces) { - if (face.Mapping?.MappingFromFilter is null) + if (face.Mapping?.MappingFromFilterPre is null) throw new NotSupportedException(); - if (face.Mapping.MappingFromFilter.IsUsed is not null && face.Mapping.MappingFromFilter.IsUsed.Value && face.Mapping.MappingFromFilter.IsFocusPerson is not null && !face.Mapping.MappingFromFilter.IsFocusPerson.Value) + if (face.Mapping.MappingFromFilterPre.InSkipCollection is not null && face.Mapping.MappingFromFilterPre.InSkipCollection.Value) + continue; + if (face.Mapping.MappingFromFilterPre.IsFocusModel is not null && !face.Mapping.MappingFromFilterPre.IsFocusModel.Value) + continue; + if (face.Mapping.MappingFromFilterPre.IsFocusRelativePath is not null && !face.Mapping.MappingFromFilterPre.IsFocusRelativePath.Value) continue; if (face.FaceEncoding is not null && face.FaceDistance?.Encoding is not null && face.FaceDistance.Encoding is FaceRecognitionDotNet.FaceEncoding _) continue; @@ -390,7 +394,7 @@ public partial class E_Distance : IDistance distance += 1; continue; } - sortingContainer = new(face.Mapping, sorting); + sortingContainer = new(sorting, face.Mapping); results.Add(sortingContainer); if (results.Count >= distanceLimits.SortingMaximumPerFaceShouldBeHigh) break; @@ -399,11 +403,11 @@ public partial class E_Distance : IDistance return results; } - private static List GetSortingCollection(Map.Models.MapLogic mapLogic, ReadOnlyCollection faceDistanceEncodings, int i, FaceDistance faceDistanceEncoding, Face face) + private static List GetSortingCollection(Map.Models.MapLogic mapLogic, ReadOnlyCollection faceDistanceEncodings, int i, Face face, FaceDistance faceDistanceEncoding) { List results; List faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding); - results = mapLogic.GetSortingCollection(i, faceDistanceEncoding, face, faceDistanceLengths); + results = mapLogic.GetSortingCollection(i, face, faceDistanceEncoding, faceDistanceLengths); return results; } @@ -427,7 +431,7 @@ public partial class E_Distance : IDistance return results; } - public static FaceDistanceContainer[] FilteredFaceDistanceContainers(Map.Models.MapLogic mapLogic, ReadOnlyCollection faceDistanceContainers, long? skipOlderThan, DistanceLimits distanceLimits) + public static FaceDistanceContainer[] FilteredPostLoadFaceDistanceContainers(Map.Models.MapLogic mapLogic, ReadOnlyCollection faceDistanceContainers, long? skipOlderThan, DistanceLimits distanceLimits) { List results = new(); foreach (FaceDistanceContainer faceDistanceContainer in faceDistanceContainers) @@ -440,23 +444,24 @@ public partial class E_Distance : IDistance continue; if (faceDistanceContainer.Face.Mapping.MappingFromLocation.AreaPermyriad < distanceLimits.FaceAreaPermyriad) continue; - if (faceDistanceContainer.Face.Mapping.MappingFromFilter.IsUsed is not null && faceDistanceContainer.Face.Mapping.MappingFromFilter.IsUsed.Value) + if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.InSkipCollection is not null && faceDistanceContainer.Face.Mapping.MappingFromFilterPre.InSkipCollection.Value) + throw new NotSupportedException(nameof(PreFilterSetFaceDistances)); + if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusModel is not null && faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusModel.Value) + throw new NotSupportedException(nameof(PreFilterSetFaceDistances)); + if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath is not null && faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath.Value) + throw new NotSupportedException(nameof(PreFilterSetFaceDistances)); + if (faceDistanceContainer.Face.Mapping.MappingFromFilterPost.InSkipCollection is not null && faceDistanceContainer.Face.Mapping.MappingFromFilterPost.InSkipCollection.Value) continue; - if (faceDistanceContainer.Face.Mapping.MappingFromFilter.IsFocusPerson is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilter.IsFocusPerson.Value) - continue; - if (faceDistanceContainer.Face.Mapping.MappingFromFilter.IsFocusModel is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilter.IsFocusModel.Value) - continue; - if (faceDistanceContainer.Face.Mapping.MappingFromFilter.IsFocusRelativePath is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilter.IsFocusRelativePath.Value) + if (faceDistanceContainer.Face.Mapping.MappingFromFilterPost.IsFocusPerson is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilterPost.IsFocusPerson.Value) continue; results.Add(faceDistanceContainer); } return results.ToArray(); } - public static SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Map.Models.Configuration mapConfiguration, long ticks, Map.Models.MapLogic mapLogic, IDistanceLimits distanceLimits, ReadOnlyCollection faceDistanceEncodings, FaceDistanceContainer[] filteredFaceDistanceContainers) + public static ReadOnlyCollection SetFaceMappingSortingCollectionThenGetSortedSortingContainers(int maxDegreeOfParallelism, Map.Models.Configuration mapConfiguration, long ticks, Map.Models.MapLogic mapLogic, IDistanceLimits distanceLimits, ReadOnlyCollection faceDistanceEncodings, FaceDistanceContainer[] filteredFaceDistanceContainers) { - SortingContainer[] results; - List collection = new(); + List results = new(); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; string message = $") {filteredFaceDistanceContainers.Length:000} Get Sorting Containers Then Set Face Mapping Sorting Collection - {totalSeconds} total second(s)"; @@ -465,28 +470,23 @@ public partial class E_Distance : IDistance _ = Parallel.For(0, filteredFaceDistanceContainers.Length, parallelOptions, (i, state) => { progressBar.Tick(); - FaceDistance faceDistanceEncoding = filteredFaceDistanceContainers[i].FaceDistance; Face face = filteredFaceDistanceContainers[i].Face; - List sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, i, faceDistanceEncoding, face); + FaceDistance faceDistanceEncoding = filteredFaceDistanceContainers[i].FaceDistance; + List sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, i, face, faceDistanceEncoding); if (sortingCollection.Count == 0) return; List sortingContainers = GetSortingContainers(mapConfiguration, distanceLimits, face, faceDistanceEncoding, sortingCollection); if (sortingContainers.Count > 0) { - lock (collection) - collection.AddRange(sortingContainers); + lock (results) + results.AddRange(sortingContainers); } }); - if (collection.Count == 0) - results = Array.Empty(); + if (distanceLimits is not null && distanceLimits.RangeDaysDeltaTargetLessThenUpper) + results = Shared.Models.Stateless.Methods.ISortingContainer.Sort(results); else - { - if (distanceLimits.RangeDaysDeltaTargetLessThenUpper) - results = Shared.Models.Stateless.Methods.ISortingContainer.Sort(collection); - else - results = Shared.Models.Stateless.Methods.ISortingContainer.SortUsingDaysDelta(collection); - } - return results; + results = Shared.Models.Stateless.Methods.ISortingContainer.SortUsingDaysDelta(results); + return new(results); } private static void WriteVsCodeFiles(string eDistanceContentDirectory, string? displayDirectoryName, string directory) diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index d69fdbb..e7266b7 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -338,7 +338,7 @@ public partial class DlibDotNet } _Distance.Clear(); ReadOnlyCollection distinctFilteredFaces = Map.Models.Stateless.Methods.IMapLogic.GetFaces(distinctFilteredItems); - ReadOnlyCollection distinctFilteredMappingCollection = SetCreationTimeAndGetMappings(_Configuration.PropertyConfiguration, eDistanceContentDirectory, containers, mapLogic, distinctItems: true); + ReadOnlyCollection distinctFilteredMappingCollection = GetMappings(_Configuration.PropertyConfiguration, eDistanceContentDirectory, containers, mapLogic, distinctItems: true); if (runToDoCollectionFirst) { string json = JsonSerializer.Serialize(distinctFilteredMappingCollection); @@ -556,7 +556,7 @@ public partial class DlibDotNet } } - private ReadOnlyCollection SetCreationTimeAndGetMappings(Property.Models.Configuration propertyConfiguration, string eDistanceContentDirectory, Container[] containers, MapLogic mapLogic, bool distinctItems) + private ReadOnlyCollection GetMappings(Property.Models.Configuration propertyConfiguration, string eDistanceContentDirectory, Container[] containers, MapLogic mapLogic, bool distinctItems) { ReadOnlyCollection results; int count = 0; @@ -570,7 +570,6 @@ public partial class DlibDotNet IEnumerable filteredItems; MappingFromItem mappingFromItem; List mappingCollection = new(); - ReadOnlyCollection? locationContainersFiles = null; foreach (Container container in containers) { if (container.Items.Count == 0) @@ -600,15 +599,10 @@ public partial class DlibDotNet continue; anyValidFaces = true; mappingCollection.Add(face.Mapping); - if (face.Mapping.MappingFromPerson is null || face.Mapping.MappingFromPerson.LocationContainersFiles.Count == 0) - continue; - Map.Models.Stateless.Methods.IMapLogic.SetCreationTime(face.Mapping.MappingFromItem, face.Mapping.MappingFromPerson); - if (_Configuration.MoveToDecade && _Configuration.LocationContainerDistanceTolerance is null) - Map.Models.Stateless.Methods.IMapLogic.MoveToDecade(propertyConfiguration, face.Mapping.MappingFromItem, face.Mapping.MappingFromPerson); } if (!anyValidFaces) { - (mapping, notMapped) = GetMapping(mapLogic, locationContainersFiles, item, isFocusRelativePath, mappingFromItem); + (mapping, notMapped) = GetMappingAndUpdateMappingFromPerson(mapLogic, item, isFocusRelativePath, mappingFromItem); mappingCollection.Add(mapping); } } @@ -728,7 +722,7 @@ public partial class DlibDotNet if (_Configuration.SaveMappedForOutputResolutions.Contains(outputResolution)) mapLogic.SaveMapped(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, personKeyToIds, distinctFilteredMappingCollection, idToWholePercentagesToMapping); if (_Configuration.SaveFaceDistancesForOutputResolutions.Contains(outputResolution)) - SaveFaceDistances(ticks, mapLogic, distinctFilteredFaces, distinctFilteredMappingCollection, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, idToWholePercentagesToMapping); + SaveFaceDistances(ticks, mapLogic, distinctFilteredFaces, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, idToWholePercentagesToMapping); } private bool? GetIsFocusModel(Shared.Models.Property? property) @@ -776,12 +770,11 @@ public partial class DlibDotNet return result; } - private int GetNotMappedCountAndSetMapping(MapLogic mapLogic, Item item, bool? isFocusRelativePath, ReadOnlyCollection> locationContainers, MappingFromItem mappingFromItem, List? mappingFromPhotoPrismCollection, List faces) + private int GetNotMappedCountAndUpdateMappingFromPersonThenSetMapping(MapLogic mapLogic, Item item, bool? isFocusRelativePath, ReadOnlyCollection> locationContainers, MappingFromItem mappingFromItem, List? mappingFromPhotoPrismCollection, List faces) { int result; double? α; int? eyeα; - bool? isUsed; bool? canReMap; bool? eyeReview; Mapping mapping; @@ -792,12 +785,10 @@ public partial class DlibDotNet bool? inSkipCollection; int wholePercentRectangle; string deterministicHashCodeKey; - MappingFromFilter mappingFromFilter; MappingFromLocation? mappingFromLocation; MappingFromFilterPre mappingFromFilterPre; MappingFromFilterPost mappingFromFilterPost; bool? isFocusModel = GetIsFocusModel(item.Property); - bool ignoreXMatches = _JLinkResolvedDirectories.Count > 0; long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray(); ReadOnlyDictionary>? wholePercentagesToPersonContainers; ReadOnlyCollection locationContainersFiles = new((from l in locationContainers select l.File).ToArray()); @@ -807,13 +798,11 @@ public partial class DlibDotNet if (item.Property?.Id is null || face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) { canReMap = null; - isUsed = null; isFocusPerson = null; inSkipCollection = null; mappingFromLocation = null; mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath); - mappingFromFilter = new(isFocusModel, isFocusPerson, isFocusRelativePath, inSkipCollection, isUsed); } else { @@ -832,14 +821,11 @@ public partial class DlibDotNet inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation); mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath); canReMap = Map.Models.Stateless.Methods.IMapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); - isUsed = mapLogic.IsUsed(ignoreXMatches, item.Property.Id.Value, wholePercentagesToPersonContainers, mappingFromLocation); - isFocusPerson = mapLogic.IsFocusPersonOld(_Configuration.SkipPersonWithMoreThen, _JLinkResolvedDirectories, wholePercentagesToPersonContainers, mappingFromLocation); - mappingFromFilter = new(isFocusModel, isFocusPerson, isFocusRelativePath, inSkipCollection, isUsed); isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); } - mapping = new(mappingFromFilter, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection); - notMapped += mapLogic.UpdateMappingFromPerson(locationContainersFiles, wholePercentagesToPersonContainers, mapping); + mapping = new(mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection); + notMapped += mapLogic.UpdateMappingFromPerson(wholePercentagesToPersonContainers, mapping); face.SetMapping(mapping); } result = notMapped; @@ -862,6 +848,8 @@ public partial class DlibDotNet configuration.PersonCharacters.ToArray(), configuration.RangeDaysDeltaTolerance, configuration.RangeDistanceTolerance, + configuration.ReMap, + configuration.SaveIndividually, configuration.SaveSortingWithoutPerson, configuration.SkipNotSkipDirectories, configuration.SortingMaximumPerKey, @@ -872,10 +860,9 @@ public partial class DlibDotNet return result; } - private (Mapping, int) GetMapping(MapLogic mapLogic, ReadOnlyCollection? locationContainersFiles, Item item, bool? isFocusRelativePath, MappingFromItem mappingFromItem) + private (Mapping, int) GetMappingAndUpdateMappingFromPerson(MapLogic mapLogic, Item item, bool? isFocusRelativePath, MappingFromItem mappingFromItem) { Mapping result; - bool? isUsed; bool? canReMap; int? eyeα = null; bool? isFocusPerson; @@ -885,24 +872,20 @@ public partial class DlibDotNet int faceAreaPermyriad = 0; int wholePercentRectangle; string deterministicHashCodeKey; - MappingFromFilter mappingFromFilter; MappingFromLocation? mappingFromLocation; MappingFromFilterPre mappingFromFilterPre; MappingFromFilterPost mappingFromFilterPost; bool? isFocusModel = GetIsFocusModel(item.Property); - bool ignoreXMatches = _JLinkResolvedDirectories.Count > 0; long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray(); ReadOnlyDictionary>? wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(item.Property?.Id); if (item.Property?.Id is null) { - isUsed = null; canReMap = null; isFocusPerson = null; inSkipCollection = null; mappingFromLocation = null; mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath); - mappingFromFilter = new(isFocusModel, isFocusPerson, isFocusRelativePath, inSkipCollection, isUsed); } else { @@ -912,14 +895,11 @@ public partial class DlibDotNet inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation); mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath); canReMap = Map.Models.Stateless.Methods.IMapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); - isUsed = mapLogic.IsUsed(ignoreXMatches, item.Property.Id.Value, wholePercentagesToPersonContainers, mappingFromLocation); - isFocusPerson = mapLogic.IsFocusPersonOld(_Configuration.SkipPersonWithMoreThen, _JLinkResolvedDirectories, wholePercentagesToPersonContainers, mappingFromLocation); - mappingFromFilter = new(isFocusModel, isFocusPerson, isFocusRelativePath, inSkipCollection, isUsed); isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); } - result = new(mappingFromFilter, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection: null); - int notMapped = mapLogic.UpdateMappingFromPerson(locationContainersFiles, wholePercentagesToPersonContainers, result); + result = new(mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection: null); + int notMapped = mapLogic.UpdateMappingFromPerson(wholePercentagesToPersonContainers, result); return (result, notMapped); } @@ -998,6 +978,7 @@ public partial class DlibDotNet throw new NullReferenceException(nameof(property)); item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder); MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); + Map.Models.Stateless.Methods.IMapLogic.SetCreationTimeMaybeMoveToDecade(_Configuration.PropertyConfiguration, _Configuration.MoveToDecade && _Configuration.LocationContainerDistanceTolerance is null, mappingFromItem, locationContainers); (int metadataGroups, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, changesFrom, mappingFromItem); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection)); @@ -1022,7 +1003,7 @@ public partial class DlibDotNet faces = _Faces.GetFaces(outputResolution, dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, locationContainers, mappingFromPhotoPrismCollection); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.GetFaces)); - result = GetNotMappedCountAndSetMapping(mapLogic, item, isFocusRelativePath, locationContainers, mappingFromItem, mappingFromPhotoPrismCollection, faces); + result = GetNotMappedCountAndUpdateMappingFromPersonThenSetMapping(mapLogic, item, isFocusRelativePath, locationContainers, mappingFromItem, mappingFromPhotoPrismCollection, faces); List<(Shared.Models.Face, FileInfo?, string, bool Saved)> faceCollection = _Faces.SaveFaces(_FaceParts.FileNameExtension, dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, faces); if (_Configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) _FaceParts.CopyFacesAndSaveFaceLandmarkImage(facePartsCollectionDirectory, mappingFromItem, faceCollection); @@ -1069,7 +1050,6 @@ public partial class DlibDotNet throw new NullReferenceException(nameof(_Log)); int result = 0; int exceptionsCount = 0; - bool ignoreXMatches = _JLinkResolvedDirectories.Count > 0; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; DateTime[] containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems); ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; @@ -1164,49 +1144,53 @@ public partial class DlibDotNet return new(cResultsFullGroupDirectory, c2ResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory); } - private void SaveFaceDistances(long ticks, MapLogic mapLogic, ReadOnlyCollection mappingCollection, string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyDictionary> idToWholePercentagesToMapping, ReadOnlyCollection faceDistanceEncodings, ReadOnlyCollection faceDistanceContainers) + private void SaveFaceDistances(long ticks, MapLogic mapLogic, string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyDictionary> idToWholePercentagesToMapping, ReadOnlyCollection faceDistanceEncodings, ReadOnlyCollection faceDistanceContainers) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); int? useFiltersCounter = null; DistanceLimits distanceLimits; - SortingContainer[] sortingContainers; + ReadOnlyCollection sortingContainers; FaceDistanceContainer[] filteredFaceDistanceContainers; long? skipOlderThan = _Configuration.SkipOlderThanDays is null ? null : new DateTime(ticks).AddDays(-_Configuration.SkipOlderThanDays.Value).Ticks; distanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaPermyriadTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh); - filteredFaceDistanceContainers = E_Distance.FilteredFaceDistanceContainers(mapLogic, faceDistanceContainers, skipOlderThan, distanceLimits); + filteredFaceDistanceContainers = E_Distance.FilteredPostLoadFaceDistanceContainers(mapLogic, faceDistanceContainers, skipOlderThan, distanceLimits); if (filteredFaceDistanceContainers.Length == 0) _Log.Information("All images have been filtered!"); else { - sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distanceLimits, faceDistanceEncodings, filteredFaceDistanceContainers); - if (sortingContainers.Length == 0) + sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortedSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distanceLimits, faceDistanceEncodings, filteredFaceDistanceContainers); + if (sortingContainers.Count == 0) { for (useFiltersCounter = 1; useFiltersCounter < _Configuration.UseFilterTries; useFiltersCounter++) { distanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaPermyriadTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh, useFiltersCounter); - filteredFaceDistanceContainers = E_Distance.FilteredFaceDistanceContainers(mapLogic, faceDistanceContainers, skipOlderThan, distanceLimits); + filteredFaceDistanceContainers = E_Distance.FilteredPostLoadFaceDistanceContainers(mapLogic, faceDistanceContainers, skipOlderThan, distanceLimits); if (filteredFaceDistanceContainers.Length == 0) _Log.Information("All images have been filtered!"); else { - sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distanceLimits, faceDistanceEncodings, filteredFaceDistanceContainers); - if (sortingContainers.Length == 0) + sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortedSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distanceLimits, faceDistanceEncodings, filteredFaceDistanceContainers); + if (sortingContainers.Count == 0) break; } } } - E_Distance.SaveFaceDistances(_Configuration.PropertyConfiguration, sortingContainers); + sortingContainers = mapLogic.GetFilterSortingContainers(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, idToWholePercentagesToMapping, distanceLimits, sortingContainers); + if (sortingContainers.Count > 0) + E_Distance.SaveFaceDistances(_Configuration.PropertyConfiguration, sortingContainers); if (filteredFaceDistanceContainers.Length > 0) { - int updated = sortingContainers.Length == 0 ? 0 : mapLogic.UpdateFromSortingContainers(_Configuration.SaveIndividually, idToWholePercentagesToMapping, distanceLimits, sortingContainers); - List saveContainers = mapLogic.GetSaveContainers(_Configuration.SaveIndividually, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, mappingCollection, idToWholePercentagesToMapping, useFiltersCounter, sortingContainers.Length > 0); - mapLogic.SaveContainers(_Configuration.SaveIndividually, updated, saveContainers); + int updated = sortingContainers.Count == 0 ? 0 : mapLogic.UpdateFromSortingContainers(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, idToWholePercentagesToMapping, sortingContainers); + List saveContainers; + saveContainers = mapLogic.GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, idToWholePercentagesToMapping, distanceLimits, useFiltersCounter, sortingContainers); + if (saveContainers.Count > 0) + mapLogic.SaveContainers(updated, saveContainers); } } } - private void SaveFaceDistances(long ticks, MapLogic mapLogic, ReadOnlyCollection distinctFilteredFaces, ReadOnlyCollection mappingCollection, string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyDictionary> idToWholePercentagesToMapping) + private void SaveFaceDistances(long ticks, MapLogic mapLogic, ReadOnlyCollection distinctFilteredFaces, string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyDictionary> idToWholePercentagesToMapping) { E_Distance.PreFilterSetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, distinctFilteredFaces); ReadOnlyCollection faceDistanceContainers = E_Distance.GetFaceDistanceContainers(distinctFilteredFaces); @@ -1219,7 +1203,7 @@ public partial class DlibDotNet continue; faceDistanceEncodings.Add(faceDistanceContainer.FaceDistance); } - SaveFaceDistances(ticks, mapLogic, mappingCollection, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, idToWholePercentagesToMapping, new(faceDistanceEncodings), faceDistanceContainers); + SaveFaceDistances(ticks, mapLogic, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, idToWholePercentagesToMapping, new(faceDistanceEncodings), faceDistanceContainers); } } diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index f097109..077016c 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -66,6 +66,7 @@ public class Configuration public float[]? RangeFaceAreaTolerance { get; set; } public float[]? RangeFaceConfidence { get; set; } public float[]? RectangleIntersectMinimums { get; set; } + public bool? ReMap { get; set; } public bool? Reverse { get; set; } public string[]? SaveBlurHashForOutputResolutions { get; set; } public string[]? SaveFaceDistancesForOutputResolutions { get; set; } @@ -163,6 +164,7 @@ public class Configuration // if (configuration?.RangeFaceAreaTolerance is null) throw new NullReferenceException(nameof(configuration.RangeFaceAreaTolerance)); // if (configuration?.RangeFaceConfidence is null) throw new NullReferenceException(nameof(configuration.RangeFaceConfidence)); // if (configuration?.RectangleIntersectMinimums is null) throw new NullReferenceException(nameof(configuration.RectangleIntersectMinimums)); + if (configuration?.ReMap is null) throw new NullReferenceException(nameof(configuration.ReMap)); if (configuration?.Reverse is null) throw new NullReferenceException(nameof(configuration.Reverse)); // if (configuration?.SaveBlurHashForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveBlurHashForOutputResolutions)); // if (configuration?.SaveFaceDistancesForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFaceDistancesForOutputResolutions)); @@ -247,6 +249,7 @@ public class Configuration configuration.RangeFaceAreaTolerance ?? Array.Empty(), configuration.RangeFaceConfidence ?? Array.Empty(), configuration.RectangleIntersectMinimums ?? Array.Empty(), + configuration.ReMap.Value, configuration.Reverse.Value, configuration.SaveBlurHashForOutputResolutions ?? Array.Empty(), configuration.SaveFaceDistancesForOutputResolutions ?? Array.Empty(), diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index c4747b1..f71d159 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -60,6 +60,7 @@ public record Configuration(Property.Models.Configuration PropertyConfiguration, float[] RangeFaceAreaPermyriadTolerance, float[] RangeFaceConfidence, float[] RectangleIntersectMinimums, + bool ReMap, bool Reverse, string[] SaveBlurHashForOutputResolutions, string[] SaveFaceDistancesForOutputResolutions, diff --git a/Instance/Models/_F_Random.cs b/Instance/Models/_F_Random.cs index 8ff650c..4059686 100644 --- a/Instance/Models/_F_Random.cs +++ b/Instance/Models/_F_Random.cs @@ -30,7 +30,6 @@ internal class F_Random { Dictionary> results = new(); string key; - long personKey; DateTime dateTime; List? personKeys; List? relativePaths; @@ -40,12 +39,11 @@ internal class F_Random continue; if (!idToPersonKeys.TryGetValue(mapping.MappingFromItem.Id, out personKeys)) continue; - if (Shared.Models.Stateless.Methods.IPersonBirthday.IsCounterPersonBirthday(mapping.MappingFromPerson.PersonBirthday)) + if (Shared.Models.Stateless.Methods.IPersonBirthday.IsCounterPersonYear(mapping.MappingFromPerson.PersonKey)) continue; - if (!personKeys.Contains(mapping.MappingFromPerson.PersonBirthday.Value.Ticks)) + if (!personKeys.Contains(mapping.MappingFromPerson.PersonKey)) continue; - personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks; - dateTime = new(personKey); + dateTime = new(mapping.MappingFromPerson.PersonKey); key = dateTime.ToString(dateFormat); if (!results.TryGetValue(key, out relativePaths)) { diff --git a/Map/Models/Configuration.cs b/Map/Models/Configuration.cs index 82976a9..7374b68 100644 --- a/Map/Models/Configuration.cs +++ b/Map/Models/Configuration.cs @@ -13,6 +13,8 @@ public record Configuration(bool DeletePossibleDuplicates, char[] PersonCharacters, int[] RangeDaysDeltaTolerance, float[] RangeDistanceTolerance, + bool ReMap, + bool SaveIndividually, bool SaveSortingWithoutPerson, string[] SkipNotSkipDirectories, int SortingMaximumPerKey, diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index 22f67f6..e8e09ea 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -1,9 +1,11 @@ using Humanizer; using ShellProgressBar; +using System.Buffers; using System.Collections.ObjectModel; using System.Globalization; using System.Text.Json; using System.Text.RegularExpressions; +using View_by_Distance.Map.Models.Stateless.Methods; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Stateless.Methods; using WindowsShortcutFactory; @@ -13,26 +15,10 @@ namespace View_by_Distance.Map.Models; public partial class MapLogic : Shared.Models.Methods.IMapLogic { - private bool IsUsed(bool ignoreXMatches, int id, ReadOnlyDictionary>? wholePercentagesToPersonContainers, int wholePercentages) - { - bool result; - List? wholePercentagesCollection; - ReadOnlyCollection? personContainers; - result = _SkipCollection.TryGetValue(id, out wholePercentagesCollection) && wholePercentagesCollection.Contains(wholePercentages); - if (!result && wholePercentagesToPersonContainers is not null) - if (wholePercentagesToPersonContainers.TryGetValue(wholePercentages, out personContainers)) - if (!ignoreXMatches || !personContainers.Any(l => IPerson.IsDefaultName(l))) - result = true; - return result; - } - - public bool IsUsed(bool ignoreXMatches, int id, ReadOnlyDictionary>? wholePercentagesToPersonContainers, MappingFromLocation mappingFromLocation) => - IsUsed(ignoreXMatches, id, wholePercentagesToPersonContainers, mappingFromLocation.WholePercentages); - [GeneratedRegex("[\\\\,\\/,\\:,\\*,\\?,\\\",\\<,\\>,\\|]")] private static partial Regex FileSystemSafe(); - public void SaveContainers(bool saveIndividually, int? updated, List saveContainers) + public void SaveContainers(int? updated, List saveContainers) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -79,7 +65,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic } else continue; - if (saveIndividually) + if (_Configuration.SaveIndividually) { fileName = Path.GetFileName(checkFile); if (distinct.Contains(fileName)) @@ -89,7 +75,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic if (File.Exists(checkFile)) continue; File.Copy(sourceFile, checkFile); - if (saveIndividually) + if (_Configuration.SaveIndividually) continue; if (saveContainer.MakeAllHidden) File.SetAttributes(checkFile, FileAttributes.Hidden); @@ -148,7 +134,6 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); int season; - long personKey; string fileName; string directory; string weekOfYear; @@ -158,7 +143,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic List? personKeys; string personKeyFormatted; Calendar calendar = new CultureInfo("en-US").Calendar; - ReadOnlyDictionary> idToPersonKeys = Stateless.Methods.IMapLogic.GetIdToPersonKeys(personKeyToIds); + ReadOnlyDictionary> idToPersonKeys = IMapLogic.GetIdToPersonKeys(personKeyToIds); foreach (Mapping mapping in mappingCollection) { dateTime = mapping.MappingFromItem.GetDateTimeOriginalThenMinimumDateTime(); @@ -182,10 +167,9 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic continue; if (!idToPersonKeys.TryGetValue(mapping.MappingFromItem.Id, out personKeys)) continue; - personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks; - if (!personKeys.Contains(mapping.MappingFromPerson.PersonBirthday.Value.Ticks)) + if (!personKeys.Contains(mapping.MappingFromPerson.PersonKey)) continue; - personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday); + personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonKey); directory = Path.Combine($"{eDistanceContentDirectory}---", "Person Key Shortcuts", personKeyFormatted, directoryName); fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk"); results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.GetDateTimeOriginalThenMinimumDateTime(), fileName, description, MakeAllHidden: false)); @@ -399,45 +383,32 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic return new(result, wholePercentagesToPersonContainers); } - public int UpdateMappingFromPerson(ReadOnlyCollection? locationContainersFiles, ReadOnlyDictionary>? wholePercentagesToPersonContainers, Mapping mapping) + public int UpdateMappingFromPerson(ReadOnlyDictionary>? wholePercentagesToPersonContainers, Mapping mapping) { int result = 0; - long personKey; - const int zero = 0; - string mappingSegmentB; - PersonBirthday personBirthday; - ReadOnlyCollection? personContainers; - for (int i = 1; i < 2; i++) + if (mapping.MappingFromLocation is not null) { - if (mapping.MappingFromLocation is null) - continue; if (wholePercentagesToPersonContainers is null) - { - if (mapping.MappingFromFilter.InSkipCollection is not null && mapping.MappingFromFilter.InSkipCollection.Value) - continue; result += 1; - continue; - } - if (!wholePercentagesToPersonContainers.TryGetValue(mapping.MappingFromLocation.WholePercentages, out personContainers)) + else { - if (mapping.MappingFromFilter.InSkipCollection is not null && mapping.MappingFromFilter.InSkipCollection.Value) - continue; - result += 1; - continue; - } - foreach (PersonContainer personContainer in personContainers) - { - if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Birthdays.Length == 0) - continue; - personBirthday = personContainer.Birthdays[zero]; - personKey = personBirthday.Value.Ticks; - mappingSegmentB = Stateless.MapLogic.GetMappingSegmentB(_Ticks, personBirthday, personContainer.ApproximateYears, mapping.MappingFromItem); - 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); + ReadOnlyCollection? personContainers; + if (!wholePercentagesToPersonContainers.TryGetValue(mapping.MappingFromLocation.WholePercentages, out personContainers)) + result += 1; + else + { + const int zero = 0; + string mappingSegmentB; + PersonBirthday personBirthday; + foreach (PersonContainer personContainer in personContainers) + { + if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Birthdays.Length == 0) + continue; + personBirthday = personContainer.Birthdays[zero]; + mappingSegmentB = Stateless.MapLogic.GetMappingSegmentB(_Ticks, personBirthday, personContainer.ApproximateYears, mapping.MappingFromItem); + mapping.UpdateMappingFromPerson(personContainer.ApproximateYears, personContainer.DisplayDirectoryName, personContainer.Key.Value, mappingSegmentB); + } + } } } return result; @@ -498,6 +469,55 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic return (ticks, directory); } + private static bool PreAndPostContinue(Configuration configuration, ReadOnlyDictionary> idToWholePercentagesToMapping, Sorting sorting, Mapping mapping, Mapping keyMapping) + { + bool result = true; + if (result && mapping.MappingFromFilterPre.InSkipCollection is not null && mapping.MappingFromFilterPre.InSkipCollection.Value) + result = false; + if (result && mapping.MappingFromFilterPre.IsFocusModel is not null && !mapping.MappingFromFilterPre.IsFocusModel.Value) + result = false; + if (result && mapping.MappingFromFilterPre.IsFocusRelativePath is not null && !mapping.MappingFromFilterPre.IsFocusRelativePath.Value) + result = false; + if (result && mapping.MappingFromFilterPost.InSkipCollection is not null && mapping.MappingFromFilterPost.InSkipCollection.Value) + result = false; + if (result && mapping.MappingFromFilterPost.IsFocusPerson is not null && !mapping.MappingFromFilterPost.IsFocusPerson.Value) + result = false; + if (result && keyMapping.MappingFromFilterPost.CanReMap is not null && !configuration.ReMap) + result = false; + if (result && keyMapping.MappingFromFilterPost.CanReMap is not null && (!keyMapping.MappingFromFilterPost.CanReMap.Value || (mapping.MappingFromPerson is not null && IPerson.IsDefaultName(mapping.MappingFromPerson.DisplayDirectoryName)))) + result = false; + if (result && keyMapping.MappingFromFilterPost.InSkipCollection is not null && keyMapping.MappingFromFilterPost.InSkipCollection.Value) + result = false; + if (result && keyMapping.MappingFromFilterPost.IsFocusPerson is not null && keyMapping.MappingFromFilterPost.IsFocusPerson.Value) + result = false; + return result; + } + + private (string?, long?, string) Get(Configuration configuration, bool saveIndividually, string by, Mapping question, int padLeft) + { + long? ticks; + string? directory; + string personDirectory; + if (question.MappingFromPerson is null) + { + (ticks, directory) = GetDirectory(configuration, saveIndividually, padLeft, question.SegmentC, by, question.MappingFromItem); + personDirectory = directory is null ? string.Empty : Path.Combine(directory, $"X+{ticks}"); + } + else + { + ticks = null; + string personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, question.MappingFromPerson.PersonKey); + if (string.IsNullOrEmpty(question.SegmentC)) + directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, question.MappingFromPerson.SegmentB); + else if (saveIndividually) + directory = Path.Combine(_EDistanceContentTicksDirectory, by, question.SegmentC.PadLeft(padLeft, '0'), personKeyFormatted, question.MappingFromPerson.SegmentB); + else + directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, question.MappingFromPerson.SegmentB, question.SegmentC); + personDirectory = Path.Combine(directory, question.MappingFromPerson.DisplayDirectoryName, "lnk"); + } + return (directory, ticks, personDirectory); + } + private List GetSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyCollection mappingCollection, ReadOnlyDictionary> idToWholePercentagesToMapping, ReadOnlyDictionary> personKeyToIds, int? useFiltersCounter, bool saveMapped, bool saveIndividually, bool sortingContainersAny) { if (_Configuration is null) @@ -506,20 +526,17 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic string by; long? ticks; List? ids; - long personKey; bool isByMapping; bool isBySorting; + Sorting? sorting; string checkFile; string? directory; + Mapping? question; string shortcutFile; - Mapping? keyMapping; string facesDirectory; - string? directoryName; string personDirectory; FileHolder faceFileHolder; string facePartsDirectory; - string personKeyFormatted; - List distinct = new(); SaveContainer? saveContainer; FileHolder facePartsFileHolder; FileHolder hiddenFaceFileHolder; @@ -530,82 +547,62 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic { if (mapping.MappingFromLocation is null) continue; - directoryName = Path.GetDirectoryName(mapping.MappingFromItem.RelativePath); - if (directoryName is null) - throw new NotSupportedException(); - if (mapping.MappingFromFilter.InSkipCollection is not null && mapping.MappingFromFilter.InSkipCollection.Value) + if (mapping.MappingFromFilterPre.InSkipCollection is not null && mapping.MappingFromFilterPre.InSkipCollection.Value) + continue; + if (mapping.MappingFromFilterPre.IsFocusModel is not null && !mapping.MappingFromFilterPre.IsFocusModel.Value) + continue; + if (mapping.MappingFromFilterPre.IsFocusRelativePath is not null && !mapping.MappingFromFilterPre.IsFocusRelativePath.Value) + continue; + if (mapping.MappingFromFilterPost.InSkipCollection is not null && mapping.MappingFromFilterPost.InSkipCollection.Value) + continue; + if (mapping.MappingFromFilterPost.IsFocusPerson is not null && !mapping.MappingFromFilterPost.IsFocusPerson.Value) continue; (by, isByMapping, isBySorting) = Stateless.MapLogic.Get(useFiltersCounter, saveIndividually, sortingContainersAny, forceSingleImageHumanized, mapping); if (isByMapping && !saveMapped) continue; - if (mapping.MappingFromPerson is null) - { - if (!_Configuration.SaveSortingWithoutPerson) - continue; - if (mapping.SortingContainer is null) - { - if (sortingContainersAny) - continue; - mapping.UpdateMappingFromUnknownPerson(saveIndividually, new(mapping, new(mapping, mapping.MappingFromLocation))); - if (mapping.SortingContainer is null) - continue; - } - if (distinct.Contains(mapping.MappingFromItem.Id)) - continue; - if (distinct.Contains(mapping.SortingContainer.Sorting.Id)) - continue; - (ticks, directory) = GetDirectory(_Configuration, saveIndividually, padLeft, mapping.SegmentC, by, mapping.MappingFromItem); - if (ticks is null || string.IsNullOrEmpty(directory)) - continue; - personDirectory = Path.Combine(directory, $"X+{ticks}"); - if (saveIndividually) - { - directory = Path.Combine(directory, mapping.MappingFromItem.Id.ToString()); - results.Add(new(Path.Combine(directory, $"X+{ticks}"))); - } - distinct.Add(mapping.MappingFromItem.Id); - distinct.Add(mapping.SortingContainer.Sorting.Id); - } + if (!isBySorting || mapping.SortingContainer is null) + (sorting, question) = (null, null); else { - if (string.IsNullOrEmpty(mapping.MappingFromPerson.SegmentB)) + sorting = mapping.SortingContainer.Sorting; + if (!idToWholePercentagesToMapping.TryGetValue(sorting.Id, out wholePercentagesToMapping)) throw new NotSupportedException(); - if (string.IsNullOrEmpty(mapping.MappingFromPerson.DisplayDirectoryName)) + if (!wholePercentagesToMapping.TryGetValue(sorting.WholePercentages, out question)) throw new NotSupportedException(); - personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks; - personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday); - if (string.IsNullOrEmpty(mapping.SegmentC)) - directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, mapping.MappingFromPerson.SegmentB); - else if (saveIndividually) - directory = Path.Combine(_EDistanceContentTicksDirectory, by, mapping.SegmentC.PadLeft(padLeft, '0'), personKeyFormatted, mapping.MappingFromPerson.SegmentB); - else - directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, mapping.MappingFromPerson.SegmentB, mapping.SegmentC); - if (isByMapping) - personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName); - else if (mapping.By is not null) - personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName, "lnk"); - else - personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName[..1], "lnk"); + if (!PreAndPostContinue(_Configuration, idToWholePercentagesToMapping, sorting, mapping, question)) + continue; + } + (directory, ticks, personDirectory) = Get(_Configuration, saveIndividually, by, mapping, padLeft); + if (string.IsNullOrEmpty(directory)) + throw new NotSupportedException(); + if (mapping.MappingFromPerson is not null) + { if (saveIndividually) { directory = Path.Combine(directory, mapping.MappingFromItem.Id.ToString()); results.Add(new(Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName))); } - if (isByMapping && personKeyToIds.TryGetValue(personKey, out ids)) + if (isByMapping && personKeyToIds.TryGetValue(mapping.MappingFromPerson.PersonKey, out ids)) results.Add(new(Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName, $"{ids.Count} Face(s)"))); } - results.Add(new(personDirectory)); - if (!isBySorting || mapping.SortingContainer is null) - keyMapping = null; else { - if (!idToWholePercentagesToMapping.TryGetValue(mapping.SortingContainer.Sorting.Id, out wholePercentagesToMapping)) + if (!_Configuration.SaveSortingWithoutPerson) continue; - if (!wholePercentagesToMapping.TryGetValue(mapping.SortingContainer.Sorting.WholePercentages, out keyMapping)) + if (ticks is null) continue; - if (keyMapping.MappingFromLocation is null) + if (saveIndividually) + { + directory = Path.Combine(directory, mapping.MappingFromItem.Id.ToString()); + results.Add(new(Path.Combine(directory, $"X+{ticks}"))); + } + } + results.Add(new(personDirectory)); + if (question is not null) + { + if (question.MappingFromLocation is null) continue; - if (saveIndividually && keyMapping.MappingFromLocation.WholePercentages == mapping.MappingFromLocation.WholePercentages) + if (saveIndividually && question.MappingFromLocation.WholePercentages == mapping.MappingFromLocation.WholePercentages) results.Add(new(Path.Combine(directory, "Maybe"))); } facesDirectory = Stateless.MapLogic.GetFacesDirectory(_PropertyConfiguration, dFacesContentDirectory, mapping.MappingFromItem); @@ -633,43 +630,12 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic hiddenFaceFileHolder = new(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesHiddenFileNameExtension}")); facePartsFileHolder = new(Path.Combine(facePartsDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacePartsFileNameExtension}")); saveContainer = new(checkFile, directory, faceFileHolder, hiddenFaceFileHolder, facePartsFileHolder, mapping.MappingFromItem.ResizedFileHolder, shortcutFile); - if (!isByMapping && mapping.By is not null && mapping.MappingFromPerson?.LocationContainersFiles.Count > 0 && IPerson.IsDefaultName(mapping.MappingFromPerson)) - results.Add(new(Path.GetDirectoryName(personDirectory) ?? personDirectory, mapping.MappingFromPerson.LocationContainersFiles[0])); - } - results.Add(saveContainer); - if (!isBySorting || mapping.SortingContainer is null || keyMapping is null) - continue; - if (!saveIndividually && isBySorting && mapping.MappingFromPerson is null) - { - saveContainer = GetMatchSaveContainer(dFacesContentDirectory, d2FacePartsContentDirectory, directory, keyMapping); - if (saveContainer is not null) - results.Add(saveContainer); - } - if (!saveIndividually) - saveContainer = Stateless.MapLogic.GetDebugSaveContainer(directory, mapping.MappingFromPerson, mapping.SortingContainer, keyMapping); - else - { - (saveContainer, SaveContainer? extraSaveContainer) = Stateless.MapLogic.GetContainers(_Configuration.FacesFileNameExtension, _Configuration.FacePartsFileNameExtension, _PropertyConfiguration, dFacesContentDirectory, d2FacePartsContentCollectionDirectory, directory, mapping.SortingContainer, keyMapping); - if (saveContainer is null || extraSaveContainer is null) - continue; - results.Add(extraSaveContainer); } results.Add(saveContainer); } return results; } - public List GetSaveContainers(bool saveIndividually, string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyCollection mappingCollection, ReadOnlyDictionary> idToWholePercentagesToMapping, int? useFiltersCounter, bool sortingContainersAny) - { - if (_Configuration is null) - throw new NullReferenceException(nameof(_Configuration)); - List results; - bool saveMapped = false; - ReadOnlyDictionary> personKeyToIds = new(new Dictionary>()); - results = GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, mappingCollection, idToWholePercentagesToMapping, personKeyToIds, useFiltersCounter, saveMapped, saveIndividually, sortingContainersAny); - return results; - } - public void SaveMapped(string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyDictionary> personKeyToIds, ReadOnlyCollection mappingCollection, ReadOnlyDictionary> idToWholePercentagesToMapping) { if (_Configuration is null) @@ -677,42 +643,55 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic int? updated = null; bool saveMapped = true; int? useFiltersCounter = null; - bool saveIndividually = false; string mappingDirectory = Path.Combine(_EDistanceContentTicksDirectory, nameof(Shared.Models.Stateless.IMapLogic.Mapping)); List saveContainers = GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, mappingCollection, idToWholePercentagesToMapping, personKeyToIds, useFiltersCounter, saveMapped, sortingContainersAny: true, saveIndividually: false); - SaveContainers(saveIndividually, updated, saveContainers); + SaveContainers(updated, saveContainers); if (!string.IsNullOrEmpty(_EDistanceContentTicksDirectory) && Directory.Exists(mappingDirectory)) Stateless.MapLogic.SaveMappingShortcuts(mappingDirectory); } - public List GetSortingCollection(int i, FaceDistance faceDistanceEncoding, Face face, List faceDistanceLengths) + public List GetSortingCollection(int i, Face face, FaceDistance faceDistanceEncoding, List faceDistanceLengths) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); List results = new(); Sorting sorting; FaceDistance faceDistanceLength; - List? wholePercentagesCollection; - bool skipNotSkipCollectionAny = _SkipNotSkipCollection.Count > 0; for (int j = 0; j < faceDistanceLengths.Count; j++) { if (faceDistanceEncoding.WholePercentages is null) throw new NotSupportedException(); - if (face.Mapping?.MappingFromFilter is null) + if (face.Mapping?.MappingFromFilterPost is null) throw new NotSupportedException(); if (j == i) continue; - if (faceDistanceEncoding.Id is not null && _SkipCollection.TryGetValue(faceDistanceEncoding.Id.Value, out wholePercentagesCollection) && wholePercentagesCollection.Contains(faceDistanceEncoding.WholePercentages.Value)) - continue; - if (faceDistanceEncoding.Id is not null && skipNotSkipCollectionAny && (!_SkipNotSkipCollection.TryGetValue(faceDistanceEncoding.Id.Value, out wholePercentagesCollection) || !wholePercentagesCollection.Contains(faceDistanceEncoding.WholePercentages.Value))) - continue; - if (face.Mapping.MappingFromFilter.IsUsed is not null && face.Mapping.MappingFromFilter.IsUsed.Value) - continue; + if (face.Mapping.MappingFromFilterPre.InSkipCollection is not null && face.Mapping.MappingFromFilterPre.InSkipCollection.Value) + throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance)); + if (face.Mapping.MappingFromFilterPre.IsFocusModel is not null && face.Mapping.MappingFromFilterPre.IsFocusModel.Value) + throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance)); + if (face.Mapping.MappingFromFilterPre.IsFocusRelativePath is not null && face.Mapping.MappingFromFilterPre.IsFocusRelativePath.Value) + throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance)); + if (face.Mapping.MappingFromFilterPost.InSkipCollection is not null && face.Mapping.MappingFromFilterPost.InSkipCollection.Value) + throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance)); + if (face.Mapping.MappingFromFilterPost.IsFocusPerson is not null && !face.Mapping.MappingFromFilterPost.IsFocusPerson.Value) + throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance)); + if (face.Mapping.MappingFromFilterPost.InSkipCollection is not null && face.Mapping.MappingFromFilterPost.InSkipCollection.Value) + throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance)); faceDistanceLength = faceDistanceLengths[j]; if (faceDistanceLength.WholePercentages is null || faceDistanceLength.Length is null) throw new NotSupportedException(); if (faceDistanceLength.Length == 0) continue; + if (faceDistanceLength.MappingFromFilterPost is null) + throw new NotSupportedException(); + if (faceDistanceLength.MappingFromFilterPost.CanReMap is not null && !_Configuration.ReMap) + continue; + if (faceDistanceLength.MappingFromFilterPost.CanReMap is not null && !faceDistanceLength.MappingFromFilterPost.CanReMap.Value) + continue; + if (faceDistanceLength.MappingFromFilterPost.InSkipCollection is not null && faceDistanceLength.MappingFromFilterPost.InSkipCollection.Value) + continue; + if (faceDistanceLength.MappingFromFilterPost.IsFocusPerson is not null && !faceDistanceLength.MappingFromFilterPost.IsFocusPerson.Value) + continue; sorting = ISorting.Get(_Configuration.FaceDistancePermyriad, faceDistanceEncoding, faceDistanceLength); if (sorting.DistancePermyriad == 0) continue; @@ -727,7 +706,49 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic return results; } - public int UpdateFromSortingContainers(bool saveIndividually, ReadOnlyDictionary> idToWholePercentagesToMapping, Shared.Models.Methods.IDistanceLimits distanceLimits, SortingContainer[] sortingContainers) + public int UpdateFromSortingContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyDictionary> idToWholePercentagesToMapping, ReadOnlyCollection sortingContainers) + { + if (_Configuration is null) + throw new NullReferenceException(nameof(_Configuration)); + int result = 0; + string key; + string segmentB; + string? segmentC; + string personKeyFormatted; + MappingFromPerson mappingFromPerson; + Dictionary keyToCount = new(); + foreach (SortingContainer sortingContainer in sortingContainers) + { + if (sortingContainer.Question is null) + throw new NotSupportedException(); + if (sortingContainer.Source.MappingFromPerson is null) + { + sortingContainer.Question.UpdateMappingFromUnknownPerson(_Configuration.SaveIndividually, sortingContainer); + result += 1; + } + else + { + mappingFromPerson = sortingContainer.Source.MappingFromPerson; + personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mappingFromPerson.PersonKey); + segmentB = IMapLogic.GetDecade(sortingContainer.Question.MappingFromItem); + key = string.Concat(personKeyFormatted, '\t', segmentB); + if (!keyToCount.ContainsKey(key)) + keyToCount.Add(key, new()); + if (!keyToCount.ContainsKey(key)) + keyToCount.Add(key, 0); + keyToCount[key]++; + if (!_Configuration.SaveIndividually && keyToCount[key] < _Configuration.SortingMaximumPerKey) + segmentC = null; + else + segmentC = sortingContainer.Sorting.DistancePermyriad.ToString(); + sortingContainer.Question.UpdateMappingFromPerson(mappingFromPerson.ApproximateYears, mappingFromPerson.DisplayDirectoryName, mappingFromPerson.PersonKey, segmentB, segmentC, sortingContainer); + result += 1; + } + } + return result; + } + + public List GetSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyDictionary> idToWholePercentagesToMapping, Shared.Models.Methods.IDistanceLimits distanceLimits, int? useFiltersCounter, ReadOnlyCollection sortingContainers) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -736,91 +757,173 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic string counts = distanceLimits.GetCounts(); _ = Directory.CreateDirectory(Path.Combine(_EDistanceContentTicksDirectory, counts)); } - int result = 0; - string key; - Mapping? mapping; - const int zero = 0; - string mappingSegmentB; - string personKeyFormatted; - PersonBirthday personBirthday; - List? wholePercentagesCollectionForA; - List? wholePercentagesCollectionForB; - Dictionary keyToCount = new(); - Dictionary keyToSegmentC = new(); - ReadOnlyCollection? personContainers; - ReadOnlyDictionary? wholePercentagesToMapping; - Dictionary> idToWholePercentagesCollectionForA = new(); - Dictionary> idToWholePercentagesCollectionForB = new(); - int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - _Ticks).TotalSeconds); - ReadOnlyDictionary>? wholePercentagesToPersonContainers; - string message = $") {sortingContainers.Length:000} Update From Sorting Container(s) - {totalSeconds} total second(s)"; - ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; - using ProgressBar progressBar = new(sortingContainers.Length, message, options); + List results = new(); + string by; + long? ticks; + bool isBySorting; + string checkFile; + Mapping? question; + string? directory; + string shortcutFile; + string facesDirectory; + string personDirectory; + bool isCounterPersonYear; + string facePartsDirectory; + FileHolder? faceFileHolder; + SaveContainer? saveContainer; + FileHolder? facePartsFileHolder; + FileHolder? hiddenFaceFileHolder; + int padLeft = _Configuration.FaceDistancePermyriad.ToString().Length; + string forceSingleImageHumanized = nameof(Shared.Models.Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title); foreach (SortingContainer sortingContainer in sortingContainers) { - progressBar.Tick(); - if (sortingContainer.Mapping?.MappingFromLocation is null) + if (sortingContainer.Question is null) throw new NotSupportedException(); - if (!idToWholePercentagesCollectionForA.TryGetValue(sortingContainer.Mapping.MappingFromItem.Id, out wholePercentagesCollectionForA)) + isCounterPersonYear = sortingContainer.Source.MappingFromPerson is not null && IPersonBirthday.IsCounterPersonYear(sortingContainer.Source.MappingFromPerson.PersonKey); + (by, _, isBySorting) = Stateless.MapLogic.Get(useFiltersCounter, _Configuration.SaveIndividually, sortingContainers.Count > 0, forceSingleImageHumanized, sortingContainer.Question); + question = sortingContainer.Question.MappingFromPerson is null ? sortingContainer.Source : sortingContainer.Question; + if (question is null) + throw new NotSupportedException(); + if (question.MappingFromLocation is null) + continue; + (directory, ticks, personDirectory) = Get(_Configuration, _Configuration.SaveIndividually, by, question, padLeft); + if (string.IsNullOrEmpty(directory)) + throw new NotSupportedException(); + if (question.MappingFromPerson is not null) { - idToWholePercentagesCollectionForA.Add(sortingContainer.Mapping.MappingFromItem.Id, new()); - if (!idToWholePercentagesCollectionForA.TryGetValue(sortingContainer.Mapping.MappingFromItem.Id, out wholePercentagesCollectionForA)) - throw new Exception(); - } - if (!idToWholePercentagesCollectionForB.TryGetValue(sortingContainer.Mapping.MappingFromItem.Id, out wholePercentagesCollectionForB)) - { - idToWholePercentagesCollectionForB.Add(sortingContainer.Mapping.MappingFromItem.Id, new()); - if (!idToWholePercentagesCollectionForB.TryGetValue(sortingContainer.Mapping.MappingFromItem.Id, out wholePercentagesCollectionForB)) - throw new Exception(); - } - if (!_IdThenWholePercentagesToPersonContainers.TryGetValue(sortingContainer.Sorting.Id, out wholePercentagesToPersonContainers) || !wholePercentagesToPersonContainers.TryGetValue(sortingContainer.Sorting.WholePercentages, out personContainers)) - { - if (!_Configuration.SaveSortingWithoutPerson) - continue; - if (wholePercentagesCollectionForA.Contains(sortingContainer.Mapping.MappingFromLocation.WholePercentages)) - continue; - sortingContainer.Mapping.UpdateMappingFromUnknownPerson(saveIndividually, sortingContainer); - wholePercentagesCollectionForA.Add(sortingContainer.Mapping.MappingFromLocation.WholePercentages); - result += 1; + if (_Configuration.SaveIndividually) + { + directory = Path.Combine(directory, question.MappingFromItem.Id.ToString()); + results.Add(new(Path.Combine(directory, question.MappingFromPerson.DisplayDirectoryName))); + } } else { - if (wholePercentagesCollectionForB.Contains(sortingContainer.Mapping.MappingFromLocation.WholePercentages)) + if (!_Configuration.SaveSortingWithoutPerson) + throw new NotSupportedException(); + if (ticks is null) continue; - foreach (PersonContainer personContainer in personContainers) + if (_Configuration.SaveIndividually) { - if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Birthdays.Length == 0) - continue; - personBirthday = personContainer.Birthdays[zero]; - personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personBirthday); - mappingSegmentB = Stateless.MapLogic.GetMappingSegmentB(_Ticks, personBirthday, personContainer.ApproximateYears, sortingContainer.Mapping.MappingFromItem); - key = string.Concat(personKeyFormatted, '\t', mappingSegmentB); - if (!keyToCount.ContainsKey(key)) - keyToCount.Add(key, new()); - if (!keyToCount.ContainsKey(key)) - keyToCount.Add(key, 0); - if (!keyToSegmentC.ContainsKey(key)) - keyToSegmentC.Add(key, string.Empty); - keyToCount[key]++; - if (saveIndividually || keyToCount[key] > _Configuration.SortingMaximumPerKey) - { - keyToCount[key] = 0; - keyToSegmentC[key] = sortingContainer.Sorting.DistancePermyriad.ToString(); - } - if (!idToWholePercentagesToMapping.TryGetValue(sortingContainer.Sorting.Id, out wholePercentagesToMapping)) - continue; - if (!wholePercentagesToMapping.TryGetValue(sortingContainer.Sorting.WholePercentages, out mapping)) - continue; - if (mapping.MappingFromPerson is null) - continue; - sortingContainer.Mapping.UpdateMappingFromPerson(personContainer.ApproximateYears, personContainer.DisplayDirectoryName, personBirthday, mappingSegmentB, keyToSegmentC[key], sortingContainer, mapping.MappingFromPerson.LocationContainersFiles); - wholePercentagesCollectionForB.Add(sortingContainer.Mapping.MappingFromLocation.WholePercentages); - result += 1; - break; + directory = Path.Combine(directory, question.MappingFromItem.Id.ToString()); + results.Add(new(Path.Combine(directory, $"X+{ticks}"))); } } + results.Add(new(personDirectory)); + if (_Configuration.SaveIndividually && question.MappingFromLocation.WholePercentages == question.MappingFromLocation.WholePercentages) + results.Add(new(Path.Combine(directory, "Maybe"))); + facesDirectory = Stateless.MapLogic.GetFacesDirectory(_PropertyConfiguration, dFacesContentDirectory, question.MappingFromItem); + faceFileHolder = new(Path.Combine(facesDirectory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}")); + facePartsDirectory = Stateless.MapLogic.GetFacePartsDirectory(_PropertyConfiguration, d2FacePartsContentDirectory, question.MappingFromItem); + shortcutFile = Path.Combine(personDirectory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}.lnk"); + checkFile = Path.Combine(directory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}"); + hiddenFaceFileHolder = new(Path.Combine(facesDirectory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesHiddenFileNameExtension}")); + facePartsFileHolder = new(Path.Combine(facePartsDirectory, $"{question.MappingFromLocation.DeterministicHashCodeKey}{question.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacePartsFileNameExtension}")); + saveContainer = new(checkFile, directory, faceFileHolder, hiddenFaceFileHolder, facePartsFileHolder, question.MappingFromItem.ResizedFileHolder, shortcutFile); + results.Add(saveContainer); + if (!_Configuration.SaveIndividually && isBySorting && question.MappingFromPerson is null) + { + saveContainer = GetMatchSaveContainer(dFacesContentDirectory, d2FacePartsContentDirectory, directory, question); + if (saveContainer is not null) + results.Add(saveContainer); + } + if (!_Configuration.SaveIndividually) + saveContainer = Stateless.MapLogic.GetDebugSaveContainer(sortingContainer, directory, question); + else + { + (saveContainer, SaveContainer? extraSaveContainer) = Stateless.MapLogic.GetContainers(_Configuration.FacesFileNameExtension, _Configuration.FacePartsFileNameExtension, _PropertyConfiguration, dFacesContentDirectory, d2FacePartsContentCollectionDirectory, directory, question); + if (saveContainer is null || extraSaveContainer is null) + continue; + results.Add(extraSaveContainer); + } + results.Add(saveContainer); } - return result; + return results; + } + + public ReadOnlyCollection GetFilterSortingContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyDictionary> idToWholePercentagesToMapping, Shared.Models.Methods.IDistanceLimits distanceLimits, ReadOnlyCollection sortingContainers) + { + if (_Configuration is null) + throw new NullReferenceException(nameof(_Configuration)); + if (distanceLimits is not null) + { + string counts = distanceLimits.GetCounts(); + _ = Directory.CreateDirectory(Path.Combine(_EDistanceContentTicksDirectory, counts)); + } + List results = new(); + Sorting sorting; + Mapping? keyMapping; + List? wholePercentagesCollection; + MappingFromFilterPre mappingFromFilterPre; + Dictionary keyToCount = new(); + MappingFromFilterPost mappingFromFilterPost; + ReadOnlyCollection? personContainers; + ReadOnlyDictionary? wholePercentagesToMapping; + Dictionary> idToWholePercentagesCollection = new(); + int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - _Ticks).TotalSeconds); + ReadOnlyDictionary>? wholePercentagesToPersonContainers; + string message = $") {sortingContainers.Count:000} Filter Sorting Container(s) - {totalSeconds} total second(s)"; + ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; + using ProgressBar progressBar = new(sortingContainers.Count, message, options); + foreach (SortingContainer sortingContainer in sortingContainers) + { + progressBar.Tick(); + if (sortingContainer.Source?.MappingFromLocation is null) + throw new NotSupportedException(); + mappingFromFilterPre = sortingContainer.Source.MappingFromFilterPre; + mappingFromFilterPost = sortingContainer.Source.MappingFromFilterPost; + if (sortingContainer.Source.MappingFromFilterPre.InSkipCollection is not null && sortingContainer.Source.MappingFromFilterPre.InSkipCollection.Value) + throw new NotSupportedException(nameof(GetSortingCollection)); + if (sortingContainer.Source.MappingFromFilterPre.IsFocusModel is not null && sortingContainer.Source.MappingFromFilterPre.IsFocusModel.Value) + throw new NotSupportedException(nameof(GetSortingCollection)); + if (sortingContainer.Source.MappingFromFilterPre.IsFocusRelativePath is not null && sortingContainer.Source.MappingFromFilterPre.IsFocusRelativePath.Value) + throw new NotSupportedException(nameof(GetSortingCollection)); + if (sortingContainer.Source.MappingFromFilterPost.InSkipCollection is not null && sortingContainer.Source.MappingFromFilterPost.InSkipCollection.Value) + throw new NotSupportedException(nameof(GetSortingCollection)); + if (sortingContainer.Source.MappingFromFilterPost.InSkipCollection is not null && sortingContainer.Source.MappingFromFilterPost.InSkipCollection.Value) + throw new NotSupportedException(nameof(GetSortingCollection)); + if (sortingContainer.Source.MappingFromFilterPost.IsFocusPerson is not null && !sortingContainer.Source.MappingFromFilterPost.IsFocusPerson.Value) + throw new NotSupportedException(nameof(GetSortingCollection)); + sorting = sortingContainer.Sorting; + if (!idToWholePercentagesToMapping.TryGetValue(sorting.Id, out wholePercentagesToMapping)) + throw new NotSupportedException(); + if (!wholePercentagesToMapping.TryGetValue(sorting.WholePercentages, out keyMapping)) + throw new NotSupportedException(); + if (keyMapping.MappingFromFilterPost.CanReMap is not null && !_Configuration.ReMap) + throw new NotSupportedException(nameof(GetSortingCollection)); + if (keyMapping.MappingFromFilterPost.CanReMap is not null && !keyMapping.MappingFromFilterPost.CanReMap.Value) + throw new NotSupportedException(nameof(GetSortingCollection)); + if (!PreAndPostContinue(_Configuration, idToWholePercentagesToMapping, sorting, sortingContainer.Source, keyMapping)) + continue; + if (!idToWholePercentagesCollection.TryGetValue(sorting.Id, out wholePercentagesCollection)) + { + idToWholePercentagesCollection.Add(sorting.Id, new()); + if (!idToWholePercentagesCollection.TryGetValue(sorting.Id, out wholePercentagesCollection)) + throw new Exception(); + } + if (sortingContainer.Source.MappingFromPerson is null) + { + if (!_Configuration.SaveSortingWithoutPerson) + continue; + if (wholePercentagesCollection.Contains(sorting.WholePercentages)) + continue; + keyMapping.UpdateMappingFromUnknownPerson(_Configuration.SaveIndividually, sortingContainer); + wholePercentagesCollection.Add(sorting.WholePercentages); + results.Add(new(keyMapping, sortingContainer.Sorting, sortingContainer.Source)); + } + else + { + if (wholePercentagesCollection.Contains(sorting.WholePercentages)) + continue; + if (keyMapping.MappingFromFilterPost.CanReMap is not null && (IPerson.IsDefaultName(sortingContainer.Source.MappingFromPerson.DisplayDirectoryName) || _IdThenWholePercentagesToPersonContainers.TryGetValue(sorting.Id, out wholePercentagesToPersonContainers) && wholePercentagesToPersonContainers.TryGetValue(sorting.WholePercentages, out personContainers) && personContainers.Any(l => l.Key == sortingContainer.Source.MappingFromPerson.PersonKey))) + continue; + if (sortingContainer.Source.MappingFromPerson is null) + throw new NotSupportedException(); + wholePercentagesCollection.Add(sorting.WholePercentages); + results.Add(new(keyMapping, sortingContainer.Sorting, sortingContainer.Source)); + } + } + return new(results); } private (string, PersonBirthday?) GetPersonBirthday(string[] directoryNames) @@ -950,7 +1053,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic throw new NotSupportedException(); if (string.IsNullOrEmpty(mapping.MappingFromPerson.DisplayDirectoryName)) throw new NotSupportedException(); - personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday); + personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonKey); if (personKeyFormatted == "1501-04-10_00") continue; if (!personKeyFormattedCollection.Contains(personKeyFormatted)) @@ -985,7 +1088,6 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); SaveContainer? saveContainer; - bool saveIndividually = false; List saveContainers = new(); (int, FileHolder, int, string, string, string, string)[] collection = GetCollectionForSaveFilteredOriginalImagesFromJLinks(jLinks, a2PeopleContentDirectory, personContainers, mappingCollection, personKeyToIds); foreach ((int id, FileHolder imageFileHolder, int approximateYears, string personKeyFormatted, string directory, string personDirectory, string checkFile) in collection) @@ -995,7 +1097,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic saveContainer = new(imageFileHolder, checkFile, directory); saveContainers.Add(saveContainer); } - SaveContainers(saveIndividually, null, saveContainers); + SaveContainers(null, saveContainers); } public void SaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, ReadOnlyDictionary> personKeyToIds, ReadOnlyCollection mappingCollection) @@ -1041,7 +1143,6 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); - long personKey; string fileName; string fullName; string directory; @@ -1109,18 +1210,17 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic throw new NotSupportedException(); if (string.IsNullOrEmpty(mapping.MappingFromPerson.DisplayDirectoryName)) throw new NotSupportedException(); - personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday); - personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks; + personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonKey); 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)); } directory = Path.Combine(mapping.MappingFromItem.ResizedFileHolder.DirectoryName, $"{_PropertyConfiguration.ResultAllInOne}Shortcuts", personKeyFormatted); - if (!personKeyToIds.ContainsKey(personKey)) + if (!personKeyToIds.ContainsKey(mapping.MappingFromPerson.PersonKey)) personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName); else - personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName, $"{personKeyToIds[personKey].Count} Face(s)"); + personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName, $"{personKeyToIds[mapping.MappingFromPerson.PersonKey].Count} Face(s)"); fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ResizedFileHolder.Name}.lnk"); collection.Add(new(mapping.MappingFromItem.ResizedFileHolder.FullName, personDirectory, mapping.MappingFromItem.GetDateTimeOriginalThenMinimumDateTime(), fileName, mapping.MappingFromLocation?.DeterministicHashCodeKey, MakeAllHidden: false)); } @@ -1215,38 +1315,6 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic return result; } - public bool? IsFocusPersonOld(int? skipPersonWithMoreThen, List<(string Directory, long PersonKey)> jLinkResolvedDirectories, ReadOnlyDictionary>? wholePercentagesToPersonContainers, MappingFromLocation mappingFromLocation) - { - bool? result; - ReadOnlyCollection? personContainers; - if (skipPersonWithMoreThen is null && jLinkResolvedDirectories.Count == 0) - result = null; - else if (wholePercentagesToPersonContainers is null) - result = null; - else if (!wholePercentagesToPersonContainers.TryGetValue(mappingFromLocation.WholePercentages, out personContainers)) - result = null; - else - { - result = false; - foreach (PersonContainer personContainer in personContainers) - { - 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; - } - } - } - return result; - } - public void LookForAbandoned(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, Container[] containers, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory) { string[] directories; diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index d361a6b..bd68b8a 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -115,7 +115,15 @@ internal abstract class MapLogic } } - internal static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, DateTime dateTimeOriginalThenMinimumDateTime, bool? isWrongYear) + internal static string GetMappingSegmentB(long ticks, long personKey, int? approximateYears, MappingFromItem mappingFromItem) + { + string result; + PersonBirthday personBirthday = IPersonBirthday.GetPersonBirthday(personKey); + result = GetMappingSegmentB(ticks, personBirthday, approximateYears, mappingFromItem.GetDateTimeOriginalThenMinimumDateTime(), mappingFromItem.IsWrongYear); + return result; + } + + private static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, DateTime dateTimeOriginalThenMinimumDateTime, bool? isWrongYear) { string result = GetMappingSegmentB(ticks, personBirthday, approximateYears, dateTimeOriginalThenMinimumDateTime.Ticks, isWrongYear); return result; @@ -285,7 +293,7 @@ internal abstract class MapLogic } } - private static List UpdateDateVerifyAndGetTicksDirectories(string eDistanceContentDirectory) + private static List UpdateDateVerifyAndGetTicksDirectories(Configuration configuration, string eDistanceContentDirectory) { List results = new(); float? totalDays; @@ -333,7 +341,7 @@ internal abstract class MapLogic lastDirectoryTicks = directoryTicks; } string[] compare = (from l in results where l.TotalDays is not null and < 9.95f select l.Directory).ToArray(); - if (compare.Length > 0) + if (compare.Length > 0 && configuration.ReMap) throw new Exception($"Please Consolidate <{string.Join(Environment.NewLine, compare)}>"); return results; } @@ -701,7 +709,7 @@ internal abstract class MapLogic OpenPossibleDuplicates(configuration, duplicates); else { - if (delete.Count > 5) + if (delete.Count > 8) throw new Exception("Something maybe wrong!"); foreach (string file in delete) { @@ -900,7 +908,7 @@ internal abstract class MapLogic results.Clear(); distinct.Clear(); directoryNumber = 0; - ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(eDistanceContentDirectory); + ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(configuration, 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); @@ -1351,46 +1359,44 @@ internal abstract class MapLogic return result; } - internal static SaveContainer GetDebugSaveContainer(string directory, MappingFromPerson? mappingFromPerson, SortingContainer sortingContainer, Mapping mapping) + internal static SaveContainer GetDebugSaveContainer(SortingContainer sortingContainer, string directory, Mapping keyMapping) { SaveContainer result; - if (sortingContainer.Mapping.MappingFromLocation is null) - throw new NullReferenceException(nameof(sortingContainer.Mapping.MappingFromLocation)); - FileHolder faceFileHolder = new($"C:/{sortingContainer.Sorting.Id}.{sortingContainer.Sorting.WholePercentages}"); string shortcutFile; - if (mappingFromPerson is null) - shortcutFile = Path.Combine(directory, $"{sortingContainer.Mapping.MappingFromLocation.DeterministicHashCodeKey}{sortingContainer.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}.{sortingContainer.Sorting.DistancePermyriad}.lnk"); + if (sortingContainer?.Source.MappingFromLocation is null) + throw new NullReferenceException(nameof(sortingContainer.Source.MappingFromLocation)); + FileHolder faceFileHolder = new($"C:/{sortingContainer.Sorting.Id}.{sortingContainer.Sorting.WholePercentages}"); + if (keyMapping.MappingFromPerson is not null && keyMapping.MappingFromLocation is not null) + shortcutFile = Path.Combine(directory, $"{keyMapping.MappingFromLocation.DeterministicHashCodeKey}{keyMapping.MappingFromItem.ImageFileHolder.ExtensionLowered}.{sortingContainer.Sorting.DistancePermyriad}.lnk"); else - shortcutFile = Path.Combine(directory, $"{sortingContainer.Mapping.MappingFromLocation.DeterministicHashCodeKey}{sortingContainer.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}.{sortingContainer.Sorting.DistancePermyriad}.lnk"); - result = new(directory, faceFileHolder, mapping.MappingFromItem.ResizedFileHolder, shortcutFile); + shortcutFile = Path.Combine(directory, $"{sortingContainer.Source.MappingFromLocation.DeterministicHashCodeKey}{sortingContainer.Source.MappingFromItem.ImageFileHolder.ExtensionLowered}.{sortingContainer.Sorting.DistancePermyriad}.lnk"); + result = new(directory, faceFileHolder, sortingContainer.Source.MappingFromItem.ResizedFileHolder, shortcutFile); return result; } - internal static (SaveContainer?, SaveContainer?) GetContainers(string facesFileNameExtension, string facePartsFileNameExtension, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dFacesContentDirectory, string d2FacePartsContentCollectionDirectory, string directory, SortingContainer sortingContainer, Mapping mapping) + internal static (SaveContainer?, SaveContainer?) GetContainers(string facesFileNameExtension, string facePartsFileNameExtension, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dFacesContentDirectory, string d2FacePartsContentCollectionDirectory, string directory, Mapping keyMapping) { SaveContainer? result; SaveContainer? saveContainer; - if (sortingContainer.Mapping.MappingFromLocation is null) - throw new NullReferenceException(nameof(sortingContainer.Mapping.MappingFromLocation)); - if (mapping.MappingFromLocation is null) + if (keyMapping.MappingFromLocation is null) (result, saveContainer) = (null, null); else { - string? facePartsContentCollectionFile = GetFacePartsContentCollectionFile(facePartsFileNameExtension, d2FacePartsContentCollectionDirectory, mapping.MappingFromItem); + string? facePartsContentCollectionFile = GetFacePartsContentCollectionFile(facePartsFileNameExtension, d2FacePartsContentCollectionDirectory, keyMapping.MappingFromItem); if (facePartsContentCollectionFile is null || !File.Exists(facePartsContentCollectionFile)) result = null; else { - string checkFile = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}{facePartsFileNameExtension}"); + string checkFile = Path.Combine(directory, $"{keyMapping.MappingFromItem.ImageFileHolder.Name}{facePartsFileNameExtension}"); result = new(checkFile, directory, new(facePartsContentCollectionFile)); } - string facesDirectory = GetFacesDirectory(propertyConfiguration, dFacesContentDirectory, mapping.MappingFromItem); - FileHolder faceFileHolder = new(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}")); + string facesDirectory = GetFacesDirectory(propertyConfiguration, dFacesContentDirectory, keyMapping.MappingFromItem); + FileHolder faceFileHolder = new(Path.Combine(facesDirectory, $"{keyMapping.MappingFromLocation.DeterministicHashCodeKey}{keyMapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}")); if (!faceFileHolder.Exists) saveContainer = null; else { - string checkFile = Path.Combine(directory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}"); + string checkFile = Path.Combine(directory, $"{keyMapping.MappingFromLocation.DeterministicHashCodeKey}{keyMapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}"); saveContainer = new(checkFile, directory, faceFileHolder); } } @@ -1578,19 +1584,20 @@ internal abstract class MapLogic { isByMapping = mapping.By == Shared.Models.Stateless.IMapLogic.Mapping; isBySorting = mapping.By == Shared.Models.Stateless.IMapLogic.Sorting; + bool isDefaultName = mapping.MappingFromPerson is not null && IPerson.IsDefaultName(mapping.MappingFromPerson.DisplayDirectoryName); if (isBySorting && mapping.MappingFromPerson is null) by = saveIndividually ? nameof(Shared.Models.Stateless.IMapLogic.Individually) : $"{nameof(Shared.Models.Stateless.IMapLogic.Sorting)} Without Person"; else if (isBySorting && useFiltersCounter.HasValue) - by = $"{nameof(Shared.Models.Stateless.IMapLogic.Sorting)} Modified Filters - {useFiltersCounter.Value}"; + by = $"{nameof(Shared.Models.Stateless.IMapLogic.Sorting)}{(!isDefaultName ? "-A" : "-Z")} Modified Filters - {useFiltersCounter.Value}"; else { - by = mapping.By.Value switch + by = $"{mapping.By.Value switch { Shared.Models.Stateless.IMapLogic.Mapping => nameof(Shared.Models.Stateless.IMapLogic.Mapping), Shared.Models.Stateless.IMapLogic.Sorting => saveIndividually ? nameof(Shared.Models.Stateless.IMapLogic.Individually) : nameof(Shared.Models.Stateless.IMapLogic.Sorting), Shared.Models.Stateless.IMapLogic.ForceSingleImage => forceSingleImageHumanized, _ => throw new NotImplementedException() - }; + }}{(!isDefaultName ? "-A" : "-Z")}"; } } return new(by, isByMapping, isBySorting); @@ -1675,24 +1682,26 @@ internal abstract class MapLogic return new(results); } - internal static void SetCreationTime(MappingFromItem mappingFromItem, MappingFromPerson mappingFromPerson) + internal static string GetDecade(MappingFromItem mappingFromItem) { - DateTime dateTime; - FileInfo fileInfo; - foreach (string locationContainersFile in mappingFromPerson.LocationContainersFiles) + string result; + string year; + if (mappingFromItem.DateTimeOriginal is null) { - fileInfo = new(locationContainersFile); - if (!fileInfo.Exists) - continue; - dateTime = mappingFromItem.DateTimeOriginal is null ? mappingFromItem.MinimumDateTime : mappingFromItem.DateTimeOriginal.Value; - if (fileInfo.CreationTime != dateTime) - File.SetCreationTime(locationContainersFile, dateTime); + year = mappingFromItem.MinimumDateTime.Year.ToString(); + result = year[3] > '4' ? $"#{year[..3]}+" : $"#{year[..3]}-"; } + else + { + year = mappingFromItem.DateTimeOriginal.Value.Year.ToString(); + result = year[3] > '4' ? $"^{year[..3]}+" : $"^{year[..3]}-"; + } + return result; } - internal static void MoveToDecade(Property.Models.Configuration propertyConfiguration, MappingFromItem mappingFromItem, MappingFromPerson mappingFromPerson) + internal static void SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, MappingFromItem mappingFromItem, ReadOnlyCollection> locationContainers) { - string year; + DateTime dateTime; FileInfo fileInfo; string halfDecade; string checkDirectory; @@ -1702,12 +1711,17 @@ internal abstract class MapLogic string personNameDirectoryName; string? personKeyFormattedDirectory; string? personKeyFormattedDirectoryName; - foreach (string locationContainersFile in mappingFromPerson.LocationContainersFiles) + foreach (LocationContainer locationContainer in locationContainers) { - fileInfo = new(locationContainersFile); + fileInfo = new(locationContainer.File); if (!fileInfo.Exists) continue; - personNameDirectory = Path.GetDirectoryName(locationContainersFile); + dateTime = mappingFromItem.DateTimeOriginal is null ? mappingFromItem.MinimumDateTime : mappingFromItem.DateTimeOriginal.Value; + if (fileInfo.CreationTime != dateTime) + File.SetCreationTime(locationContainer.File, dateTime); + if (!moveToDecade) + continue; + personNameDirectory = Path.GetDirectoryName(locationContainer.File); if (string.IsNullOrEmpty(personNameDirectory)) continue; personNameDirectoryName = Path.GetFileName(personNameDirectory); @@ -1721,22 +1735,13 @@ internal abstract class MapLogic personKeyFormattedDirectoryName = Path.GetFileName(personKeyFormattedDirectory); if (personKeyFormattedDirectoryName.Length != propertyConfiguration.PersonBirthdayFormat.Length) break; - if (mappingFromItem.DateTimeOriginal is null) - { - year = mappingFromItem.MinimumDateTime.Year.ToString(); - halfDecade = year[3] > '4' ? $"#{year[..3]}+" : $"#{year[..3]}-"; - } - else - { - year = mappingFromItem.DateTimeOriginal.Value.Year.ToString(); - halfDecade = year[3] > '4' ? $"^{year[..3]}+" : $"^{year[..3]}-"; - } + halfDecade = GetDecade(mappingFromItem); if (halfDecade == yearDirectoryName) continue; checkDirectory = Path.Combine(personKeyFormattedDirectory, halfDecade, personNameDirectoryName); if (!Directory.Exists(checkDirectory)) _ = Directory.CreateDirectory(checkDirectory); - File.Move(locationContainersFile, Path.Combine(checkDirectory, Path.GetFileName(locationContainersFile))); + File.Move(locationContainer.File, Path.Combine(checkDirectory, Path.GetFileName(locationContainer.File))); } } @@ -1815,7 +1820,16 @@ internal abstract class MapLogic if (!wholePercentagesToPersonContainers.TryGetValue(mappingFromLocation.WholePercentages, out personContainers)) result = null; else - result = personContainers.Any(l => IPerson.IsDefaultName(l) && l.Key is not null && IPersonBirthday.IsCounterPersonYear(new DateTime(l.Key.Value).Year) && !jLinkResolvedPersonKeys.Contains(l.Key.Value)); + { + result = false; + foreach (PersonContainer personContainer in personContainers) + { + if (!IPerson.IsDefaultName(personContainer) || personContainer.Key is null || !IPersonBirthday.IsCounterPersonYear(new DateTime(personContainer.Key.Value).Year) || jLinkResolvedPersonKeys.Contains(personContainer.Key.Value)) + continue; + result = true; + break; + } + } } return result; } diff --git a/Map/Models/Stateless/Methods/IMapLogic.cs b/Map/Models/Stateless/Methods/IMapLogic.cs index c4b40d7..2a6e95f 100644 --- a/Map/Models/Stateless/Methods/IMapLogic.cs +++ b/Map/Models/Stateless/Methods/IMapLogic.cs @@ -35,19 +35,19 @@ public interface IMapLogic static List<(string, long)> GetJLinkDirectories(string genealogicalDataCommunicationFile, string[] jLinks, string personBirthdayFormat, char[] personCharacters, string a2PeopleSingletonDirectory, string a2PeopleContentDirectory) => MapLogic.GetJLinkDirectories(genealogicalDataCommunicationFile, jLinks, personBirthdayFormat, personCharacters, a2PeopleSingletonDirectory, a2PeopleContentDirectory); - void TestStatic_SetCreationTime(Shared.Models.MappingFromItem mappingFromItem, Shared.Models.MappingFromPerson mappingFromPerson) => - SetCreationTime(mappingFromItem, mappingFromPerson); - static void SetCreationTime(Shared.Models.MappingFromItem mappingFromItem, Shared.Models.MappingFromPerson mappingFromPerson) => - MapLogic.SetCreationTime(mappingFromItem, mappingFromPerson); - - void TestStatic_MoveToDecade(Property.Models.Configuration propertyConfiguration, Shared.Models.MappingFromItem mappingFromItem, Shared.Models.MappingFromPerson mappingFromPerson) => - MoveToDecade(propertyConfiguration, mappingFromItem, mappingFromPerson); - static void MoveToDecade(Property.Models.Configuration propertyConfiguration, Shared.Models.MappingFromItem mappingFromItem, Shared.Models.MappingFromPerson mappingFromPerson) => - MapLogic.MoveToDecade(propertyConfiguration, mappingFromItem, mappingFromPerson); + void TestStatic_SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, Shared.Models.MappingFromItem mappingFromItem, ReadOnlyCollection> locationContainers) => + SetCreationTimeMaybeMoveToDecade(propertyConfiguration, moveToDecade, mappingFromItem, locationContainers); + static void SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, Shared.Models.MappingFromItem mappingFromItem, ReadOnlyCollection> locationContainers) => + MapLogic.SetCreationTimeMaybeMoveToDecade(propertyConfiguration, moveToDecade, mappingFromItem, locationContainers); bool? TestStatic_CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary>? wholePercentagesToPersonContainers, Shared.Models.MappingFromLocation mappingFromLocation) => CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); static bool? CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary>? wholePercentagesToPersonContainers, Shared.Models.MappingFromLocation mappingFromLocation) => MapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); + string TestStatic_GetDecade(Shared.Models.MappingFromItem mappingFromItem) => + GetDecade(mappingFromItem); + static string GetDecade(Shared.Models.MappingFromItem mappingFromItem) => + MapLogic.GetDecade(mappingFromItem); + } \ No newline at end of file diff --git a/Shared/.kanbn/index.md b/Shared/.kanbn/index.md index 765e419..6f2158d 100644 --- a/Shared/.kanbn/index.md +++ b/Shared/.kanbn/index.md @@ -37,6 +37,7 @@ taskTemplate: '^+^_${overdue ? ''^R'' : ''''}${name}^: ${relations ? (''\n^-^/^g - [merge-kristy-files](tasks/merge-kristy-files.md) - [review-location-container-distance-tolerance](tasks/review-location-container-distance-tolerance.md) +- [can-re-map](tasks/can-re-map.md) ## Done diff --git a/Shared/.kanbn/tasks/can-re-map.md b/Shared/.kanbn/tasks/can-re-map.md new file mode 100644 index 0000000..81fd11d --- /dev/null +++ b/Shared/.kanbn/tasks/can-re-map.md @@ -0,0 +1,41 @@ +--- +created: 2023-09-06T01:48:53.593Z +updated: 2023-09-06T01:48:53.588Z +assigned: "" +progress: 0 +tags: [] +started: 2023-09-06T01:48:53.593Z +--- + +# CanReMap + +```csharp +DlibDotNet.GetMappingAndUpdateMappingFromPerson; +private (Mapping, int) GetMappingAndUpdateMappingFromPerson(MapLogic mapLogic, Item item, bool? isFocusRelativePath, MappingFromItem mappingFromItem) +// ... Done +E_Distance.PreFilterSetFaceDistances; +public static void PreFilterSetFaceDistances(int maxDegreeOfParallelism, long ticks, ReadOnlyCollection distinctFilteredFaces) +// ... Done +E_Distance.FilteredPostLoadFaceDistanceContainers; +public static FaceDistanceContainer[] FilteredPostLoadFaceDistanceContainers(Map.Models.MapLogic mapLogic, ReadOnlyCollection faceDistanceContainers, long? skipOlderThan, DistanceLimits distanceLimits) +// ... Done +E_Distance.SetFaceMappingSortingCollectionThenGetSortedSortingContainers +=> MapLogic.GetSortingCollection; +public List GetSortingCollection(int i, Face face, FaceDistance faceDistanceEncoding, List faceDistanceLengths) +// ... +MapLogic.GetFilterSortingContainers; +public ReadOnlyCollection GetFilterSortingContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyDictionary> idToWholePercentagesToMapping, Shared.Models.Methods.IDistanceLimits distanceLimits, ReadOnlyCollection sortingContainers) +// ... +E_Distance.SaveFaceDistances; +public static void SaveFaceDistances(Property.Models.Configuration configuration, ReadOnlyCollection sortingContainers) +// ... +MapLogic.UpdateFromSortingContainers; +public int UpdateFromSortingContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyDictionary> idToWholePercentagesToMapping, ReadOnlyCollection sortingContainers) +// ... +MapLogic.GetSaveContainers; +public List GetSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, ReadOnlyDictionary> idToWholePercentagesToMapping, Shared.Models.Methods.IDistanceLimits distanceLimits, int? useFiltersCounter, ReadOnlyCollection sortingContainers) +// ... +MapLogic.SaveContainers; +public void SaveContainers(int? updated, List saveContainers) +// ... +``` \ No newline at end of file diff --git a/Shared/Models/Mapping.cs b/Shared/Models/Mapping.cs index b4ab44b..cb2439c 100644 --- a/Shared/Models/Mapping.cs +++ b/Shared/Models/Mapping.cs @@ -1,4 +1,3 @@ -using System.Collections.ObjectModel; using System.Text.Json; using System.Text.Json.Serialization; @@ -15,7 +14,6 @@ public class Mapping : Properties.IMapping public MappingFromFilterPost MappingFromFilterPost { init; get; } public MappingFromFilterPre MappingFromFilterPre { init; get; } public MappingFromItem MappingFromItem { init; get; } - public MappingFromFilter MappingFromFilter { init; get; } public MappingFromLocation? MappingFromLocation { init; get; } public MappingFromPerson? MappingFromPerson => _MappingFromPerson; public List? MappingFromPhotoPrismCollection { init; get; } @@ -23,11 +21,10 @@ public class Mapping : Properties.IMapping public SortingContainer? SortingContainer => _SortingContainer; [JsonConstructor] - public Mapping(int? by, MappingFromFilter mappingFromFilter, MappingFromFilterPost mappingFromFilterPost, MappingFromFilterPre mappingFromFilterPre, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, MappingFromPerson? mappingFromPerson, List? mappingFromPhotoPrismCollection, string? segmentC, SortingContainer? sortingContainer) + public Mapping(int? by, MappingFromFilterPost mappingFromFilterPost, MappingFromFilterPre mappingFromFilterPre, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, MappingFromPerson? mappingFromPerson, List? mappingFromPhotoPrismCollection, string? segmentC, SortingContainer? sortingContainer) { _By = by; _SegmentC = segmentC; - MappingFromFilter = mappingFromFilter; MappingFromFilterPost = mappingFromFilterPost; MappingFromFilterPre = mappingFromFilterPre; MappingFromItem = mappingFromItem; @@ -37,8 +34,8 @@ public class Mapping : Properties.IMapping _SortingContainer = sortingContainer; } - public Mapping(MappingFromFilter mappingFromFilter, MappingFromFilterPost mappingFromFilterPost, MappingFromFilterPre mappingFromFilterPre, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, List? mappingFromPhotoPrismCollection) : - this(null, mappingFromFilter, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, null, mappingFromPhotoPrismCollection, null, null) + public Mapping(MappingFromFilterPost mappingFromFilterPost, MappingFromFilterPre mappingFromFilterPre, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, List? mappingFromPhotoPrismCollection) : + this(null, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, null, mappingFromPhotoPrismCollection, null, null) { } public override string ToString() @@ -54,19 +51,19 @@ public class Mapping : Properties.IMapping _SegmentC = !saveIndividually ? null : sortingContainer.Sorting.DistancePermyriad.ToString(); } - public void UpdateMappingFromPerson(ReadOnlyCollection locationContainersFiles, int? approximateYears, string displayDirectoryName, PersonBirthday personBirthday, string segmentB) + public void UpdateMappingFromPerson(int? approximateYears, string displayDirectoryName, long personKey, string segmentB) { _SortingContainer = null; _By = Stateless.IMapLogic.Mapping; - _MappingFromPerson = new(approximateYears, displayDirectoryName, locationContainersFiles, personBirthday, segmentB); + _MappingFromPerson = new(approximateYears, displayDirectoryName, personKey, segmentB); } - public void UpdateMappingFromPerson(int? approximateYears, string displayDirectoryName, PersonBirthday personBirthday, string segmentB, string segmentC, SortingContainer sortingContainer, ReadOnlyCollection locationContainersFiles) + public void UpdateMappingFromPerson(int? approximateYears, string displayDirectoryName, long personKey, string segmentB, string? segmentC, SortingContainer sortingContainer) { _SegmentC = segmentC; _By = Stateless.IMapLogic.Sorting; _SortingContainer = sortingContainer; - _MappingFromPerson = new(approximateYears, displayDirectoryName, locationContainersFiles, personBirthday, segmentB); + _MappingFromPerson = new(approximateYears, displayDirectoryName, personKey, segmentB); } } \ No newline at end of file diff --git a/Shared/Models/MappingFromPerson.cs b/Shared/Models/MappingFromPerson.cs index 2606220..a66bd80 100644 --- a/Shared/Models/MappingFromPerson.cs +++ b/Shared/Models/MappingFromPerson.cs @@ -1,4 +1,3 @@ -using System.Collections.ObjectModel; using System.Text.Json; using System.Text.Json.Serialization; @@ -6,8 +5,7 @@ namespace View_by_Distance.Shared.Models; public record MappingFromPerson(int? ApproximateYears, string DisplayDirectoryName, - ReadOnlyCollection LocationContainersFiles, - PersonBirthday PersonBirthday, + long PersonKey, string SegmentB) { diff --git a/Shared/Models/Properties/IMapping.cs b/Shared/Models/Properties/IMapping.cs index 9851d2f..16fdac4 100644 --- a/Shared/Models/Properties/IMapping.cs +++ b/Shared/Models/Properties/IMapping.cs @@ -6,7 +6,6 @@ public interface IMapping public int? By { get; } public MappingFromFilterPost MappingFromFilterPost { init; get; } public MappingFromFilterPre MappingFromFilterPre { init; get; } - public MappingFromItem MappingFromItem { init; get; } public MappingFromLocation? MappingFromLocation { init; get; } public MappingFromPerson? MappingFromPerson { get; } public List? MappingFromPhotoPrismCollection { init; get; } diff --git a/Shared/Models/Properties/ISorting.cs b/Shared/Models/Properties/ISorting.cs index 530fc6c..46e37e6 100644 --- a/Shared/Models/Properties/ISorting.cs +++ b/Shared/Models/Properties/ISorting.cs @@ -3,7 +3,7 @@ namespace View_by_Distance.Shared.Models.Properties; public interface ISorting { - public bool CanReMap { init; get; } + public bool? CanReMap { init; get; } public int DaysDelta { init; get; } public int DistancePermyriad { init; get; } public int Id { init; get; } diff --git a/Shared/Models/Properties/ISortingContainer.cs b/Shared/Models/Properties/ISortingContainer.cs index ec3d178..1c15685 100644 --- a/Shared/Models/Properties/ISortingContainer.cs +++ b/Shared/Models/Properties/ISortingContainer.cs @@ -3,7 +3,8 @@ namespace View_by_Distance.Shared.Models.Properties; public interface ISortingContainer { - public Mapping Mapping { init; get; } + public Mapping? Question { init; get; } public Sorting Sorting { init; get; } + public Mapping Source { init; get; } } \ No newline at end of file diff --git a/Shared/Models/Sorting.cs b/Shared/Models/Sorting.cs index 34695bb..5a05806 100644 --- a/Shared/Models/Sorting.cs +++ b/Shared/Models/Sorting.cs @@ -6,7 +6,7 @@ namespace View_by_Distance.Shared.Models; public record class Sorting : Properties.ISorting { - public bool CanReMap { init; get; } + public bool? CanReMap { init; get; } public int DaysDelta { init; get; } public int DistancePermyriad { init; get; } public int Id { init; get; } @@ -14,7 +14,7 @@ public record class Sorting : Properties.ISorting public int WholePercentages { init; get; } [JsonConstructor] - public Sorting(bool canReMap, int daysDelta, int distancePermyriad, int id, bool older, int wholePercentages) + public Sorting(bool? canReMap, int daysDelta, int distancePermyriad, int id, bool older, int wholePercentages) { CanReMap = canReMap; DaysDelta = daysDelta; @@ -25,7 +25,7 @@ public record class Sorting : Properties.ISorting } public Sorting(Mapping mapping, MappingFromLocation mappingFromLocation) : - this(false, 0, 0, mapping.MappingFromItem.Id, false, mappingFromLocation.WholePercentages) + this(null, 0, 0, mapping.MappingFromItem.Id, false, mappingFromLocation.WholePercentages) { } public override string ToString() diff --git a/Shared/Models/SortingContainer.cs b/Shared/Models/SortingContainer.cs index 44629b2..add3df6 100644 --- a/Shared/Models/SortingContainer.cs +++ b/Shared/Models/SortingContainer.cs @@ -5,19 +5,25 @@ namespace View_by_Distance.Shared.Models; public record class SortingContainer : Properties.ISortingContainer { - public Mapping Mapping { init; get; } + public Mapping? Question { init; get; } public Sorting Sorting { init; get; } + public Mapping Source { init; get; } [JsonConstructor] - public SortingContainer(Mapping mapping, Sorting sorting) + public SortingContainer(Mapping? question, Sorting sorting, Mapping source) { - Mapping = mapping; + Question = question; Sorting = sorting; + Source = source; } + public SortingContainer(Sorting sorting, Mapping source) : + this(null, sorting, source) + { } + public override string ToString() { - string result = string.Concat(Mapping.MappingFromItem.Id, '\t', Mapping.MappingFromLocation?.WholePercentages, '\t', Sorting.Id, '\t', Sorting.WholePercentages, '\t', Sorting.Older, '\t', '\t', Sorting.DistancePermyriad, '\t', Sorting.DaysDelta); + string result = string.Concat(Source.MappingFromItem.Id, '\t', Source.MappingFromLocation?.WholePercentages, '\t', Sorting.Id, '\t', Sorting.WholePercentages, '\t', Sorting.Older, '\t', '\t', Sorting.DistancePermyriad, '\t', Sorting.DaysDelta); return result; } diff --git a/Shared/Models/Stateless/Methods/IPersonBirthday.cs b/Shared/Models/Stateless/Methods/IPersonBirthday.cs index 09bd3b6..75a8166 100644 --- a/Shared/Models/Stateless/Methods/IPersonBirthday.cs +++ b/Shared/Models/Stateless/Methods/IPersonBirthday.cs @@ -16,6 +16,9 @@ public interface IPersonBirthday static bool IsCounterPersonBirthday(Models.PersonBirthday personBirthday) => personBirthday.Value.Year < 1809; + static bool IsCounterPersonYear(long personKey) => + new DateTime(personKey).Year < 1809; + static bool IsCounterPersonYear(int year) => year < 1809; diff --git a/Shared/Models/Stateless/Methods/ISortingContainer.cs b/Shared/Models/Stateless/Methods/ISortingContainer.cs index 0abc684..082c513 100644 --- a/Shared/Models/Stateless/Methods/ISortingContainer.cs +++ b/Shared/Models/Stateless/Methods/ISortingContainer.cs @@ -3,11 +3,11 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; public interface ISortingContainer { // ... - Models.SortingContainer[] TestStatic_Sort(List collection) => + List TestStatic_Sort(List collection) => Sort(collection); - static Models.SortingContainer[] Sort(List collection) => - (from l in collection orderby l.Sorting.DistancePermyriad select l).ToArray(); - static Models.SortingContainer[] SortUsingDaysDelta(List collection) => - (from l in collection orderby l.Sorting.DistancePermyriad, l.Sorting.DaysDelta select l).ToArray(); + static List Sort(List collection) => + (from l in collection orderby l.Sorting.DistancePermyriad select l).ToList(); + static List SortUsingDaysDelta(List collection) => + (from l in collection orderby l.Sorting.DistancePermyriad, l.Sorting.DaysDelta select l).ToList(); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/Sorting.cs b/Shared/Models/Stateless/Methods/Sorting.cs index cc67306..00ab595 100644 --- a/Shared/Models/Stateless/Methods/Sorting.cs +++ b/Shared/Models/Stateless/Methods/Sorting.cs @@ -15,8 +15,8 @@ internal abstract class Sorting TimeSpan timeSpan = new(faceDistanceLength.DateTimeOriginalThenMinimumDateTime.Ticks - faceDistanceEncoding.DateTimeOriginalThenMinimumDateTime.Ticks); bool older = timeSpan.TotalMilliseconds < 0; int daysDelta = (int)Math.Round(Math.Abs(timeSpan.TotalDays), 0); + bool? canReMap = faceDistanceLength.MappingFromFilterPost?.CanReMap; int distancePermyriad = (int)(faceDistanceLength.Length.Value * faceDistancePermyriad); - bool canReMap = faceDistanceLength.MappingFromFilterPost?.CanReMap is not null && faceDistanceLength.MappingFromFilterPost.CanReMap.Value; result = new(canReMap, daysDelta, distancePermyriad, faceDistanceLength.Id.Value, older, faceDistanceLength.WholePercentages.Value); return result; }