using Humanizer; using ShellProgressBar; 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 List GetNonSpecificPeopleCollection(Configuration configuration, long ticks, List personKeys) { List results = new(); Person person; long personKey; int? approximateYears = null; PersonBirthday personBirthday; PersonContainer personContainer; string[] personDisplayDirectoryAllFiles = Array.Empty(); DateTime incrementDate = new(configuration.PersonBirthdayFirstYear, 1, 1); for (int i = 0; i < int.MaxValue; i++) { personKey = incrementDate.Ticks; incrementDate = incrementDate.AddDays(1); if (incrementDate.Ticks > ticks) break; if (personKeys.Contains(personKey)) continue; personBirthday = IPersonBirthday.GetPersonBirthday(personKey); person = IPerson.GetPerson(configuration.MappingDefaultName, personKey, personBirthday); personContainer = new(approximateYears, person, new PersonBirthday[] { personBirthday }, personDisplayDirectoryAllFiles, configuration.MappingDefaultName, personKey, partialKeyFormatted: null); results.Add(personContainer); } return results; } private static void SetPersonCollections(Configuration configuration, List personContainers, List personKeys, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List personKeyFormattedCollection, Dictionary> skipCollection) { int? id; long personKey; string personKeyFormatted; int? normalizedRectangle; string newestPersonKeyFormatted; 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 (!skipCollection.ContainsKey(id.Value)) skipCollection.Add(id.Value, new()); skipCollection[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) { personKey = personBirthday.Value.Ticks; personKeys.Add(personKey); } 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); } } } 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; const int zero = 0; string[] yearDirectories; string personKeyFormatted; string ticksDirectoryName; string? personFirstInitial; DirectoryInfo directoryInfo; string[] personKeyDirectories; int? normalizedRectangle; 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; if (!long.TryParse(ticksDirectoryName[1..^1], out long directoryTicks)) { if (!long.TryParse(ticksDirectoryName[1..^4], out directoryTicks)) continue; } 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)); personKeyDirectories = Directory.GetDirectories(ticksDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string personKeyDirectory in personKeyDirectories) { personKeyFormatted = Path.GetFileName(personKeyDirectory); 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 (personKeyFormatted == nameof(Shared.Models.Stateless.IMapLogic.Sorting) && 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 || personDisplayDirectoryNames[^1] == configuration.MappingDefaultName || !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()); Directory.Move(personNameDirectory, personFirstInitialDirectory); files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); } foreach (string file in files) { if (file.EndsWith(".lnk") || file.EndsWith(".json")) continue; (id, normalizedRectangle) = IMapping.GetConverted(configuration.FacesFileNameExtension, file); if (id is null || normalizedRectangle is null) continue; 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; } internal static List<(string, string[], string)> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory, PersonContainer[] personContainers) { List<(string, string[], string)> results; string personKeyFormatted; List personKeyFormattedCollection = new(); List<(long? PersonKey, string Line)> lines = new(); _ = GetDistinctCollection(configuration, personContainers.ToList(), new()); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string[] ticksDirectories; if (string.IsNullOrEmpty(eDistanceContentDirectory)) ticksDirectories = Array.Empty(); else { if (!Directory.Exists(eDistanceContentDirectory)) _ = Directory.CreateDirectory(eDistanceContentDirectory); else { _ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory); if (!Directory.Exists(eDistanceContentDirectory)) _ = Directory.CreateDirectory(eDistanceContentDirectory); } ticksDirectories = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly); } string message = $") {ticksDirectories.Length:000} collect from and clean ticks Director(ies) - A - {totalSeconds} total second(s)"; foreach (PersonContainer personContainer in personContainers) { lines.AddRange(IPersonContainer.GetDisplay(configuration.PersonBirthdayFormat, personContainer)); 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 (!string.IsNullOrEmpty(a2PeopleContentDirectory)) File.WriteAllLines(Path.Combine(a2PeopleContentDirectory, "People - C.tsv"), from l in lines select l.Line); results = DeleteEmptyDirectoriesAndGetCollection(configuration, personKeyFormattedCollection, ticksDirectories, message); 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, List personContainers, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection, List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection, Dictionary personKeyToPersonContainer, Dictionary> idThenNormalizedRectangleToPersonContainers, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer, Dictionary> incorrectIdThenNormalizedRectangleToPersonContainers) { PersonBirthday? personBirthday; PersonContainer[] distinctPersonContainers; Dictionary personKeyFormattedToPersonContainer = new(); Dictionary>> idThenNormalizedRectangleToPersonContainerCollection = new(); Dictionary>> incorrectIdThenNormalizedRectangleToPersonContainerCollection = new(); List<(long, PersonContainer)> collection = GetDistinctCollection(configuration, personContainers, personKeyFormattedToPersonContainer); foreach ((long personKey, PersonContainer personContainer) in collection) personKeyToPersonContainer.Add(personKey, personContainer); 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(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); } }; if (incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection.Any()) { PersonContainer personContainer; foreach ((string personKeyFormatted, int id, int normalizedRectangle) in incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection) { personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormatted); if (personBirthday is null) continue; if (!incorrectIdThenNormalizedRectangleToPersonContainerCollection.ContainsKey(id)) incorrectIdThenNormalizedRectangleToPersonContainerCollection.Add(id, new()); if (!personKeyFormattedToPersonContainer.ContainsKey(personKeyFormatted)) { personContainer = new(personBirthday, configuration.MappingDefaultName); personKeyFormattedToPersonContainer.Add(personKeyFormatted, personContainer); } if (!incorrectIdThenNormalizedRectangleToPersonContainerCollection[id].ContainsKey(normalizedRectangle)) incorrectIdThenNormalizedRectangleToPersonContainerCollection[id].Add(normalizedRectangle, new()); incorrectIdThenNormalizedRectangleToPersonContainerCollection[id][normalizedRectangle].Add(personKeyFormattedToPersonContainer[personKeyFormatted]); } } foreach (KeyValuePair>> keyValuePair in incorrectIdThenNormalizedRectangleToPersonContainerCollection) { incorrectIdThenNormalizedRectangleToPersonContainers.Add(keyValuePair.Key, new()); foreach (KeyValuePair> innerKeyValuePair in keyValuePair.Value) { distinctPersonContainers = GetDistinctPersonContainers(innerKeyValuePair.Value); incorrectIdThenNormalizedRectangleToPersonContainers[keyValuePair.Key].Add(innerKeyValuePair.Key, distinctPersonContainers); } } } private static List<(long, PersonContainer)> GetDistinctCollection(Configuration configuration, List personContainers, Dictionary personKeyFormattedToPersonContainer) { List<(long, PersonContainer)> results = new(); const int zero = 0; string newestPersonKeyFormatted; Dictionary> personKeyToPersonContainerCollection = 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) throw new NotSupportedException(keyValuePair.Value[zero].DisplayDirectoryName); results.Add(new(keyValuePair.Key, keyValuePair.Value[zero])); } return results; } private static (int, int) SetCollectionsAndGetUnableToConvertCount(Configuration configuration, long ticks, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection, List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection, List<(string, string[], string)> collection) { int result = 0; int? id; int? normalizedRectangle; List normalizedRectangles; string newestPersonKeyFormatted; string personDisplayDirectoryName; List duplicateMappedFaceFiles = new(); 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(); (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); if (!personKeyFormattedToNewestPersonKeyFormatted.ContainsKey(personKeyFormatted)) newestPersonKeyFormatted = personKeyFormatted; else newestPersonKeyFormatted = personKeyFormattedToNewestPersonKeyFormatted[personKeyFormatted]; personDisplayDirectoryName = personDisplayDirectoryNames[^1]; if (string.IsNullOrEmpty(personDisplayDirectoryName) || personDisplayDirectoryName[0] == '!') incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection.Add(new(newestPersonKeyFormatted, id.Value, normalizedRectangle.Value)); else personKeyFormattedIdThenNormalizedRectangleCollection.Add(new(newestPersonKeyFormatted, personDisplayDirectoryNames, id.Value, normalizedRectangle.Value)); } if (duplicateMappedFaceFiles.Any()) { duplicateMappedFaceFiles.Sort(); if (duplicateMappedFaceFiles.Any()) { } } return new(result, duplicateMappedFaceFiles.Count); } private static double GetStandardDeviation(IEnumerable values, double average) { double result = 0; if (!values.Any()) throw new Exception("Collection must have at least one value!"); double sum = values.Sum(l => (l - average) * (l - average)); result = Math.Sqrt(sum / values.Count()); return result; } private static List GetSumCollection(long[] collection) { List results = new(); long result = 0; foreach (long item in collection) { result += item; if (result > long.MaxValue) { results.Add(result); result = 0; } } return results; } private static void SetPersonKeysRanges(Configuration configuration, long ticks, Dictionary> personKeyToMinimumDateTimeTicks, Dictionary personKeyToRanges) { long lcl; long ucl; long maximum; long minimum; double average; long[] collection; double standardDeviation; List sumCollection; foreach (KeyValuePair> keyValuePair in personKeyToMinimumDateTimeTicks) { minimum = keyValuePair.Value.Min(); if (keyValuePair.Value.Count < configuration.SortingMinimumToUseSigma) { maximum = keyValuePair.Value.Max(); personKeyToRanges.Add(keyValuePair.Key, new(new DateTime(minimum).AddDays(-configuration.RangeDaysDeltaTolerance).Ticks, minimum, maximum, new DateTime(maximum).AddDays(configuration.RangeDaysDeltaTolerance).Ticks)); } else { collection = (from l in keyValuePair.Value select l - minimum).ToArray(); maximum = collection.Max() + minimum; sumCollection = GetSumCollection(collection); if (sumCollection.Count < 2) average = (sumCollection.Sum() / collection.Length) + minimum; else average = (sumCollection.Sum() / collection.Length) + minimum; standardDeviation = GetStandardDeviation(collection, average); ucl = (long)(average + (standardDeviation * Shared.Models.Stateless.IMapLogic.Sigma)); lcl = (long)(average - (standardDeviation * Shared.Models.Stateless.IMapLogic.Sigma)); if (lcl < 0) lcl = 0; if (ucl > 0) ucl = ticks; personKeyToRanges.Add(keyValuePair.Key, new(lcl, minimum, maximum, ucl)); } } } internal static void SetPersonTicks(Configuration configuration, long ticks, Mapping[] mappingCollection, Dictionary personKeyToRanges, Dictionary> idThenNormalizedRectangleToPersonContainers) { PersonContainer[]? personContainers; Dictionary? keyValuePairs; Dictionary> personKeyToMinimumDateTimeTicks = new(); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") {mappingCollection.Length:000} Set Person Ticks - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using ProgressBar progressBar = new(mappingCollection.Length, message, options); foreach (Mapping mapping in mappingCollection) { progressBar.Tick(); if (!idThenNormalizedRectangleToPersonContainers.TryGetValue(mapping.MappingFromItem.Id, out keyValuePairs)) continue; if (!keyValuePairs.TryGetValue(mapping.MappingFromLocation.NormalizedRectangle, out personContainers)) continue; foreach (PersonContainer personContainer in personContainers) { if (personContainer.Key is null) continue; if (!personKeyToMinimumDateTimeTicks.ContainsKey(personContainer.Key.Value)) personKeyToMinimumDateTimeTicks.Add(personContainer.Key.Value, new()); personKeyToMinimumDateTimeTicks[personContainer.Key.Value].Add(mapping.MappingFromItem.MinimumDateTime.Ticks); } } SetPersonKeysRanges(configuration, ticks, personKeyToMinimumDateTimeTicks, personKeyToRanges); } private static List GetNotMappedPersonContainers(Configuration configuration, List personContainers, List personKeys, long[] personKeyCollection) { List results = new(); List notMappedAndNotNamedPersonKeys = new(); List notMappedAndWithNamedPersonKeys = new(); 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); // results.AddRange(notMappedAndWithNamedPersonKeys); return results; } private static void AppendToSkipCollection(Dictionary> skipCollection, Dictionary> idThenNormalizedRectangleToPersonContainers, Dictionary> incorrectIdThenNormalizedRectangleToPersonContainers) { Dictionary? keyValuePairs; foreach (KeyValuePair> keyValuePair in incorrectIdThenNormalizedRectangleToPersonContainers) { if (!skipCollection.ContainsKey(keyValuePair.Key)) skipCollection.Add(keyValuePair.Key, new()); if (idThenNormalizedRectangleToPersonContainers.TryGetValue(keyValuePair.Key, out keyValuePairs)) { if (keyValuePairs.ContainsKey(keyValuePair.Value.ElementAt(0).Key)) continue; } skipCollection[keyValuePair.Key].AddRange(from l in keyValuePair.Value.Keys select l); } } 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, List personContainers, long[] personKeyCollection, Dictionary personKeyToPersonContainer) { 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()) { int? approximateYears = null; PersonBirthday? personBirthday; PersonContainer? personContainer; displayDirectoryName = configuration.MappingDefaultName; foreach (long personKey in personKeyCollection) { if (personKeyToPersonContainer.ContainsKey(personKey)) continue; personBirthday = IPersonBirthday.GetPersonBirthday(personKey); personContainer = new(approximateYears, personBirthday, displayDirectoryName, personKey); personKeyToPersonContainer.Add(personKey, personContainer); } } } internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, long ticks, List personContainers, string? a2PeopleContentDirectory, string eDistanceContentDirectory, Shared.Models.Methods.IMapLogicSupport mapLogicSupport, Dictionary personKeyToPersonContainer, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> idThenNormalizedRectangleToPersonContainers) { if (configuration is null) throw new NullReferenceException(nameof(configuration)); string message; int totalSeconds; List personKeys = new(); List nullablePersonKeyCollection = new(); List personKeyFormattedCollection = new(); Dictionary personKeyFormattedToNewestPersonKeyFormatted = new(); List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer = new(); List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection = new(); List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection = new(); Dictionary> incorrectIdThenNormalizedRectangleToPersonContainers = new(); SetPersonCollections(configuration, personContainers, personKeys, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection, skipCollection); personContainers.AddRange(GetNonSpecificPeopleCollection(configuration, ticks, personKeys)); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string[] ticksDirectories = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly); 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); (int unableToMatchCount, int duplicateCount) = SetCollectionsAndGetUnableToConvertCount(configuration, ticks, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedIdThenNormalizedRectangleCollection, incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection, collection); SetKeyValuePairs(configuration, personContainers, personKeyFormattedIdThenNormalizedRectangleCollection, incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection, personKeyToPersonContainer, idThenNormalizedRectangleToPersonContainers, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer, incorrectIdThenNormalizedRectangleToPersonContainers); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); message = $") {collection.Count:000} message from ticks Director(ies) - D - {duplicateCount} Duplicate Count {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); notMappedPersonContainers.AddRange(GetNotMappedPersonContainers(configuration, personContainers, personKeys, personKeyCollection)); AppendToSkipCollection(skipCollection, idThenNormalizedRectangleToPersonContainers, incorrectIdThenNormalizedRectangleToPersonContainers); if (possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Any()) mapLogicSupport.SavePossiblyNewPersonContainers(propertyConfiguration, configuration.PersonBirthdayFormat, configuration.FacesFileNameExtension, a2PeopleContentDirectory, personKeyToPersonContainer, 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 SaveContainer GetDebugSaveContainer(string directory, SortingContainer sortingContainer, Mapping mapping) { SaveContainer result; FileHolder faceFileHolder = new($"C:/{sortingContainer.Sorting.Id}.{sortingContainer.Sorting.NormalizedRectangle}"); string shortcutFile = Path.Combine(directory, $"{sortingContainer.Mapping.MappingFromLocation.DeterministicHashCodeKey}{sortingContainer.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}.debug.lnk"); result = new(directory, faceFileHolder, mapping.MappingFromItem.ResizedFileHolder, shortcutFile); return result; } 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) { } } } }