using Humanizer; using ShellProgressBar; using System.Collections.ObjectModel; using System.Diagnostics; using System.Drawing; using System.Text.Json; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Stateless.Methods; using WindowsShortcutFactory; namespace View_by_Distance.Map.Models.Stateless; internal abstract class MapLogic { private static void SetPersonCollections(Configuration configuration, ReadOnlyCollection personContainers, string? a2PeopleSingletonDirectory, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List personKeyFormattedCollection, Dictionary> skipCollection, Dictionary> skipNotSkipCollection) { int? id; int? normalizedRectangle; string personKeyFormatted; string newestPersonKeyFormatted; bool skipNotSkipDirectoriesAny = configuration.SkipNotSkipDirectories.Any(); string[] checkDirectories = (from l in configuration.SkipNotSkipDirectories select Path.GetFullPath(string.Concat(a2PeopleSingletonDirectory, l))).ToArray(); foreach (PersonContainer personContainer in personContainers) { foreach (string personDisplayDirectoryAllFile in personContainer.DisplayDirectoryAllFiles) { if (!personDisplayDirectoryAllFile.EndsWith(configuration.FacesFileNameExtension)) continue; (id, normalizedRectangle) = IMapping.GetConverted(configuration.FacesFileNameExtension, personDisplayDirectoryAllFile); if (id is null || normalizedRectangle is null) continue; if (!skipNotSkipDirectoriesAny || !checkDirectories.Any(l => personDisplayDirectoryAllFile.StartsWith(l))) { if (!skipCollection.ContainsKey(id.Value)) skipCollection.Add(id.Value, new()); skipCollection[id.Value].Add(normalizedRectangle.Value); } else { if (!skipNotSkipCollection.ContainsKey(id.Value)) skipNotSkipCollection.Add(id.Value, new()); skipNotSkipCollection[id.Value].Add(normalizedRectangle.Value); } } if (personContainer.Person is null || personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) continue; foreach (PersonBirthday personBirthday in personContainer.Birthdays) { personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personBirthday); personKeyFormattedCollection.Add(personKeyFormatted); if (personContainer.Birthdays.Length < 1) continue; newestPersonKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personContainer.Key.Value); if (!personKeyFormattedToNewestPersonKeyFormatted.ContainsKey(personKeyFormatted)) personKeyFormattedToNewestPersonKeyFormatted.Add(personKeyFormatted, newestPersonKeyFormatted); } } } private static void MoveTo(string actionDirectory, string ticksDirectory, string directory, string personKeyFormatted, string yearDirectoryName, string alphaDirectoryName, string[] files, string[] facesFileNames) { 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 (facesFileNames.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[] facesFileNames; 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); if (yearDirectoryName.StartsWith('=')) Directory.Move(yearDirectory, yearDirectory.Replace('=', '~')); } 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; alphaDirectoryName = Path.GetFileName(alphaDirectories[0]); 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(); if (IPerson.IsDefaultName(configuration.MappingDefaultName, alphaDirectoryName)) facesFileNames = (from l in collection where l.Extension == configuration.FacesFileNameExtension select l.FullName).ToArray(); else facesFileNames = (from l in collection where l.Extension == configuration.FacesFileNameExtension && l.Name.Contains(matchDirectoryName) select l.FullName).ToArray(); if (!facesFileNames.Any()) continue; personDisplayDirectory = Path.Combine(matchDirectory, alphaDirectoryName); if (!Directory.Exists(personDisplayDirectory) || !Directory.Exists(matchDirectory)) continue; _ = 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, facesFileNames); break; } } } } } } } internal static List<(string, string[], string)> DeleteEmptyDirectoriesAndGetCollection(Configuration configuration, List personKeyFormattedCollection, string[] ticksDirectories, string message) { List<(string, string[], string)> results = new(); int? id; string[] files; string fileName; const int zero = 0; string[] yearDirectories; int? normalizedRectangle; string personKeyFormatted; string ticksDirectoryName; string? personFirstInitial; bool isReservedDirectoryName; List distinct = new(); string[] personKeyDirectories; string[] personNameDirectories; string[] personNameLinkDirectories; string? personFirstInitialDirectory; string[] personDisplayDirectoryNames; string manualCopyHumanized = nameof(Shared.Models.Stateless.IMapLogic.ManualCopy).Humanize(LetterCasing.Title); string forceSingleImageHumanized = nameof(Shared.Models.Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title); ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using ProgressBar progressBar = new(ticksDirectories.Length, message, options); foreach (string ticksDirectory in ticksDirectories) { progressBar.Tick(); ticksDirectoryName = Path.GetFileName(ticksDirectory); if (ticksDirectoryName.Length < 3 || ticksDirectoryName[zero] != '(' || ticksDirectoryName[^1] != ')') continue; personKeyDirectories = Directory.GetDirectories(ticksDirectory, "*", SearchOption.TopDirectoryOnly); 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)); if (!isReservedDirectoryName && personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Individually))) { Individually(configuration, ticksDirectory, personKeyDirectory); throw new Exception($"B) Move personKey directories up one from {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} and delete {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} directory!"); } yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string yearDirectory in yearDirectories) { files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly); personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string file in files) File.Delete(file); foreach (string personNameDirectory in personNameDirectories) { personDisplayDirectoryNames = IPath.GetDirectoryNames(personNameDirectory); if (!personDisplayDirectoryNames.Any()) continue; files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly); if (isReservedDirectoryName && files.Any()) throw new Exception($"Move personKey directories up one from {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} and delete {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} directory!"); if (personKeyFormatted == manualCopyHumanized && files.Any()) throw new Exception($"Move personKey directories up one from {manualCopyHumanized} and delete {manualCopyHumanized} directory!"); if (personKeyFormatted == forceSingleImageHumanized && files.Any()) throw new Exception($"Move personKey directories up one from {forceSingleImageHumanized} and delete {forceSingleImageHumanized} directory!"); if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length) continue; if (personDisplayDirectoryNames[^1].Length == 1 || IPerson.IsDefaultName(configuration.MappingDefaultName, personDisplayDirectoryNames[^1]) || !personKeyFormattedCollection.Contains(personKeyFormatted)) personFirstInitialDirectory = personNameDirectory; else { personFirstInitial = personDisplayDirectoryNames[^1][..1]; if (personFirstInitial.All(l => char.IsDigit(l))) { foreach (string file in files) File.Delete(file); files = Directory.GetFiles(personNameDirectory, "*", SearchOption.AllDirectories); foreach (string file in files) File.Delete(file); _ = IPath.DeleteEmptyDirectories(personNameDirectory); continue; } personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial.ToString()); if (Directory.Exists(personFirstInitialDirectory)) throw new Exception("Forgot to ..."); Directory.Move(personNameDirectory, personFirstInitialDirectory); files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); } foreach (string file in files) { if (file.EndsWith(".lnk")) continue; (id, normalizedRectangle) = IMapping.GetConverted(configuration.FacesFileNameExtension, file); if (id is null || normalizedRectangle is null) continue; fileName = Path.GetFileName(file); if (distinct.Contains(fileName)) { if (!File.Exists($"{file}.dup")) File.Move(file, $"{file}.dup"); continue; } distinct.Add(fileName); results.Add(new(personKeyFormatted, personDisplayDirectoryNames, file)); } personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string personNameLinkDirectory in personNameLinkDirectories) { files = Directory.GetFiles(personNameLinkDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string file in files) { if (!file.EndsWith(".lnk")) continue; File.Delete(file); } _ = IPath.DeleteEmptyDirectories(personNameLinkDirectory); } _ = IPath.DeleteEmptyDirectories(personFirstInitialDirectory); } _ = IPath.DeleteEmptyDirectories(yearDirectory); } _ = IPath.DeleteEmptyDirectories(personKeyDirectory); } _ = IPath.DeleteEmptyDirectories(ticksDirectory); _ = IPath.DeleteEmptyDirectories(ticksDirectory); } return results; } private static PersonContainer[] GetDistinctPersonContainers(List personContainers) { List results = new(); List distinctCheck = new(); foreach (PersonContainer personContainer in personContainers) { if (personContainer.Key is null || distinctCheck.Contains(personContainer.Key.Value)) continue; results.Add(personContainer); } return results.ToArray(); } private static void SetKeyValuePairs(Configuration configuration, ReadOnlyCollection personContainers, Dictionary> personKeyToPersonContainerCollection, Dictionary personKeyFormattedToPersonContainer, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection, Dictionary personKeyToPersonContainer, Dictionary> idThenNormalizedRectangleToPersonContainers, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) { PersonBirthday? personBirthday; PersonContainer[] distinctPersonContainers; (long, PersonContainer)[] collection = GetDistinctCollection(configuration, personContainers, personKeyToPersonContainerCollection, personKeyFormattedToPersonContainer); foreach ((long personKey, PersonContainer personContainer) in collection) personKeyToPersonContainer.Add(personKey, personContainer); Dictionary>> idThenNormalizedRectangleToPersonContainerCollection = new(); if (personKeyFormattedIdThenNormalizedRectangleCollection.Any()) { string personDisplayDirectory; PersonContainer personContainer; string personDisplayDirectoryName; Dictionary personDisplayDirectoryTo = new(); foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, int id, int normalizedRectangle) in personKeyFormattedIdThenNormalizedRectangleCollection) { personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormatted); if (personBirthday is null) continue; personDisplayDirectoryName = personDisplayDirectoryNames[^1]; personDisplayDirectory = Path.Combine(personDisplayDirectoryNames); if (!personKeyFormattedToPersonContainer.ContainsKey(personKeyFormatted)) { personContainer = new(configuration.MappingDefaultName, configuration.PersonCharacters.ToArray(), personBirthday, personDisplayDirectoryName); personKeyFormattedToPersonContainer.Add(personKeyFormatted, personContainer); } if (personDisplayDirectoryName.Length != 1 && personDisplayDirectoryName != configuration.MappingDefaultName && !personDisplayDirectoryTo.ContainsKey(personDisplayDirectory)) personDisplayDirectoryTo.Add(personDisplayDirectory, new(personDisplayDirectoryNames, personKeyFormattedToPersonContainer[personKeyFormatted])); if (!idThenNormalizedRectangleToPersonContainerCollection.ContainsKey(id)) idThenNormalizedRectangleToPersonContainerCollection.Add(id, new()); if (!idThenNormalizedRectangleToPersonContainerCollection[id].ContainsKey(normalizedRectangle)) idThenNormalizedRectangleToPersonContainerCollection[id].Add(normalizedRectangle, new()); idThenNormalizedRectangleToPersonContainerCollection[id][normalizedRectangle].Add(personKeyFormattedToPersonContainer[personKeyFormatted]); } foreach (KeyValuePair keyValuePair in personDisplayDirectoryTo) possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Add(keyValuePair.Value); } foreach (KeyValuePair>> keyValuePair in idThenNormalizedRectangleToPersonContainerCollection) { idThenNormalizedRectangleToPersonContainers.Add(keyValuePair.Key, new()); foreach (KeyValuePair> innerKeyValuePair in keyValuePair.Value) { distinctPersonContainers = GetDistinctPersonContainers(innerKeyValuePair.Value); idThenNormalizedRectangleToPersonContainers[keyValuePair.Key].Add(innerKeyValuePair.Key, distinctPersonContainers); } }; } private static (long, PersonContainer)[] GetDistinctCollection(Configuration configuration, IEnumerable personContainers, Dictionary> personKeyToPersonContainerCollection, Dictionary personKeyFormattedToPersonContainer) { (long, PersonContainer)[] results; const int zero = 0; List errors = new(); string newestPersonKeyFormatted; List<(long PersonKey, PersonContainer PersonContainer)> collection = new(); foreach (PersonContainer personContainer in personContainers) { if (personContainer.Key is null) continue; if (!personKeyToPersonContainerCollection.ContainsKey(personContainer.Key.Value)) personKeyToPersonContainerCollection.Add(personContainer.Key.Value, new()); personKeyToPersonContainerCollection[personContainer.Key.Value].Add(personContainer); newestPersonKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personContainer.Key.Value); if (!personKeyFormattedToPersonContainer.ContainsKey(newestPersonKeyFormatted)) personKeyFormattedToPersonContainer.Add(newestPersonKeyFormatted, personContainer); } foreach (KeyValuePair> keyValuePair in personKeyToPersonContainerCollection) { if (keyValuePair.Value.Count != 1 && (from l in keyValuePair.Value select l.DisplayDirectoryName).Distinct().Count() != 1) errors.Add(keyValuePair.Value[zero].DisplayDirectoryName); collection.Add(new(keyValuePair.Key, keyValuePair.Value[zero])); } if (errors.Any()) throw new Exception(string.Join(Environment.NewLine, errors)); results = (from l in collection orderby l.PersonKey descending select (l.PersonKey, l.PersonContainer)).ToArray(); return results; } private static int SetCollectionsAndGetUnableToConvertCount(Configuration configuration, long ticks, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection, List<(string, string[], string)> collection) { int result = 0; int? id; int? normalizedRectangle; List normalizedRectangles; string? newestPersonKeyFormatted; string personDisplayDirectoryName; Dictionary> idToNormalizedRectangles = new(); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") {collection.Count:000} join from ticks Director(ies) - C - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using ProgressBar progressBar = new(collection.Count, message, options); foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string mappedFaceFile) in collection) { progressBar.Tick(); if (!personKeyFormattedToNewestPersonKeyFormatted.TryGetValue(personKeyFormatted, out newestPersonKeyFormatted)) { if (personDisplayDirectoryNames.Any() && !IPerson.IsDefaultName(configuration.MappingDefaultName, personDisplayDirectoryNames[^1])) continue; newestPersonKeyFormatted = personKeyFormatted; } (id, normalizedRectangle) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFaceFile); if (id is null || normalizedRectangle is null) { result++; continue; } if (!idToNormalizedRectangles.ContainsKey(id.Value)) idToNormalizedRectangles.Add(id.Value, new()); normalizedRectangles = idToNormalizedRectangles[id.Value]; normalizedRectangles.Add(normalizedRectangle.Value); idToNormalizedRectangles[id.Value].Add(normalizedRectangle.Value); personDisplayDirectoryName = personDisplayDirectoryNames[^1]; if (string.IsNullOrEmpty(personDisplayDirectoryName)) continue; personKeyFormattedIdThenNormalizedRectangleCollection.Add(new(newestPersonKeyFormatted, personDisplayDirectoryNames, id.Value, normalizedRectangle.Value)); } return result; } private static List GetNotMappedPersonContainers(Configuration configuration, ReadOnlyCollection personContainers, long[] personKeyCollection) { List results = new(); List notMappedAndNotNamedPersonKeys = new(); List notMappedAndWithNamedPersonKeys = new(); List personKeys = IPersonContainer.GetPersonKeys(personContainers); foreach (PersonContainer personContainer in personContainers) { if (personContainer.Person is null || personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) continue; if (personKeys.Contains(personContainer.Key.Value)) continue; if (personKeyCollection.Contains(personContainer.Key.Value)) continue; if (string.IsNullOrEmpty(personContainer.DisplayDirectoryName) || personContainer.DisplayDirectoryName == configuration.MappingDefaultName) notMappedAndNotNamedPersonKeys.Add(personContainer); else notMappedAndWithNamedPersonKeys.Add(personContainer); } results.AddRange(notMappedAndNotNamedPersonKeys); return results; } private static string? GetDisplayDirectoryName(Dictionary personKeyToPersonContainer, long key) { string? result = null; if (personKeyToPersonContainer.TryGetValue(key, out PersonContainer? personContainer)) { result = personContainer.DisplayDirectoryName; if (string.IsNullOrEmpty(result)) throw new NotSupportedException(); } return result; } private static void SetPersonKeyToPersonContainer(Configuration configuration, ReadOnlyCollection personContainers, long[] personKeyCollection, Dictionary personKeyToPersonContainer, Dictionary> personKeyToPersonContainerCollection) { string? displayDirectoryName; foreach (PersonContainer personContainer in personContainers) { if (personContainer.Key is null || !personKeyCollection.Contains(personContainer.Key.Value)) continue; displayDirectoryName = GetDisplayDirectoryName(personKeyToPersonContainer, personContainer.Key.Value); if (displayDirectoryName is not null && (displayDirectoryName == personContainer.DisplayDirectoryName || (displayDirectoryName[0] == personContainer.DisplayDirectoryName[0] && (displayDirectoryName.Length == 1 || personContainer.DisplayDirectoryName.Length == 1)))) continue; personKeyToPersonContainer.Add(personContainer.Key.Value, personContainer); } if (personKeyCollection.Any()) { const int zero = 0; int? approximateYears = null; PersonBirthday? personBirthday; PersonContainer personContainer; displayDirectoryName = configuration.MappingDefaultName; foreach (long personKey in personKeyCollection) { if (personKeyToPersonContainer.ContainsKey(personKey)) continue; personBirthday = IPersonBirthday.GetPersonBirthday(personKey); if (!personKeyToPersonContainerCollection.ContainsKey(personKey)) personContainer = new(approximateYears, personBirthday, displayDirectoryName, personKey); else personContainer = new(approximateYears, personBirthday, personKeyToPersonContainerCollection[personKey][zero].PersonDirectory, displayDirectoryName, personKey); personKeyToPersonContainer.Add(personKey, personContainer); } } } static void SavePossiblyNewPersonContainers(string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, string? a2PeopleSingletonDirectory, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) { string json; string[] files; string checkFile; string[] segments; const int zero = 0; char personCharacter; string personKeyFormatted; string personDisplayDirectory; PersonBirthday personBirthday; string personDisplayDirectoryName; string checkPersonDisplayDirectory; string checkPersonKeyFormattedDirectory; JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true }; foreach ((string[] personDisplayDirectoryNames, PersonContainer personContainer) in possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) { if (a2PeopleSingletonDirectory is null || personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) continue; personBirthday = personContainer.Birthdays[zero]; personDisplayDirectoryName = personDisplayDirectoryNames[^1]; personDisplayDirectory = Path.Combine(personDisplayDirectoryNames); personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday); segments = personDisplayDirectoryName.Split(personCharacters); if (segments.Length != 2) personCharacter = '_'; else personCharacter = personDisplayDirectoryName[segments[zero].Length]; checkPersonDisplayDirectory = Path.Combine(a2PeopleSingletonDirectory, personCharacter.ToString(), personDisplayDirectoryName); checkPersonKeyFormattedDirectory = Path.Combine(checkPersonDisplayDirectory, personKeyFormatted); if (Directory.Exists(checkPersonKeyFormattedDirectory)) continue; _ = Directory.CreateDirectory(checkPersonKeyFormattedDirectory); checkFile = Path.Combine(checkPersonKeyFormattedDirectory, $"{personKeyFormatted}.json"); json = JsonSerializer.Serialize(personContainer.Person, jsonSerializerOptions); _ = IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true); if (!Directory.Exists(personDisplayDirectory)) continue; files = Directory.GetFiles(personDisplayDirectory, $"*{facesFileNameExtension}", SearchOption.TopDirectoryOnly); foreach (string file in files) { checkFile = Path.Combine(checkPersonDisplayDirectory, Path.GetFileName(file)); if (File.Exists(checkFile)) continue; File.Copy(files[0], checkFile); break; } } } private static string[] UpdateDateVerifyAndGetTicksDirectories(string eDistanceContentDirectory) { const int zero = 0; string ticksDirectoryName; DirectoryInfo directoryInfo; long? lastDirectoryTicks = null; DateTime dateTime = DateTime.Now; List<(string Directory, TimeSpan TimeSpan)> collection = new(); string[] results = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string ticksDirectory in results) { ticksDirectoryName = Path.GetFileName(ticksDirectory); if (ticksDirectoryName.Length < 3 || ticksDirectoryName[zero] != '(' || ticksDirectoryName[^1] != ')') continue; if (!long.TryParse(ticksDirectoryName[1..^1], out long directoryTicks)) { if (!long.TryParse(ticksDirectoryName[1..^4], out directoryTicks)) throw new NotSupportedException(); } directoryInfo = new(ticksDirectory); if (directoryInfo.CreationTime.Ticks != directoryTicks) Directory.SetCreationTime(ticksDirectory, new DateTime(directoryTicks)); if (directoryInfo.LastWriteTime.Ticks != directoryTicks) Directory.SetLastWriteTime(ticksDirectory, new DateTime(directoryTicks)); if (lastDirectoryTicks is not null && new TimeSpan(dateTime.Ticks - directoryTicks).TotalDays > 1) collection.Add((ticksDirectory, new TimeSpan(directoryTicks - lastDirectoryTicks.Value))); lastDirectoryTicks = directoryTicks; } string[] compare = (from l in collection where l.TimeSpan.TotalDays < 4 select l.Directory).ToArray(); if (compare.Any()) throw new Exception($"Please Consolidate <{string.Join(Environment.NewLine, compare)}>"); return results; } private static List<(long, string)> GetDisplayDirectoryAllFiles(string fileNameExtension, ReadOnlyCollection personContainers) { List<(long, string)> results = new(); List distinct = new(); foreach (PersonContainer personContainer in personContainers) { if (personContainer.Key is null) continue; foreach (string displayDirectoryAllFile in personContainer.DisplayDirectoryAllFiles) { if (!displayDirectoryAllFile.EndsWith(fileNameExtension)) continue; if (distinct.Contains(displayDirectoryAllFile)) continue; distinct.Add(displayDirectoryAllFile); results.Add(new(personContainer.Key.Value, displayDirectoryAllFile)); } } return results; } private static List<(long PersonKey, string File)> GetCollection(Configuration configuration, ReadOnlyCollection personContainers, List<(string, string[], string)> collection) { List<(long PersonKey, string File)> results = new(); string file; long personKey; List distinct = new(); PersonBirthday? personBirthday; results.AddRange(GetDisplayDirectoryAllFiles(configuration.FacesFileNameExtension, personContainers)); foreach ((string personKeyFormatted, _, string mappedFaceFile) in collection) { personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormatted); if (personBirthday is null) continue; if (distinct.Contains(mappedFaceFile)) continue; distinct.Add(mappedFaceFile); personKey = personBirthday.Value.Ticks; results.Add(new(personKey, mappedFaceFile)); } for (int i = results.Count - 1; i > -1; i--) { file = results[i].File; if (file.EndsWith(".old")) { results.RemoveAt(i); continue; } if (!file.EndsWith(".dup") && !file.EndsWith(".unk") && !file.EndsWith(".abd")) continue; if (!File.Exists(file)) continue; File.Move(file, file[..^4]); results[i] = new(results[i].PersonKey, file[..^4]); } return results; } private static void ParallelFor(Configuration configuration, string eDistanceContentDirectory, List> collection, long personKey, string file) { const string lnk = ".lnk"; int? id, normalizedRectangle; IReadOnlyList directories; bool fromDistanceContent = !file.EndsWith(lnk) && file.Contains(eDistanceContentDirectory); if (!file.EndsWith(lnk)) (id, normalizedRectangle) = IMapping.GetConverted(configuration.FacesFileNameExtension, file); else (id, normalizedRectangle) = IMapping.GetConverted(configuration.FacesFileNameExtension, file[..^4]); if (id is null || normalizedRectangle is null) return; if (file.EndsWith(lnk) || (!configuration.DistanceMoveUnableToMatch && !configuration.DistanceRenameToMatch)) directories = new List(); else directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file); Rectangle? rectangle = ILocation.GetNormalizedRectangle(configuration.LocationDigits, normalizedRectangle.Value); lock (collection) collection.Add(new(fromDistanceContent, file, personKey, id.Value, normalizedRectangle.Value, directories, rectangle, null)); } private static void OpenPossibleDuplicates(Configuration configuration, List<(long, int, string, double?)> duplicates) { string personKeyFormatted; foreach ((long personKey, int id, string file, double? percent) in duplicates) { if (percent is null) continue; _ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\"")); personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personKey); } foreach ((long personKey, int id, string file, double? percent) in duplicates) { if (percent is not null && percent.Value == 0) continue; _ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\"")); personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personKey); } foreach ((long personKey, int id, string file, double? percent) in duplicates) { if (percent is not null && percent.Value > 0) continue; _ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\"")); personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personKey); } } private static void LookForPossibleDuplicates(Configuration configuration, List> collection) { string key; double? percent; Rectangle? rectangle; List delete = new(); Rectangle intersectRectangle; (string File, int NormalizedRectangle) item; Dictionary distinct = new(); List<(long, int, string, double?)> duplicates = new(); foreach (LocationContainer locationContainer in collection) { key = string.Concat(locationContainer.PersonKey, locationContainer.Id); if (distinct.TryGetValue(key, out item)) { if (item.NormalizedRectangle == locationContainer.NormalizedRectangle) continue; if (locationContainer.Rectangle is null) percent = null; else { rectangle = ILocation.GetNormalizedRectangle(configuration.LocationDigits, item.NormalizedRectangle); if (locationContainer.Rectangle is null || rectangle is null) percent = null; else { intersectRectangle = Rectangle.Intersect(locationContainer.Rectangle.Value, rectangle.Value); percent = intersectRectangle.Width * intersectRectangle.Height; } } delete.Add(item.File); delete.Add(locationContainer.File); duplicates.Add(new(locationContainer.PersonKey, locationContainer.Id, locationContainer.File, percent)); continue; } distinct.Add(key, new(locationContainer.File, locationContainer.NormalizedRectangle)); } if (!configuration.DeletePossibleDuplicates && duplicates.Any()) OpenPossibleDuplicates(configuration, duplicates); else { if (delete.Count > 5) throw new Exception("Something maybe wrong!"); foreach (string file in delete) { if (File.Exists(file)) File.Delete(file); } } } private static List> GetLocationContainers(int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection personContainers, string eDistanceContentDirectory, List<(string, string[], string)> sourceCollection) { List> results = new(); List<(long PersonKey, string File)> collection = GetCollection(configuration, personContainers, sourceCollection); if (collection.Any() && (configuration.DistanceMoveUnableToMatch || configuration.DistanceRenameToMatch)) { int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") Building Mapped Face Files Collection - {totalSeconds} total second(s)"; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using ProgressBar progressBar = new(collection.Count, message, options); _ = Parallel.For(0, collection.Count, parallelOptions, (i, state) => { progressBar.Tick(); ParallelFor(configuration, eDistanceContentDirectory, results, collection[i].PersonKey, collection[i].File); }); } LookForPossibleDuplicates(configuration, results); return results; } internal static void Set(int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection personContainers, string? a2PeopleSingletonDirectory, string eDistanceContentDirectory, Dictionary personKeyToPersonContainer, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> skipNotSkipCollection, List> locationContainers, Dictionary> idThenNormalizedRectangleToPersonContainers) { string message; int totalSeconds; List nullablePersonKeyCollection = new(); List personKeyFormattedCollection = new(); Dictionary personKeyFormattedToNewestPersonKeyFormatted = new(); Dictionary personKeyFormattedToPersonContainer = new(); Dictionary> personKeyToPersonContainerCollection = new(); string[] ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(eDistanceContentDirectory); List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection = new(); List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer = new(); SetPersonCollections(configuration, personContainers, a2PeopleSingletonDirectory, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection, skipCollection, skipNotSkipCollection); // personContainers.AddRange(GetNonSpecificPeopleCollection(configuration, ticks, personKeys)); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); message = $") {ticksDirectories.Length:000} compile from and clean ticks Director(ies) - B - {totalSeconds} total second(s)"; List<(string, string[], string)> collection = DeleteEmptyDirectoriesAndGetCollection(configuration, personKeyFormattedCollection, ticksDirectories, message); locationContainers.AddRange(GetLocationContainers(maxDegreeOfParallelism, configuration, ticks, personContainers, eDistanceContentDirectory, collection)); int unableToMatchCount = SetCollectionsAndGetUnableToConvertCount(configuration, ticks, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedIdThenNormalizedRectangleCollection, collection); SetKeyValuePairs(configuration, personContainers, personKeyToPersonContainerCollection, personKeyFormattedToPersonContainer, personKeyFormattedIdThenNormalizedRectangleCollection, personKeyToPersonContainer, idThenNormalizedRectangleToPersonContainers, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); message = $") {collection.Count:000} message from ticks Director(ies) - D - {unableToMatchCount} Unable To Match Count / {collection.Count} Collection - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using (ProgressBar progressBar = new(collection.Count, message, options)) { foreach (KeyValuePair> keyValuePair in idThenNormalizedRectangleToPersonContainers) { progressBar.Tick(); foreach (KeyValuePair keyValue in keyValuePair.Value) nullablePersonKeyCollection.AddRange(from l in keyValue.Value select l.Key); } } long[] personKeyCollection = (from l in nullablePersonKeyCollection where l is not null select l.Value).Distinct().ToArray(); SetPersonKeyToPersonContainer(configuration, personContainers, personKeyCollection, personKeyToPersonContainer, personKeyToPersonContainerCollection); notMappedPersonContainers.AddRange(GetNotMappedPersonContainers(configuration, personContainers, personKeyCollection)); if (possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Any()) SavePossiblyNewPersonContainers(configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), configuration.FacesFileNameExtension, a2PeopleSingletonDirectory, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); } private static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, long minimumDateTimeTicks, bool? isWrongYear) { int years; string result; TimeSpan? timeSpan = IPersonBirthday.GetTimeSpan(minimumDateTimeTicks, isWrongYear, personBirthday); if (timeSpan.HasValue && timeSpan.Value.Ticks < 0) result = "!---"; else if (timeSpan.HasValue) { (years, _) = IPersonBirthday.GetAge(minimumDateTimeTicks, personBirthday); result = $"^{years:000}"; } else if (approximateYears.HasValue) { DateTime dateTime = new(ticks); (years, _) = IAge.GetAge(minimumDateTimeTicks, dateTime.AddYears(-approximateYears.Value)); result = $"~{years:000}"; } else { string isWrongYearFlag = IItem.GetWrongYearFlag(isWrongYear); result = $"{isWrongYearFlag}{new DateTime(minimumDateTimeTicks):yyyy}"; } return result; } internal static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, DateTime minimumDateTime, bool? isWrongYear) { string result = GetMappingSegmentB(ticks, personBirthday, approximateYears, minimumDateTime.Ticks, isWrongYear); return result; } internal static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, MappingFromItem mappingFromItem) { string result = GetMappingSegmentB(ticks, personBirthday, approximateYears, mappingFromItem.MinimumDateTime, mappingFromItem.IsWrongYear); return result; } internal static string? GetFacePartsContentCollectionFile(string extension, string d2FacePartsContentCollectionDirectory, MappingFromItem mappingFromItem) { string? result; string? directoryName = Path.GetDirectoryName(mappingFromItem.RelativePath); if (directoryName is null) result = null; else result = Path.Combine($"{d2FacePartsContentCollectionDirectory}{directoryName}", $"{mappingFromItem.ImageFileHolder.Name}{extension}"); return result; } internal static string? GetFacesDirectory(string dFacesContentDirectory, MappingFromItem mappingFromItem) { string? result; string? directoryName = Path.GetDirectoryName(mappingFromItem.RelativePath); if (directoryName is null) result = null; else result = Path.Combine($"{dFacesContentDirectory}{directoryName}", mappingFromItem.ImageFileHolder.NameWithoutExtension); return result; } internal static string? GetFacePartsDirectory(string d2FacePartsContentDirectory, MappingFromItem mappingFromItem) { string? result; string? directoryName = Path.GetDirectoryName(mappingFromItem.RelativePath); if (directoryName is null) result = null; else result = Path.Combine($"{d2FacePartsContentDirectory}{directoryName}", mappingFromItem.ImageFileHolder.NameWithoutExtension); return result; } internal static SaveContainer GetDebugSaveContainer(string directory, MappingFromPerson? mappingFromPerson, SortingContainer sortingContainer, Mapping mapping) { SaveContainer result; if (sortingContainer.Mapping.MappingFromLocation is null) throw new NullReferenceException(nameof(sortingContainer.Mapping.MappingFromLocation)); FileHolder faceFileHolder = new($"C:/{sortingContainer.Sorting.Id}.{sortingContainer.Sorting.NormalizedRectangle}"); string shortcutFile; if (mappingFromPerson is null) shortcutFile = Path.Combine(directory, $"{sortingContainer.Mapping.MappingFromLocation.DeterministicHashCodeKey}{sortingContainer.Mapping.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); return result; } internal static (SaveContainer?, SaveContainer?) GetContainers(string facesFileNameExtension, string facePartsFileNameExtension, string dFacesContentDirectory, string d2FacePartsContentCollectionDirectory, string directory, SortingContainer sortingContainer, Mapping mapping) { SaveContainer? result; SaveContainer? saveContainer; if (sortingContainer.Mapping.MappingFromLocation is null) throw new NullReferenceException(nameof(sortingContainer.Mapping.MappingFromLocation)); if (mapping.MappingFromLocation is null) (result, saveContainer) = (null, null); else { string? facePartsContentCollectionFile = GetFacePartsContentCollectionFile(facePartsFileNameExtension, d2FacePartsContentCollectionDirectory, mapping.MappingFromItem); if (facePartsContentCollectionFile is null || !File.Exists(facePartsContentCollectionFile)) result = null; else { string checkFile = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}{facePartsFileNameExtension}"); result = new(checkFile, directory, new(facePartsContentCollectionFile)); } string? facesDirectory = GetFacesDirectory(dFacesContentDirectory, mapping.MappingFromItem); if (facesDirectory is null) saveContainer = null; else { FileHolder faceFileHolder = new(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}")); if (!faceFileHolder.Exists) saveContainer = null; else { string checkFile = Path.Combine(directory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}"); saveContainer = new(checkFile, directory, faceFileHolder); } } } return (result, saveContainer); } internal static (SaveContainer, SaveContainer) GetContainers(string facesFileNameExtension, string facePartsFileNameExtension, string directory, FileHolder faceFileHolder, string facePartsContentCollectionFile, Mapping mapping) { string checkFile; SaveContainer result; if (mapping.MappingFromLocation is null) throw new NullReferenceException(nameof(mapping.MappingFromLocation)); checkFile = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}{facePartsFileNameExtension}"); result = new(checkFile, directory, new(facePartsContentCollectionFile)); checkFile = Path.Combine(directory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}"); return (result, new(checkFile, directory, faceFileHolder)); } private static IEnumerable<(string, string)> GetCollection(string[] yearDirectories) { foreach (string l in yearDirectories) yield return new(l, Path.GetFileName(l)); } internal static void SaveMappingShortcuts(string mappingDirectory) { string? shortcutFileName; string[] yearDirectories; string personKeyFormatted; string[] personNameDirectories; WindowsShortcut windowsShortcut; string personDisplayDirectoryName; (string, string)[] yearDirectoryNameCheck; List<(string, string)> yearDirectoryNames = new(); string[] personKeyDirectories = Directory.GetDirectories(mappingDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string personKeyDirectory in personKeyDirectories) { windowsShortcut = new(); shortcutFileName = null; yearDirectoryNames.Clear(); personKeyFormatted = Path.GetFileName(personKeyDirectory); yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly); yearDirectoryNames.AddRange(GetCollection(yearDirectories)); yearDirectoryNameCheck = (from l in yearDirectoryNames where l.Item2.Contains('^') select l).OrderByDescending(l => l.Item2).ToArray(); if (!yearDirectoryNameCheck.Any()) yearDirectoryNameCheck = (from l in yearDirectoryNames where l.Item2.Contains('~') select l).OrderByDescending(l => l.Item2).ToArray(); if (!yearDirectoryNameCheck.Any()) yearDirectoryNameCheck = (from l in yearDirectoryNames where l.Item2.Contains('=') select l).OrderByDescending(l => l.Item2).ToArray(); if (!yearDirectoryNameCheck.Any()) yearDirectoryNameCheck = (from l in yearDirectoryNames select l).OrderByDescending(l => l).ToArray(); if (!yearDirectoryNameCheck.Any()) continue; foreach ((string yearDirectory, string yearDirectoryName) in yearDirectoryNameCheck) { personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string personNameDirectory in personNameDirectories) { personDisplayDirectoryName = Path.GetFileName(personNameDirectory).Split('-')[0]; if (personDisplayDirectoryName is null) continue; windowsShortcut.Path = yearDirectory; windowsShortcut.Description = yearDirectoryName; shortcutFileName = Path.Combine(mappingDirectory, $"{personDisplayDirectoryName} [{windowsShortcut.Description}].lnk"); break; } if (shortcutFileName is not null) { if (!File.Exists(shortcutFileName)) break; } } if (shortcutFileName is null || windowsShortcut.Path is null || windowsShortcut.Description is null) continue; try { windowsShortcut.Save(shortcutFileName); windowsShortcut.Dispose(); } catch (Exception) { } } } internal static Dictionary> GetIdToPersonKeys(Dictionary> personKeyToIds) { Dictionary> results = new(); List? collection; foreach (KeyValuePair> keyValuePair in personKeyToIds) { foreach (int id in keyValuePair.Value) { if (!results.TryGetValue(id, out collection)) { results.Add(id, new()); if (!results.TryGetValue(id, out collection)) throw new Exception(); } if (collection.Contains(keyValuePair.Key)) continue; collection.Add(keyValuePair.Key); } } return results; } internal static Mapping[] GetSelectedMappingCollection(List faces) { Mapping[] results; IEnumerable collection = from l in faces orderby l.Mapping?.MappingFromItem.Id select l.Mapping; results = (from l in collection where l is not null select l).ToArray(); return results; } internal static List GetFaces(List items) { List results = new(); foreach (Item item in items) { if (item.Property?.Id is null || item.ResizedFileHolder is null) continue; foreach (Face face in item.Faces) { if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) continue; results.Add(face); } } return results; } internal static Mapping[] GetSelectedMappingCollection(List items) { Mapping[] results; List faces = GetFaces(items); results = GetSelectedMappingCollection(faces); return results; } internal static Dictionary> GetIdToNormalizedRectangleToFace(Mapping[] mappingCollection) { Dictionary> results = new(); Dictionary? keyValuePairs; foreach (Mapping mapping in mappingCollection) { if (mapping.MappingFromLocation is null) continue; if (!results.TryGetValue(mapping.MappingFromItem.Id, out keyValuePairs)) { results.Add(mapping.MappingFromItem.Id, new()); if (!results.TryGetValue(mapping.MappingFromItem.Id, out keyValuePairs)) throw new Exception(); } if (keyValuePairs.ContainsKey(mapping.MappingFromLocation.NormalizedRectangle)) continue; keyValuePairs.Add(mapping.MappingFromLocation.NormalizedRectangle, mapping); } 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); } }