using ShellProgressBar; using System.Globalization; using System.Text.Json; using View_by_Distance.Shared.Models; namespace View_by_Distance.Map.Models.Stateless; public class ByRef { private static void SetOther(Property.Models.Configuration propertyConfiguration, Configuration configuration, string resizeFilenameExtension, Person[] people, string deterministicHashCodePeopleDirectory, List skipCollection, Dictionary personKeyAliases, List<(string, int?, PersonBirthday[], long)> peopleCollection) { long pK; string json; long personKey; PersonBirthday pB; string[] segments; const int zero = 0; int? approximateYears; string groupDirectoryName; string personKeyFormatted; PersonBirthday[] collection; string personKeyJsonFileName; List personKeys = new(); string[] personKeyDirectories; string personKeyJsonDirectory; PersonBirthday? personBirthday; string[] personDisplayDirectories; string convertedPersonKeyDirectory; string? personDisplayDirectoryName; List personBirthdays; Dictionary personKeyValuePairs = new(); foreach (Person person in people) { personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, person.Birthday); if (personKeyValuePairs.ContainsKey(personKeyFormatted)) break; personKeyValuePairs.Add(personKeyFormatted, person); } string[] groupDirectories = Directory.GetDirectories(deterministicHashCodePeopleDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string groupDirectory in groupDirectories) { groupDirectoryName = Path.GetFileName(groupDirectory); if (groupDirectoryName[zero] == '!') { skipCollection.AddRange(from l in Directory.GetFiles(groupDirectory, $"*{resizeFilenameExtension}", SearchOption.AllDirectories) select double.Parse(Path.GetFileNameWithoutExtension(l))); continue; } else if (groupDirectoryName[zero] is not '_' and not '~' and not '^') continue; skipCollection.AddRange(from l in Directory.GetFiles(groupDirectory, $"*{resizeFilenameExtension}", SearchOption.AllDirectories) select double.Parse(Path.GetFileNameWithoutExtension(l))); personDisplayDirectories = Directory.GetDirectories(groupDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string personDisplayDirectory in personDisplayDirectories) { personBirthdays = new(); personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); if (string.IsNullOrEmpty(personDisplayDirectoryName)) continue; if (groupDirectoryName[zero] != '~') approximateYears = null; else { segments = personDisplayDirectoryName.Split('~'); if (segments.Length == 1 || !int.TryParse(segments[1].Split('-')[zero], out int years)) approximateYears = null; else approximateYears = years; } personKeyDirectories = Directory.GetDirectories(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string personKeyDirectory in personKeyDirectories) { personKeyFormatted = Path.GetFileName(personKeyDirectory); if (!DateTime.TryParseExact(personKeyFormatted, "MM.dd.yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthday)) personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormatted); else { personBirthday = new PersonBirthday(birthday); personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personBirthday); convertedPersonKeyDirectory = Path.Combine(personDisplayDirectory, personKeyFormatted); if (!Directory.Exists(convertedPersonKeyDirectory)) Directory.Move(personKeyDirectory, convertedPersonKeyDirectory); } if (personBirthday is null) continue; personBirthdays.Add(personBirthday); } if (!personBirthdays.Any()) continue; foreach (string personKeyDirectory in personKeyDirectories) { personKeyFormatted = Path.GetFileName(personKeyDirectory); personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormatted); if (personBirthday is null) continue; if (personKeyValuePairs.ContainsKey(personKeyFormatted)) { personKeyJsonDirectory = Path.Combine(personDisplayDirectory, personKeyFormatted); if (!Directory.Exists(personKeyJsonDirectory)) Directory.Move(personKeyDirectory, personKeyJsonDirectory); personKeyJsonFileName = Path.Combine(personKeyJsonDirectory, $"{personKeyFormatted}.json"); json = JsonSerializer.Serialize(personKeyValuePairs[personKeyFormatted], new JsonSerializerOptions() { WriteIndented = true }); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(personKeyJsonFileName, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); } collection = personBirthdays.OrderByDescending(l => l.Value).ToArray(); personKey = collection[zero].Value.Ticks; if (personBirthdays.Count > 1) { for (int i = 1; i < collection.Length; i++) { pB = collection[i]; pK = pB.Value.Ticks; if (!personKeyAliases.ContainsKey(pK)) personKeyAliases.Add(pK, personKey); } } peopleCollection.Add(new(personDisplayDirectoryName, approximateYears, collection, personKey)); for (int i = 0; i < collection.Length; i++) { personKey = collection[i].Value.Ticks; personKeys.Add(personKey); } } } } approximateYears = null; string displayDirectoryName = propertyConfiguration.ResultAllInOne; DateTime incrementDate = new(configuration.PersonBirthdayFirstYear, 1, 1); for (int i = 0; i < 500; i++) { personKey = incrementDate.Ticks; personBirthday = new(incrementDate); incrementDate = incrementDate.AddDays(1); personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personBirthday); if (personKeys.Contains(personKey)) continue; personKeys.Add(personKey); peopleCollection.Add(new(displayDirectoryName, approximateYears, new PersonBirthday[] { personBirthday }, personKey)); } } internal static List<(string, char, string, int?, int?, List?)> DeleteEmptyDirectoriesAndGetCollection(Configuration configuration, long ticks, string zPropertyHolderContentDirectory, Dictionary> keyValuePairs) { List<(string, char, string, int?, int?, List?)> results = new(); int? id; string[] files; List? faces; const int zero = 0; string[] yearDirectories; string personKeyFormatted; string ticksDirectoryName; string? personFirstInitial; string[] personKeyDirectories; int? normalizedPixelPercentage; string[] personNameDirectories; string[] personNameLinkDirectories; string? personFirstInitialDirectory; bool keyValuePairsAny = keyValuePairs.Any(); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string[] ticksDirectories = Directory.GetDirectories(zPropertyHolderContentDirectory, "*", SearchOption.TopDirectoryOnly); string message = $") {ticksDirectories.Length:000} ticks Director(ies) - A - {totalSeconds} total second(s)"; 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); if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length) continue; 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) { personFirstInitial = Path.GetFileName(personNameDirectory)[..1]; if (personFirstInitial is null) continue; personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial.ToString()); if (personNameDirectory != personFirstInitialDirectory) Directory.Move(personNameDirectory, personFirstInitialDirectory); files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); if (personKeyFormatted == nameof(Models.MapLogic.ForceSingleImage) && files.Any()) throw new Exception($"Move personKey directories up one from {nameof(Models.MapLogic.ForceSingleImage)} and delete {nameof(Models.MapLogic.ForceSingleImage)} directory!"); if (personKeyFormatted == nameof(Sorting) && files.Any()) throw new Exception($"Move personKey directories up one from {nameof(Sorting)} and delete {nameof(Sorting)} directory!"); foreach (string file in files) { if (file.EndsWith(".lnk") || file.EndsWith(".json")) continue; (id, normalizedPixelPercentage, faces) = Shared.Models.Stateless.Methods.IMapping.GetReversedDeterministicHashCodeKey(configuration.LocationDigits, keyValuePairsAny, keyValuePairs, file); if (id is null || normalizedPixelPercentage is null) continue; results.Add(new(personKeyFormatted, personFirstInitial[0], file, id, normalizedPixelPercentage, faces)); } 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); } _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(personNameLinkDirectory); } _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(personFirstInitialDirectory); } _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(yearDirectory); } _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(personKeyDirectory); } _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(ticksDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(ticksDirectory); } return results; } private static void SetKeyValuePairs(Configuration configuration, List<(PersonBirthday, int, int)> idThenNormalizedPixelPercentageCollection, List<(PersonBirthday, int, int)> incorrectIdThenNormalizedPixelPercentageCollection, Dictionary> idThenNormalizedPixelPercentageKeyValuePairs, Dictionary> incorrectIdThenNormalizedPixelPercentageKeyValuePairs) { string check; int normalizedPixelPercentageInDecimalForm; Dictionary>> idThenNormalizedPixelPercentageScope = new(); foreach ((PersonBirthday personBirthday, int id, int normalizedPixelPercentage) in idThenNormalizedPixelPercentageCollection) { if (!idThenNormalizedPixelPercentageScope.ContainsKey(id)) idThenNormalizedPixelPercentageScope.Add(id, new()); check = normalizedPixelPercentage.ToString(); if (check.Length == configuration.LocationDigits) { if (!idThenNormalizedPixelPercentageScope[id].ContainsKey(normalizedPixelPercentage)) idThenNormalizedPixelPercentageScope[id].Add(normalizedPixelPercentage, new()); idThenNormalizedPixelPercentageScope[id][normalizedPixelPercentage].Add(personBirthday); } else { normalizedPixelPercentageInDecimalForm = int.Parse(check.PadRight(configuration.LocationDigits, '0')); if (!idThenNormalizedPixelPercentageScope[id].ContainsKey(normalizedPixelPercentageInDecimalForm)) idThenNormalizedPixelPercentageScope[id].Add(normalizedPixelPercentageInDecimalForm, new()); idThenNormalizedPixelPercentageScope[id][normalizedPixelPercentageInDecimalForm].Add(personBirthday); } } foreach (KeyValuePair>> keyValuePair in idThenNormalizedPixelPercentageScope) { idThenNormalizedPixelPercentageKeyValuePairs.Add(keyValuePair.Key, new()); foreach (KeyValuePair> innerKeyValuePair in keyValuePair.Value) idThenNormalizedPixelPercentageKeyValuePairs[keyValuePair.Key].Add(innerKeyValuePair.Key, innerKeyValuePair.Value.Distinct().ToArray()); } Dictionary>> incorrectIdThenNormalizedPixelPercentageScope = new(); foreach ((PersonBirthday personBirthday, int id, int normalizedPixelPercentage) in incorrectIdThenNormalizedPixelPercentageCollection) { if (!incorrectIdThenNormalizedPixelPercentageScope.ContainsKey(id)) incorrectIdThenNormalizedPixelPercentageScope.Add(id, new()); check = normalizedPixelPercentage.ToString(); if (check.Length == configuration.LocationDigits) { if (!incorrectIdThenNormalizedPixelPercentageScope[id].ContainsKey(normalizedPixelPercentage)) incorrectIdThenNormalizedPixelPercentageScope[id].Add(normalizedPixelPercentage, new()); incorrectIdThenNormalizedPixelPercentageScope[id][normalizedPixelPercentage].Add(personBirthday); } else { normalizedPixelPercentageInDecimalForm = int.Parse(check.PadRight(configuration.LocationDigits, '0')); if (!incorrectIdThenNormalizedPixelPercentageScope[id].ContainsKey(normalizedPixelPercentageInDecimalForm)) incorrectIdThenNormalizedPixelPercentageScope[id].Add(normalizedPixelPercentageInDecimalForm, new()); incorrectIdThenNormalizedPixelPercentageScope[id][normalizedPixelPercentageInDecimalForm].Add(personBirthday); } } foreach (KeyValuePair>> keyValuePair in incorrectIdThenNormalizedPixelPercentageScope) { incorrectIdThenNormalizedPixelPercentageKeyValuePairs.Add(keyValuePair.Key, new()); foreach (KeyValuePair> innerKeyValuePair in keyValuePair.Value) incorrectIdThenNormalizedPixelPercentageKeyValuePairs[keyValuePair.Key].Add(innerKeyValuePair.Key, innerKeyValuePair.Value.Distinct().ToArray()); } } private static string? GetCheckFile(string file, int id, int normalizedPixelPercentage) { string? result; string? fileName = Path.GetFileName(file); if (fileName is null) result = null; else { string[] segments = fileName.Split('.'); if (segments.Length != 3) result = null; else { string extensionLowered = $".{segments[2]}"; string? directoryName = Path.GetDirectoryName(file); if (string.IsNullOrEmpty(directoryName)) result = null; else result = Path.Combine(directoryName, $"{Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(id, normalizedPixelPercentage)}{extensionLowered}.json"); } } return result; } private static bool Valid(string checkFile, List faces) { bool result = false; string json; foreach (Face face in faces) { if (face.FaceEncoding is null) throw new NotSupportedException(); if (faces.Count != 1) break; result = true; if (File.Exists(checkFile)) continue; json = JsonSerializer.Serialize(face.FaceEncoding); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); } return result; } private static int SetCollectionsAndGet(Configuration configuration, long ticks, Shared.Models.Methods.IFaceDistance? distance, Dictionary personKeyAliases, List<(PersonBirthday, int, int)> idThenNormalizedPixelPercentageCollection, List<(PersonBirthday, int, int)> incorrectIdThenNormalizedPixelPercentageCollection, List<(string, char, string, int?, int?, List?)> collection) { int result = 0; long personKey; string? checkFile; List checkFaces = new(); PersonBirthday? personBirthday; int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") {collection.Count:000} ticks Director(ies) - B - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using ProgressBar progressBar = new(collection.Count, message, options); foreach ((string personKeyFormatted, char personFirstInitial, string file, int? id, int? normalizedPixelPercentage, List? faces) in collection) { progressBar.Tick(); if (id is null || normalizedPixelPercentage is null) continue; personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormatted); if (personBirthday is null) continue; personKey = personBirthday.Value.Ticks; if (personKeyAliases.ContainsKey(personKey)) { personKey = personKeyAliases[personKey]; personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKey); } if (faces is not null) { checkFaces.Clear(); foreach (Face face in faces) { if (face.Mapping is null) throw new NotSupportedException(); if (normalizedPixelPercentage.Value != face.Mapping.MappingFromLocation.NormalizedPixelPercentage) continue; checkFaces.Add(face); } checkFile = GetCheckFile(file, id.Value, normalizedPixelPercentage.Value); if (string.IsNullOrEmpty(checkFile)) { result++; continue; } if (checkFaces.Count != 1 && distance is not null && File.Exists(checkFile)) { checkFaces.Clear(); checkFaces.AddRange(distance.GetMatchingFaces(configuration.FaceDistanceTolerance, checkFile, faces)); } if (!checkFaces.Any()) { result++; continue; } if (checkFaces.Count != 1) { result++; continue; } if (!Valid(checkFile, checkFaces)) { result++; continue; } } if (personFirstInitial != '!') idThenNormalizedPixelPercentageCollection.Add(new(personBirthday, id.Value, normalizedPixelPercentage.Value)); else incorrectIdThenNormalizedPixelPercentageCollection.Add(new(personBirthday, id.Value, normalizedPixelPercentage.Value)); } return result; } internal static void Set(Property.Models.Configuration propertyConfiguration, Configuration? configuration, long ticks, string resizeFilenameExtension, Person[] people, string zPropertyHolderContentDirectory, string zPropertyHolderPeopleContentDirectory, List distinctFilteredFaces, Shared.Models.Methods.IFaceDistance? distance, List skipCollection, Dictionary peopleKeyValuePairs, List notMappedPersonKeys, Dictionary> idThenNormalizedPixelPercentageKeyValuePairs, Dictionary> incorrectIdThenNormalizedPixelPercentageKeyValuePairs) { if (configuration is null) throw new NullReferenceException(nameof(configuration)); Dictionary personKeyAliases = new(); Dictionary> keyValuePairs = new(); List idThenNormalizedPixelPercentagePersonKeys = new(); List<(string, int?, PersonBirthday[], long)> peopleCollection = new(); List<(PersonBirthday, int, int)> idThenNormalizedPixelPercentageCollection = new(); List<(PersonBirthday, int, int)> incorrectIdThenNormalizedPixelPercentageCollection = new(); SetOther(propertyConfiguration, configuration, resizeFilenameExtension, people, zPropertyHolderPeopleContentDirectory, skipCollection, personKeyAliases, peopleCollection); foreach (Face face in distinctFilteredFaces) { if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) throw new NotSupportedException(); if (face.Mapping is null) throw new NotSupportedException(); if (!keyValuePairs.ContainsKey(face.Mapping.MappingFromItem.Id)) keyValuePairs.Add(face.Mapping.MappingFromItem.Id, new()); keyValuePairs[face.Mapping.MappingFromItem.Id].Add(face); } List<(string, char, string, int?, int?, List?)> collection = DeleteEmptyDirectoriesAndGetCollection(configuration, ticks, zPropertyHolderContentDirectory, keyValuePairs); int unableToMatchCount = SetCollectionsAndGet(configuration, ticks, distance, personKeyAliases, idThenNormalizedPixelPercentageCollection, incorrectIdThenNormalizedPixelPercentageCollection, collection); SetKeyValuePairs(configuration, idThenNormalizedPixelPercentageCollection, incorrectIdThenNormalizedPixelPercentageCollection, idThenNormalizedPixelPercentageKeyValuePairs, incorrectIdThenNormalizedPixelPercentageKeyValuePairs); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") {collection.Count:000} ticks Director(ies) - C - {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 idThenNormalizedPixelPercentageKeyValuePairs) { progressBar.Tick(); foreach (KeyValuePair keyValue in keyValuePair.Value) idThenNormalizedPixelPercentagePersonKeys.AddRange(from l in keyValue.Value select l.Value.Ticks); } idThenNormalizedPixelPercentagePersonKeys = idThenNormalizedPixelPercentagePersonKeys.Distinct().ToList(); if (peopleCollection.Any()) { foreach ((string displayDirectoryName, int? approximateYears, PersonBirthday[] personBirthdays, long personKey) in peopleCollection) { if (peopleKeyValuePairs.ContainsKey(personKey)) { if (peopleKeyValuePairs[personKey].DisplayDirectoryName == displayDirectoryName) continue; throw new NotImplementedException(); } if (!idThenNormalizedPixelPercentagePersonKeys.Contains(personKey)) notMappedPersonKeys.Add(personKey); else peopleKeyValuePairs.Add(personKey, new(displayDirectoryName, approximateYears, personBirthdays, personKey)); } } if (idThenNormalizedPixelPercentagePersonKeys.Any()) { int? approximateYears = null; PersonBirthday? personBirthday; string displayDirectoryName = propertyConfiguration.ResultAllInOne; foreach (long personKey in idThenNormalizedPixelPercentagePersonKeys) { if (!peopleKeyValuePairs.ContainsKey(personKey)) { personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKey); peopleKeyValuePairs.Add(personKey, new(displayDirectoryName, approximateYears, new PersonBirthday[] { personBirthday }, personKey)); } } } } }