From dd2c51a0930d87e39e8de3e4c3d77f22e275f37a Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Mon, 10 Apr 2023 09:10:20 -0700 Subject: [PATCH] Individually with Explorer --- Instance/DlibDotNet.cs | 7 +- Instance/Models/Binder/Configuration.cs | 4 + Instance/Models/Configuration.cs | 9 +- Instance/appsettings.Development.json | 1 + Instance/appsettings.json | 1 + Map/Models/MapLogic.cs | 158 ++++++--------------- Map/Models/Stateless/MapLogic.cs | 175 +++++++++++++++++++++++- Shared/Models/Mapping.cs | 1 + 8 files changed, 231 insertions(+), 125 deletions(-) diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 8555f69..3875c54 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -765,9 +765,8 @@ public partial class DlibDotNet E_Distance.SaveFaceDistances(_Configuration.PropertyConfiguration, sortingContainers); if (filteredFaceDistanceContainers.Length > 0) { - bool forIndividually = true; - int updated = mapLogic.UpdateFromSortingContainers(distanceLimits, sortingContainers); - List saveContainers = mapLogic.GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, mappingCollection, idToNormalizedRectangleToMapping, useFiltersCounter, forIndividually, sortingContainers.Any()); + int updated = mapLogic.UpdateFromSortingContainers(_Configuration.SaveIndividually, distanceLimits, sortingContainers); + List saveContainers = mapLogic.GetSaveContainers(_Configuration.SaveIndividually, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, mappingCollection, idToNormalizedRectangleToMapping, useFiltersCounter, sortingContainers.Any()); mapLogic.SaveContainers(filteredFaceDistanceContainers.Length, updated, saveContainers); } } @@ -1058,7 +1057,7 @@ public partial class DlibDotNet fPhotoPrismContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), "()"); fPhotoPrismSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), "{}"); propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory); - MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _PersonContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); + MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Configuration.SaveIndividually, _MapConfiguration, _PersonContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") Building Container(s) - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index f5fbf64..5ca88b4 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -72,6 +72,7 @@ public class Configuration [Display(Name = "Save Full Year Of Random Files"), Required] public bool? SaveFullYearOfRandomFiles { get; set; } [Display(Name = "Save Mapped"), Required] public string[] SaveMappedForOutputResolutions { get; set; } [Display(Name = "Save Resized Images by Person Key Formatted"), Required] public string[] SaveFilteredOriginalImagesFromJLinksForOutputResolutions { get; set; } + [Display(Name = "Save For Individually"), Required] public bool? SaveIndividually { get; set; } [Display(Name = "Save Random For Output Resolutions"), Required] public string[] SaveRandomForOutputResolutions { get; set; } [Display(Name = "Save Resized Subfiles"), Required] public bool? SaveResizedSubfiles { get; set; } [Display(Name = "Save Shortcuts"), Required] public string[] SaveShortcutsForOutputResolutions { get; set; } @@ -203,6 +204,8 @@ public class Configuration throw new NullReferenceException(nameof(configuration.SaveFullYearOfRandomFiles)); configuration.SaveMappedForOutputResolutions ??= Array.Empty(); configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions ??= Array.Empty(); + if (configuration.SaveIndividually is null) + throw new NullReferenceException(nameof(configuration.SaveIndividually)); configuration.SaveRandomForOutputResolutions ??= Array.Empty(); if (configuration.SaveResizedSubfiles is null) throw new NullReferenceException(nameof(configuration.SaveResizedSubfiles)); @@ -284,6 +287,7 @@ public class Configuration configuration.SaveFaceDistancesForOutputResolutions, configuration.SaveFaceLandmarkForOutputResolutions, configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions, + configuration.SaveIndividually.Value, configuration.SaveFullYearOfRandomFiles.Value, configuration.SaveMappedForOutputResolutions, configuration.SaveRandomForOutputResolutions, diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index 356f90e..70bdd7e 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -66,6 +66,7 @@ public class Configuration public string[] SaveFaceDistancesForOutputResolutions { init; get; } public string[] SaveFaceLandmarkForOutputResolutions { init; get; } public string[] SaveFilteredOriginalImagesFromJLinksForOutputResolutions { init; get; } + public bool SaveIndividually { init; get; } public bool SaveFullYearOfRandomFiles { init; get; } public string[] SaveMappedForOutputResolutions { init; get; } public string[] SaveRandomForOutputResolutions { init; get; } @@ -141,6 +142,7 @@ public class Configuration string[] saveFaceDistancesForOutputResolutions, string[] saveFaceLandmarkForOutputResolutions, string[] saveFilteredOriginalImagesFromJLinksForOutputResolutions, + bool saveIndividually, bool saveFullYearOfRandomFiles, string[] saveMappedForOutputResolutions, string[] saveRandomForOutputResolutions, @@ -208,17 +210,18 @@ public class Configuration PropertiesChangedForMetadata = propertiesChangedForMetadata; PropertiesChangedForResize = propertiesChangedForResize; RangeDaysDeltaTolerance = rangeDaysDeltaTolerance; + RangeDistanceTolerance = rangeDistanceTolerance; RangeFaceAreaTolerance = rangeFaceAreaPermyriadTolerance; RangeFaceConfidence = rangeFaceConfidence; - RangeDistanceTolerance = rangeDistanceTolerance; Reverse = reverse; SaveFaceDistancesForOutputResolutions = saveFaceDistancesForOutputResolutions; SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions; + SaveFilteredOriginalImagesFromJLinksForOutputResolutions = saveFilteredOriginalImagesFromJLinksForOutputResolutions; + SaveIndividually = saveIndividually; SaveFullYearOfRandomFiles = saveFullYearOfRandomFiles; SaveMappedForOutputResolutions = saveMappedForOutputResolutions; - SaveFilteredOriginalImagesFromJLinksForOutputResolutions = saveFilteredOriginalImagesFromJLinksForOutputResolutions; - SaveResizedSubfiles = saveResizedSubfiles; SaveRandomForOutputResolutions = saveRandomForOutputResolutions; + SaveResizedSubfiles = saveResizedSubfiles; SaveShortcutsForOutputResolutions = saveShortcutsForOutputResolutions; SaveSortingWithoutPerson = saveSortingWithoutPerson; SkipNotSkipDirectories = skipNotSkipDirectories; diff --git a/Instance/appsettings.Development.json b/Instance/appsettings.Development.json index faa650f..26c090e 100644 --- a/Instance/appsettings.Development.json +++ b/Instance/appsettings.Development.json @@ -29,6 +29,7 @@ "xxxRootDirectory": "D:/2) Images B/Not-Copy-Copy-9b89679", "RootDirectory": "D:/1) Images A/Images-9b89679", "xxxxxRootDirectory": "D:/1) Images A/Images-9b89679/Facebook/2023.2 Facebook", + "SaveIndividually": true, "SaveSortingWithoutPerson": true, "SkipOlderThanDays": null, "xSkipOlderThanDays": 2200, diff --git a/Instance/appsettings.json b/Instance/appsettings.json index 647b6de..30c2ce8 100644 --- a/Instance/appsettings.json +++ b/Instance/appsettings.json @@ -106,6 +106,7 @@ "ResultSingleton": "{}", "Reverse": false, "RootDirectory": "D:/Images", + "SaveIndividually": false, "SaveFullYearOfRandomFiles": true, "SaveResizedSubFiles": true, "SaveSortingWithoutPerson": false, diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index 0b576b3..743b6b2 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -28,7 +28,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic private readonly string _EDistanceContentTicksDirectory; private readonly Shared.Models.Properties.IPropertyConfiguration _PropertyConfiguration; - public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, PersonContainer[] personContainers, long ticks, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) + public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, bool saveIndividually, Configuration? configuration, PersonContainer[] personContainers, long ticks, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) { _Ticks = ticks; _Configuration = configuration; @@ -51,15 +51,16 @@ public class MapLogic : Shared.Models.Methods.IMapLogic string? rootDirectoryParent = Path.GetDirectoryName(propertyConfiguration.RootDirectory); string eDistanceContentTicksDirectory = Path.Combine(eDistanceContentDirectory, $"({ticks})"); Dictionary> idThenNormalizedRectangleToPersonContainers = new(); - for (int i = 1; i < 5; i++) + if (!saveIndividually) + { + for (int i = 1; i < 5; i++) + _ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory); _ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory); - _ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory); + } if (string.IsNullOrEmpty(rootDirectoryParent)) throw new NullReferenceException(nameof(rootDirectoryParent)); if (!Directory.Exists(eDistanceContentDirectory)) _ = Directory.CreateDirectory(eDistanceContentDirectory); - if (!Directory.Exists(eDistanceContentTicksDirectory)) - _ = Directory.CreateDirectory(eDistanceContentTicksDirectory); if (configuration is not null) { List personContainerCollection = new(personContainers); @@ -335,40 +336,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return result; } - private static (string, bool, bool) Get(int? useFiltersCounter, bool forIndividually, bool sortingContainersAny, string forceSingleImageHumanized, Mapping mapping) - { - string by; - bool isByMapping; - bool isBySorting; - if (mapping.By is null) - { - isByMapping = false; - isBySorting = !sortingContainersAny; - by = $"{nameof(Shared.Models.Stateless.IMapLogic.Mapping)}Null"; - } - else - { - isByMapping = mapping.By == Shared.Models.Stateless.IMapLogic.Mapping; - isBySorting = mapping.By == Shared.Models.Stateless.IMapLogic.Sorting; - if (isBySorting && mapping.MappingFromPerson is null) - by = forIndividually ? 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}"; - else - { - by = mapping.By.Value switch - { - Shared.Models.Stateless.IMapLogic.Mapping => nameof(Shared.Models.Stateless.IMapLogic.Mapping), - Shared.Models.Stateless.IMapLogic.Sorting => forIndividually ? nameof(Shared.Models.Stateless.IMapLogic.Individually) : nameof(Shared.Models.Stateless.IMapLogic.Sorting), - Shared.Models.Stateless.IMapLogic.ForceSingleImage => forceSingleImageHumanized, - _ => throw new NotImplementedException() - }; - } - } - return new(by, isByMapping, isBySorting); - } - - private string GetDirectory(string by, MappingFromItem mappingFromItem, SortingContainer sortingContainer) + private string GetDirectory(bool saveIndividually, int padLeft, string? segmentC, string by, MappingFromItem mappingFromItem, SortingContainer sortingContainer) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -387,19 +355,23 @@ public class MapLogic : Shared.Models.Methods.IMapLogic personBirthday = personContainer.Birthdays[zero]; mappingSegmentB = Stateless.MapLogic.GetMappingSegmentB(_Ticks, personBirthday, personContainer.ApproximateYears, mappingFromItem); personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personBirthday); - result = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, mappingSegmentB); + if (!saveIndividually || segmentC is null) + result = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, mappingSegmentB); + else + result = Path.Combine(_EDistanceContentTicksDirectory, by, segmentC.PadLeft(padLeft, '0'), personKeyFormatted, mappingSegmentB); _NotMappedPersonContainers.RemoveAt(i); break; } return result; } - private List GetSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, Mapping[] mappingCollection, Dictionary> idToNormalizedRectangleToMapping, Dictionary> personKeyToIds, int? useFiltersCounter, bool saveMapped, bool forIndividually, bool sortingContainersAny) + private List GetSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, Mapping[] mappingCollection, Dictionary> idToNormalizedRectangleToMapping, Dictionary> personKeyToIds, int? useFiltersCounter, bool saveMapped, bool saveIndividually, bool sortingContainersAny) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); List results = new(); string by; + long ticks; List? ids; long personKey; bool isByMapping; @@ -420,6 +392,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic FileHolder hiddenFaceFileHolder; string? facePartsContentCollectionFile; Dictionary? normalizedRectangleToMapping; + int padLeft = _Configuration.FaceDistancePermyriad.ToString().Length; string forceSingleImageHumanized = nameof(Shared.Models.Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title); foreach (Mapping mapping in mappingCollection) { @@ -430,7 +403,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic throw new NotSupportedException(); if (mapping.MappingFromFilter.InSkipCollection is not null && mapping.MappingFromFilter.InSkipCollection.Value) continue; - (by, isByMapping, isBySorting) = Get(useFiltersCounter, forIndividually, sortingContainersAny, forceSingleImageHumanized, mapping); + (by, isByMapping, isBySorting) = Stateless.MapLogic.Get(useFiltersCounter, saveIndividually, sortingContainersAny, forceSingleImageHumanized, mapping); if (isByMapping && !saveMapped) continue; if (mapping.MappingFromPerson is null) @@ -449,10 +422,14 @@ public class MapLogic : Shared.Models.Methods.IMapLogic continue; if (distinct.Contains(mapping.SortingContainer.Sorting.Id)) continue; - directory = GetDirectory(by, mapping.MappingFromItem, mapping.SortingContainer); - personDirectory = Path.Combine(directory, $"Z]{DateTime.Now.Ticks}"); - if (forIndividually) + ticks = DateTime.Now.Ticks; + directory = GetDirectory(saveIndividually, padLeft, mapping.SegmentC, by, mapping.MappingFromItem, mapping.SortingContainer); + personDirectory = Path.Combine(directory, $"Z]{ticks}"); + if (saveIndividually) + { directory = Path.Combine(directory, mapping.MappingFromItem.Id.ToString()); + results.Add(new(Path.Combine(directory, $"Z]{ticks}"))); + } distinct.Add(mapping.MappingFromItem.Id); distinct.Add(mapping.SortingContainer.Sorting.Id); } @@ -464,8 +441,10 @@ public class MapLogic : Shared.Models.Methods.IMapLogic throw new NotSupportedException(); personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks; personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday); - if (forIndividually || string.IsNullOrEmpty(mapping.SegmentC)) + 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) @@ -474,16 +453,15 @@ public class MapLogic : Shared.Models.Methods.IMapLogic personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName, "lnk"); else personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName[..1], "lnk"); - if (forIndividually) - directory = Path.Combine(directory, mapping.MappingFromItem.Id.ToString()); - if (isByMapping && personKeyToIds.TryGetValue(personKey, out ids)) + if (saveIndividually) { - saveContainer = new(Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName, $"{ids.Count} Face(s)")); - results.Add(saveContainer); + directory = Path.Combine(directory, mapping.MappingFromItem.Id.ToString()); + results.Add(new(Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName))); } + if (isByMapping && personKeyToIds.TryGetValue(personKey, out ids)) + results.Add(new(Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName, $"{ids.Count} Face(s)"))); } - saveContainer = new(personDirectory); - results.Add(saveContainer); + results.Add(new(personDirectory)); if (!isBySorting || mapping.SortingContainer is null) keyMapping = null; else @@ -496,10 +474,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic if (keyMapping.MappingFromLocation is null) continue; if (keyMapping.MappingFromLocation.NormalizedRectangle == mapping.MappingFromLocation.NormalizedRectangle) - { - saveContainer = new(Path.Combine(directory, "Maybe")); - results.Add(saveContainer); - } + results.Add(new(Path.Combine(directory, "Maybe"))); } facesDirectory = Stateless.MapLogic.GetFacesDirectory(dFacesContentDirectory, mapping.MappingFromItem); if (facesDirectory is null) @@ -514,7 +489,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic } else { - if (forIndividually) + if (saveIndividually) { facePartsContentCollectionFile = Stateless.MapLogic.GetFacePartsContentCollectionFile(_Configuration.FacePartsFileNameExtension, d2FacePartsContentCollectionDirectory, mapping.MappingFromItem); if (facePartsContentCollectionFile is null) @@ -537,13 +512,13 @@ public class MapLogic : Shared.Models.Methods.IMapLogic results.Add(saveContainer); if (!isBySorting || mapping.SortingContainer is null || keyMapping is null) continue; - if (!forIndividually && isBySorting && mapping.MappingFromPerson is null) + if (!saveIndividually && isBySorting && mapping.MappingFromPerson is null) { saveContainer = GetMatchSaveContainer(dFacesContentDirectory, d2FacePartsContentDirectory, directory, keyMapping); if (saveContainer is not null) results.Add(saveContainer); } - if (!forIndividually) + if (!saveIndividually) saveContainer = Stateless.MapLogic.GetDebugSaveContainer(directory, mapping.SortingContainer, keyMapping); else { @@ -557,14 +532,14 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return results; } - public List GetSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, Mapping[] mappingCollection, Dictionary> idToNormalizedRectangleToMapping, int? useFiltersCounter, bool forIndividually, bool sortingContainersAny) + public List GetSaveContainers(bool saveIndividually, string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, Mapping[] mappingCollection, Dictionary> idToNormalizedRectangleToMapping, int? useFiltersCounter, bool sortingContainersAny) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); List results; bool saveMapped = false; Dictionary> personKeyToIds = new(); - results = GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, mappingCollection, idToNormalizedRectangleToMapping, personKeyToIds, useFiltersCounter, saveMapped, forIndividually, sortingContainersAny); + results = GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, mappingCollection, idToNormalizedRectangleToMapping, personKeyToIds, useFiltersCounter, saveMapped, saveIndividually, sortingContainersAny); return results; } @@ -576,7 +551,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic bool saveMapped = true; int? useFiltersCounter = null; string mappingDirectory = Path.Combine(_EDistanceContentTicksDirectory, nameof(Shared.Models.Stateless.IMapLogic.Mapping)); - List saveContainers = GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, mappingCollection, idToNormalizedRectangleToMapping, personKeyToIds, useFiltersCounter, saveMapped, sortingContainersAny: true, forIndividually: false); + List saveContainers = GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, mappingCollection, idToNormalizedRectangleToMapping, personKeyToIds, useFiltersCounter, saveMapped, sortingContainersAny: true, saveIndividually: false); SaveContainers(totalNotMapped, updated, saveContainers); if (!string.IsNullOrEmpty(_EDistanceContentTicksDirectory) && Directory.Exists(mappingDirectory)) Stateless.MapLogic.SaveMappingShortcuts(mappingDirectory); @@ -643,7 +618,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return results; } - public int UpdateFromSortingContainers(Shared.Models.Methods.IDistanceLimits distanceLimits, SortingContainer[] sortingContainers) + public int UpdateFromSortingContainers(bool saveIndividually, Shared.Models.Methods.IDistanceLimits distanceLimits, SortingContainer[] sortingContainers) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -710,7 +685,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic if (!keyToSegmentC.ContainsKey(key)) keyToSegmentC.Add(key, string.Empty); keyToCount[key]++; - if (keyToCount[key] > _Configuration.SortingMaximumPerKey) + if (saveIndividually || keyToCount[key] > _Configuration.SortingMaximumPerKey) { keyToCount[key] = 0; keyToSegmentC[key] = sortingContainer.Sorting.DistancePermyriad.ToString(); @@ -1037,64 +1012,13 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return results; } - private static bool TryToFind(string a2PeopleSingletonDirectory, string file, string path) - { - bool result = false; - string? pathName = Path.GetFileName(path); - string? group = Path.GetDirectoryName(path); - string? groupName = Path.GetFileName(group); - if (pathName is not null && group is not null && groupName is not null) - { - WindowsShortcut windowsShortcut; - string checkDirectory = Path.Combine(a2PeopleSingletonDirectory, groupName, pathName); - if (Directory.Exists(checkDirectory)) - { - try - { - windowsShortcut = new() { Path = checkDirectory }; - windowsShortcut.Save(file); - windowsShortcut.Dispose(); - result = true; - } - catch (Exception) - { } - } - } - return result; - } - - private static void BeforeSaveFilteredOriginalImagesFromJLinks(string[] jLinks, string a2PeopleContentDirectory) - { - string[] files; - string checkDirectory; - WindowsShortcut windowsShortcut; - foreach (string directoryName in jLinks) - { - checkDirectory = Path.Combine(a2PeopleContentDirectory, directoryName); - if (!Directory.Exists(checkDirectory)) - continue; - files = Directory.GetFiles(checkDirectory, "*.lnk", SearchOption.TopDirectoryOnly); - foreach (string file in files) - { - windowsShortcut = WindowsShortcut.Load(file); - if (windowsShortcut.Path is null) - continue; - if (!Directory.Exists(windowsShortcut.Path)) - { - if (!TryToFind(a2PeopleContentDirectory, file, windowsShortcut.Path)) - continue; - } - } - } - } - public void SaveFilteredOriginalImagesFromJLinks(string[] jLinks, PersonContainer[] personContainers, string a2PeopleContentDirectory, Dictionary> personKeyToIds, Mapping[] mappingCollection, int totalNotMapped) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); SaveContainer? saveContainer; List saveContainers = new(); - BeforeSaveFilteredOriginalImagesFromJLinks(jLinks, a2PeopleContentDirectory); + Stateless.MapLogic.BeforeSaveFilteredOriginalImagesFromJLinks(jLinks, a2PeopleContentDirectory); (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) { diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index ea2c3fc..eedef17 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -87,6 +87,90 @@ internal abstract class MapLogic } } + private static void MoveTo(string actionDirectory, string ticksDirectory, string directory, string personKeyFormatted, string yearDirectoryName, string alphaDirectoryName, string[] files, string[] matchFaceFile) + { + string checkFile; + string actionDirectoryName = Path.GetFileName(actionDirectory); + string checkDirectory = actionDirectoryName.StartsWith("y", StringComparison.CurrentCultureIgnoreCase) ? Path.Combine(ticksDirectory, personKeyFormatted, yearDirectoryName, alphaDirectoryName) : Path.Combine(directory, actionDirectoryName); + if (!Directory.Exists(checkDirectory)) + _ = Directory.CreateDirectory(checkDirectory); + foreach (string file in files) + { + if (matchFaceFile.Contains(file)) + { + checkFile = Path.Combine(checkDirectory, Path.GetFileName(file)); + if (File.Exists(checkFile)) + continue; + File.Move(file, checkFile); + continue; + } + File.Delete(file); + } + } + + private static void Individually(Configuration configuration, string ticksDirectory, string directory) + { + string[] files; + FileInfo[] collection; + string[] matchFaceFile; + string yearDirectoryName; + string[] yearDirectories; + string alphaDirectoryName; + string matchDirectoryName; + string personKeyFormatted; + string[] alphaDirectories; + string[] matchDirectories; + string[] actionDirectories; + string personDisplayDirectory; + string[] personKeyDirectories; + string[] segmentCDirectories = Directory.GetDirectories(directory, "*", SearchOption.TopDirectoryOnly); + foreach (string segmentCDirectory in segmentCDirectories) + { + personKeyDirectories = Directory.GetDirectories(segmentCDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string personKeyDirectory in personKeyDirectories) + { + personKeyFormatted = Path.GetFileName(personKeyDirectory); + yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string yearDirectory in yearDirectories) + { + yearDirectoryName = Path.GetFileName(yearDirectory); + matchDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly); + alphaDirectories = matchDirectories.Where(l => !long.TryParse(Path.GetFileName(l), out long a)).ToArray(); + if (!alphaDirectories.Any()) + continue; + foreach (string matchDirectory in matchDirectories) + { + matchDirectoryName = Path.GetFileName(matchDirectory); + files = Directory.GetFiles(matchDirectory, "*", SearchOption.TopDirectoryOnly); + if (files.Length != 4) + continue; + collection = files.Select(l => new FileInfo(l)).ToArray(); + matchFaceFile = (from l in collection where l.Extension == configuration.FacesFileNameExtension && l.Name.Contains(matchDirectoryName) select l.FullName).ToArray(); + if (!matchFaceFile.Any()) + continue; + alphaDirectoryName = Path.GetFileName(alphaDirectories[0]); + personDisplayDirectory = Path.Combine(matchDirectory, alphaDirectoryName); + if (!Directory.Exists(personDisplayDirectory) || !Directory.Exists(matchDirectory)) + continue; + if (matchDirectory.Contains('=')) + continue; + _ = System.Diagnostics.Process.Start("explorer", matchDirectory); + for (int i = 0; i < int.MaxValue; i++) + { + Thread.Sleep(500); + actionDirectories = Directory.GetDirectories(matchDirectory, "*", SearchOption.TopDirectoryOnly).Where(l => l != personDisplayDirectory && !l.EndsWith("Maybe")).ToArray(); + if (actionDirectories.Any()) + { + MoveTo(actionDirectories[0], ticksDirectory, directory, personKeyFormatted, yearDirectoryName, alphaDirectoryName, files, matchFaceFile); + break; + } + } + } + } + } + } + } + internal static List<(string, string[], string)> DeleteEmptyDirectoriesAndGetCollection(Configuration configuration, List personKeyFormattedCollection, string[] ticksDirectories, string message) { List<(string, string[], string)> results = new(); @@ -118,7 +202,12 @@ internal abstract class MapLogic foreach (string personKeyDirectory in personKeyDirectories) { personKeyFormatted = Path.GetFileName(personKeyDirectory); - isReservedDirectoryName = personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Sorting)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Mapping)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.ManualCopy)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Individually)); + if (personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Individually))) + { + Individually(configuration, ticksDirectory, personKeyDirectory); + break; + } + isReservedDirectoryName = personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Sorting)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Mapping)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.ManualCopy)); yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string yearDirectory in yearDirectories) { @@ -856,4 +945,88 @@ internal abstract class MapLogic return results; } + private static bool TryToFind(string a2PeopleSingletonDirectory, string file, string path) + { + bool result = false; + string? pathName = Path.GetFileName(path); + string? group = Path.GetDirectoryName(path); + string? groupName = Path.GetFileName(group); + if (pathName is not null && group is not null && groupName is not null) + { + WindowsShortcut windowsShortcut; + string checkDirectory = Path.Combine(a2PeopleSingletonDirectory, groupName, pathName); + if (Directory.Exists(checkDirectory)) + { + try + { + windowsShortcut = new() { Path = checkDirectory }; + windowsShortcut.Save(file); + windowsShortcut.Dispose(); + result = true; + } + catch (Exception) + { } + } + } + return result; + } + + internal static void BeforeSaveFilteredOriginalImagesFromJLinks(string[] jLinks, string a2PeopleContentDirectory) + { + string[] files; + string checkDirectory; + WindowsShortcut windowsShortcut; + foreach (string directoryName in jLinks) + { + checkDirectory = Path.Combine(a2PeopleContentDirectory, directoryName); + if (!Directory.Exists(checkDirectory)) + continue; + files = Directory.GetFiles(checkDirectory, "*.lnk", SearchOption.TopDirectoryOnly); + foreach (string file in files) + { + windowsShortcut = WindowsShortcut.Load(file); + if (windowsShortcut.Path is null) + continue; + if (!Directory.Exists(windowsShortcut.Path)) + { + if (!TryToFind(a2PeopleContentDirectory, file, windowsShortcut.Path)) + continue; + } + } + } + } + + internal static (string, bool, bool) Get(int? useFiltersCounter, bool saveIndividually, bool sortingContainersAny, string forceSingleImageHumanized, Mapping mapping) + { + string by; + bool isByMapping; + bool isBySorting; + if (mapping.By is null) + { + isByMapping = false; + isBySorting = !sortingContainersAny; + by = $"{nameof(Shared.Models.Stateless.IMapLogic.Mapping)}Null"; + } + else + { + isByMapping = mapping.By == Shared.Models.Stateless.IMapLogic.Mapping; + isBySorting = mapping.By == Shared.Models.Stateless.IMapLogic.Sorting; + 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}"; + else + { + 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() + }; + } + } + return new(by, isByMapping, isBySorting); + } + } \ No newline at end of file diff --git a/Shared/Models/Mapping.cs b/Shared/Models/Mapping.cs index 8a04b18..5aa986c 100644 --- a/Shared/Models/Mapping.cs +++ b/Shared/Models/Mapping.cs @@ -182,6 +182,7 @@ public class Mapping : Properties.IMapping { _By = Stateless.IMapLogic.Sorting; _SortingContainer = sortingContainer; + _SegmentC = sortingContainer.Sorting.DistancePermyriad.ToString(); } public void UpdateMappingFromPerson(int? approximateYears, string displayDirectoryName, PersonBirthday personBirthday, string segmentB)