diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index a86f3cd..b230b1f 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Configuration; using Phares.Shared; using ShellProgressBar; +using System.Collections.ObjectModel; using System.Drawing.Imaging; using View_by_Distance.Distance.Models; using View_by_Distance.Face.Models; @@ -30,8 +31,8 @@ public partial class DlibDotNet private readonly List _Exceptions; private readonly IsEnvironment _IsEnvironment; private readonly bool _PropertyRootExistedBefore; - private readonly PersonContainer[] _PersonContainers; private readonly Models.Configuration _Configuration; + private readonly List _PersonContainers; private readonly bool _ArgZeroIsConfigurationRootDirectory; private readonly Map.Models.Configuration _MapConfiguration; private readonly string[]? _GenealogicalDataCommunicationFooterLines; @@ -104,7 +105,7 @@ public partial class DlibDotNet { _GenealogicalDataCommunicationFooterLines = null; _GenealogicalDataCommunicationHeaderLines = null; - _PersonContainers = Array.Empty(); + _PersonContainers = new(); } else { @@ -270,7 +271,7 @@ public partial class DlibDotNet return result; } - private void SetMapping(Dictionary>> idToLocationContainers, MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem, List? mappingFromPhotoPrismCollection, List faces) + private void SetMapping(ReadOnlyDictionary>> idToLocationContainers, MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem, List? mappingFromPhotoPrismCollection, List faces) { string? model; Mapping mapping; @@ -328,7 +329,7 @@ public partial class DlibDotNet private void FullParallelForWork(A_Property propertyLogic, B_Metadata metadata, - Dictionary>> idToLocationContainers, + ReadOnlyDictionary>> idToLocationContainers, MapLogic mapLogic, string outputResolution, string cResultsFullGroupDirectory, @@ -457,7 +458,7 @@ public partial class DlibDotNet private int FullParallelWork(int maxDegreeOfParallelism, A_Property propertyLogic, B_Metadata metadata, - Dictionary>> idToLocationContainers, + ReadOnlyDictionary>> idToLocationContainers, MapLogic mapLogic, string outputResolution, string cResultsFullGroupDirectory, @@ -598,7 +599,7 @@ public partial class DlibDotNet return new(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory); } - private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, int t, Container[] containers, A_Property propertyLogic, B_Metadata metadata, string eDistanceContentDirectory, Dictionary> fileNameToCollection, Dictionary>> idToLocationContainers, MapLogic mapLogic) + private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, int t, Container[] containers, A_Property propertyLogic, B_Metadata metadata, string eDistanceContentDirectory, Dictionary> fileNameToCollection, ReadOnlyDictionary>> idToLocationContainers, MapLogic mapLogic) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); @@ -676,11 +677,11 @@ public partial class DlibDotNet } } - private (List, List) GetFilteredDistinct(string argZero, Container[] containers) + private List GetFilteredDistinct(string argZero, Container[] containers) { - List resultIds = new(); - List resultFaces = new(); + List results = new(); Item[] filteredItems; + List distinct = new(); foreach (Container container in containers) { if (!container.Items.Any()) @@ -694,18 +695,18 @@ public partial class DlibDotNet { if (item.Property?.Id is null || item.ResizedFileHolder is null) continue; - if (resultIds.Contains(item.Property.Id.Value)) + if (distinct.Contains(item.Property.Id.Value)) continue; - resultIds.Add(item.Property.Id.Value); + distinct.Add(item.Property.Id.Value); foreach (Shared.Models.Face face in item.Faces) { if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) continue; - resultFaces.Add(face); + results.Add(face); } } } - return new(resultIds, resultFaces); + return results; } private List GetItems(string argZero, Container[] containers) @@ -859,7 +860,7 @@ public partial class DlibDotNet return result; } - private static void LookForAbandoned(Dictionary>> idToLocationContainers, List distinctFilteredIds) + private static void LookForAbandoned(ReadOnlyDictionary>> idToLocationContainers, List distinctFilteredIds) { List renameCollection = new(); foreach (KeyValuePair>> idToCollection in idToLocationContainers) @@ -874,18 +875,71 @@ public partial class DlibDotNet } } if (renameCollection.Any()) + Shared.Models.Stateless.Methods.IDirectory.MoveFiles(renameCollection, "()", "(abd)"); + } + + private static void LookForAbandoned(List distinctFilteredIds, string directory, string directoryName) + { + string fileNameWithoutExtension; + List renameCollection = new(); + string[] distinctFilteredIdsValues = distinctFilteredIds.Select(l => l.ToString()).ToArray(); + string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories); + foreach (string file in files) { - string checkFile; - foreach (string file in renameCollection) + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(file))); + if (distinctFilteredIdsValues.Contains(fileNameWithoutExtension)) + continue; + if (!Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension)) + continue; + renameCollection.Add(file); + } + if (renameCollection.Any()) + { + if (directoryName.Length == 2) + Shared.Models.Stateless.Methods.IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[0]}abd{directoryName[^1]}"); + else if (directoryName.Length == 4) + Shared.Models.Stateless.Methods.IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[..2]}abd{directoryName[^2]}"); + else + throw new NotSupportedException(); + } + } + + private void LookForAbandoned(Container[] containers, ReadOnlyDictionary>> idToLocationContainers) + { + string[] directories; + string? directoryName; + string cResultsFullGroupDirectory; + string dResultsFullGroupDirectory; + string d2ResultsFullGroupDirectory; + List distinctFilteredIds = Shared.Models.Stateless.Methods.IContainer.GetFilteredDistinct(_Configuration.PropertyConfiguration, containers); + LookForAbandoned(idToLocationContainers, distinctFilteredIds); + foreach (string outputResolution in _Configuration.OutputResolutions) + { + (cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution); + directories = Directory.GetDirectories(cResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string directory in directories) { - if (!File.Exists(file)) + directoryName = Path.GetFileName(directory); + if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4)) continue; - checkFile = $"{file}.abd"; - if (File.Exists(checkFile)) - continue; - File.Move(file, checkFile); + LookForAbandoned(distinctFilteredIds, directory, directoryName); + } + directories = Directory.GetDirectories(dResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string directory in directories) + { + directoryName = Path.GetFileName(directory); + if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4)) + continue; + LookForAbandoned(distinctFilteredIds, directory, directoryName); + } + directories = Directory.GetDirectories(d2ResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string directory in directories) + { + directoryName = Path.GetFileName(directory); + if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4)) + continue; + LookForAbandoned(distinctFilteredIds, directory, directoryName); } - throw new Exception($"Renamed {renameCollection.Count}(s) files!"); } } @@ -906,14 +960,14 @@ public partial class DlibDotNet Dictionary> personKeyToIds; Dictionary> fileNameToCollection; (aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); - Dictionary>> idToLocationContainers = new(); string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "{}"); a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])"); eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), "()"); fPhotoPrismContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), "()"); fPhotoPrismSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), "{}"); propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory); - MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _PersonContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory, idToLocationContainers); + MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, new(_PersonContainers), ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); + _PersonContainers.AddRange(Shared.Models.Stateless.Methods.IPersonContainer.GetNonSpecificPeopleCollection(_Configuration.MappingDefaultName, _Configuration.PersonBirthdayFirstYear, _Configuration.PersonCharacters.ToArray(), _PersonContainers, ticks)); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") Building Container(s) - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; @@ -949,20 +1003,20 @@ public partial class DlibDotNet personKeyToIds = mapLogic.GetPersonKeyToIds(); if (!string.IsNullOrEmpty(_Configuration.GenealogicalDataCommunicationFile) && !string.IsNullOrEmpty(a2PeopleContentDirectory) && _GenealogicalDataCommunicationHeaderLines is not null && _GenealogicalDataCommunicationFooterLines is not null && _GenealogicalDataCommunicationHeaderLines.Any() && _GenealogicalDataCommunicationFooterLines.Any()) Shared.Models.Stateless.Methods.IGenealogicalDataCommunication.CreateTree(_Configuration.MappingDefaultName, _Configuration.PersonBirthdayFormat, _Configuration.PropertyConfiguration.ResultAllInOne, _PersonContainers, _GenealogicalDataCommunicationHeaderLines, _GenealogicalDataCommunicationFooterLines, ticks, a2PeopleContentDirectory, personKeyToIds); + ReadOnlyDictionary>> idToLocationContainers = mapLogic.GetIdToLocationContainers(); fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = new() : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory); FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, eDistanceContentDirectory, fileNameToCollection, idToLocationContainers, mapLogic); + LookForAbandoned(containers, idToLocationContainers); _Distance.Clear(); if (!personKeyToIds.Any()) personKeyToIds = mapLogic.GetPersonKeyToIds(); - (List distinctFilteredIds, List distinctFilteredFaces) = GetFilteredDistinct(argZero, containers); - LookForAbandoned(idToLocationContainers, distinctFilteredIds); + List distinctFilteredFaces = GetFilteredDistinct(argZero, containers); Mapping[] mappingCollection = Map.Models.Stateless.Methods.IMapLogic.GetSelectedMappingCollection(distinctFilteredFaces); int totalNotMapped = mapLogic.UpdateMappingFromPerson(mappingCollection); string json = System.Text.Json.JsonSerializer.Serialize(mappingCollection); File.WriteAllText(Path.Combine(eDistanceContentDirectory, $"{ticks}.json"), json); for (int i = 1; i < 5; i++) _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(eDistanceContentDirectory); - _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(eDistanceContentDirectory); foreach (string outputResolution in _Configuration.OutputResolutions) { if (_PropertyRootExistedBefore) diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index f29da65..c83133c 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -16,6 +16,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic protected readonly ReadOnlyDictionary> _SkipCollection; protected readonly ReadOnlyDictionary> _SkipNotSkipCollection; protected readonly ReadOnlyDictionary _PersonKeyToPersonContainer; + protected readonly List> _LocationContainers; protected readonly ReadOnlyDictionary> _IdThenNormalizedRectangleToPersonContainers; public Dictionary KeyValuePairs => throw new NotImplementedException(); @@ -27,7 +28,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic private readonly string _EDistanceContentTicksDirectory; private readonly Shared.Models.Properties.IPropertyConfiguration _PropertyConfiguration; - public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, PersonContainer[] personContainers, long ticks, string a2PeopleSingletonDirectory, string eDistanceContentDirectory, Dictionary>> idToLocationContainers) + public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, ReadOnlyCollection personContainers, long ticks, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) { _Ticks = ticks; _Configuration = configuration; @@ -35,8 +36,6 @@ public class MapLogic : Shared.Models.Methods.IMapLogic _PropertyConfiguration = propertyConfiguration; if (_Log is null) { } - if (idToLocationContainers is null) - throw new NullReferenceException(nameof(idToLocationContainers)); if (propertyConfiguration.VerifyToSeason is null || !propertyConfiguration.VerifyToSeason.Any()) throw new NullReferenceException(nameof(propertyConfiguration.VerifyToSeason)); string json; @@ -46,30 +45,29 @@ public class MapLogic : Shared.Models.Methods.IMapLogic List notMappedPersonContainers = new(); Dictionary> skipNotSkipCollection = new(); Dictionary personKeyToPersonContainer = new(); + List> locationContainers = new(); string? rootDirectoryParent = Path.GetDirectoryName(propertyConfiguration.RootDirectory); string eDistanceContentTicksDirectory = Path.Combine(eDistanceContentDirectory, $"({ticks})"); Dictionary> idThenNormalizedRectangleToPersonContainers = new(); + Dictionary>> idToLocationContainers = new(); if (string.IsNullOrEmpty(rootDirectoryParent)) throw new NullReferenceException(nameof(rootDirectoryParent)); if (!Directory.Exists(eDistanceContentDirectory)) _ = Directory.CreateDirectory(eDistanceContentDirectory); if (configuration is not null) { - List personContainerCollection = new(personContainers); Stateless.MapLogic.Set(maxDegreeOfParallelism, configuration, ticks, - personContainerCollection, + personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory, personKeyToPersonContainer, notMappedPersonContainers, skipCollection, skipNotSkipCollection, - idToLocationContainers, + locationContainers, idThenNormalizedRectangleToPersonContainers); - if (personContainerCollection.Count == personContainers.Length) - throw new NotSupportedException(); } foreach (string propertyContentCollectionFile in propertyConfiguration.PropertyContentCollectionFiles) { @@ -84,6 +82,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic throw new NullReferenceException(nameof(collection)); } _SkipCollection = new(skipCollection); + _LocationContainers = locationContainers; _SkipNotSkipCollection = new(skipNotSkipCollection); _PersonKeyToPersonContainer = new(personKeyToPersonContainer); _EDistanceContentTicksDirectory = eDistanceContentTicksDirectory; @@ -97,6 +96,19 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return result; } + public ReadOnlyDictionary>> GetIdToLocationContainers() + { + Dictionary>> results = new(); + foreach (LocationContainer locationContainer in _LocationContainers) + { + if (!results.ContainsKey(locationContainer.Id)) + results.Add(locationContainer.Id, new()); + results[locationContainer.Id].Add(locationContainer); + } + _LocationContainers.Clear(); + return new(results); + } + public Dictionary> GetPersonKeyToIds() { Dictionary> results = new(); @@ -972,7 +984,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return new(personKeyFormatted, personBirthday); } - private List GetPersonKeyFormattedCollection(string[] jLinks, string a2PeopleContentDirectory, PersonContainer[] personContainers, Dictionary> personKeyToIds) + private List GetPersonKeyFormattedCollection(string[] jLinks, string a2PeopleContentDirectory, List personContainers, Dictionary> personKeyToIds) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -1030,7 +1042,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return results; } - private (int, FileHolder, int, string, string, string, string)[] GetCollectionForSaveFilteredOriginalImagesFromJLinks(string[] jLinks, string a2PeopleContentDirectory, PersonContainer[] personContainers, Mapping[] mappingCollection, Dictionary> personKeyToIds) + private (int, FileHolder, int, string, string, string, string)[] GetCollectionForSaveFilteredOriginalImagesFromJLinks(string[] jLinks, string a2PeopleContentDirectory, List personContainers, Mapping[] mappingCollection, Dictionary> personKeyToIds) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -1091,7 +1103,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return results; } - public void SaveFilteredOriginalImagesFromJLinks(string[] jLinks, PersonContainer[] personContainers, string a2PeopleContentDirectory, Dictionary> personKeyToIds, Mapping[] mappingCollection, int totalNotMapped) + public void SaveFilteredOriginalImagesFromJLinks(string[] jLinks, List personContainers, string a2PeopleContentDirectory, Dictionary> personKeyToIds, Mapping[] mappingCollection, int totalNotMapped) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -1110,7 +1122,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic SaveContainers(saveIndividually, totalNotMapped, null, saveContainers); } - private List GetCollectionForSaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, Dictionary> personKeyToIds, Dictionary>> idToLocationContainers, Mapping[] mappingCollection) + private List GetCollectionForSaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, Dictionary> personKeyToIds, ReadOnlyDictionary>> idToLocationContainers, Mapping[] mappingCollection) { List results = new(); if (_Configuration is null) @@ -1166,7 +1178,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return results; } - public void SaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, Dictionary> personKeyToIds, Dictionary>> idToLocationContainers, Mapping[] mappingCollection) + public void SaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, Dictionary> personKeyToIds, ReadOnlyDictionary>> idToLocationContainers, Mapping[] mappingCollection) { string hiddenFile; WindowsShortcut windowsShortcut; diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index 1881545..26ae7d6 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -1,5 +1,6 @@ using Humanizer; using ShellProgressBar; +using System.Collections.ObjectModel; using System.Diagnostics; using System.Drawing; using System.Text.Json; @@ -12,36 +13,9 @@ 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, configuration.PersonCharacters.ToArray(), configuration.MappingDefaultName, personKey, personBirthday); - personContainer = new(approximateYears, new PersonBirthday[] { personBirthday }, personDisplayDirectoryAllFiles, configuration.MappingDefaultName, personKey, person); - results.Add(personContainer); - } - return results; - } - - private static void SetPersonCollections(Configuration configuration, List personContainers, string? a2PeopleSingletonDirectory, List personKeys, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List personKeyFormattedCollection, Dictionary> skipCollection, Dictionary> skipNotSkipCollection) + private static void SetPersonCollections(Configuration configuration, ReadOnlyCollection personContainers, string? a2PeopleSingletonDirectory, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List personKeyFormattedCollection, Dictionary> skipCollection, Dictionary> skipNotSkipCollection) { int? id; - long personKey; int? normalizedRectangle; string personKeyFormatted; string newestPersonKeyFormatted; @@ -72,11 +46,6 @@ internal abstract class MapLogic 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); @@ -316,7 +285,7 @@ internal abstract class MapLogic return results.ToArray(); } - private static void SetKeyValuePairs(Configuration configuration, List personContainers, Dictionary> personKeyToPersonContainerCollection, Dictionary personKeyFormattedToPersonContainer, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection, Dictionary personKeyToPersonContainer, Dictionary> idThenNormalizedRectangleToPersonContainers, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) + 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; @@ -394,16 +363,14 @@ internal abstract class MapLogic return results; } - private static (int, int) SetCollectionsAndGetUnableToConvertCount(Configuration configuration, long ticks, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection, List<(string, string[], string)> collection) + 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; - string checkFile; 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)"; @@ -414,16 +381,9 @@ internal abstract class MapLogic progressBar.Tick(); if (!personKeyFormattedToNewestPersonKeyFormatted.TryGetValue(personKeyFormatted, out newestPersonKeyFormatted)) { - if (!personDisplayDirectoryNames.Any() || IPerson.IsDefaultName(configuration.MappingDefaultName, personDisplayDirectoryNames[^1])) - newestPersonKeyFormatted = personKeyFormatted; - else - { - checkFile = $"{mappedFaceFile}.abd"; - if (File.Exists(checkFile)) - continue; - File.Move(mappedFaceFile, checkFile); + 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) @@ -441,20 +401,15 @@ internal abstract class MapLogic continue; personKeyFormattedIdThenNormalizedRectangleCollection.Add(new(newestPersonKeyFormatted, personDisplayDirectoryNames, id.Value, normalizedRectangle.Value)); } - if (duplicateMappedFaceFiles.Any()) - { - duplicateMappedFaceFiles.Sort(); - if (duplicateMappedFaceFiles.Any()) - { } - } - return new(result, duplicateMappedFaceFiles.Count); + return result; } - private static List GetNotMappedPersonContainers(Configuration configuration, List personContainers, List personKeys, long[] personKeyCollection) + 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()) @@ -484,7 +439,7 @@ internal abstract class MapLogic return result; } - private static void SetPersonKeyToPersonContainer(Configuration configuration, List personContainers, long[] personKeyCollection, Dictionary personKeyToPersonContainer, Dictionary> personKeyToPersonContainerCollection) + private static void SetPersonKeyToPersonContainer(Configuration configuration, ReadOnlyCollection personContainers, long[] personKeyCollection, Dictionary personKeyToPersonContainer, Dictionary> personKeyToPersonContainerCollection) { string? displayDirectoryName; foreach (PersonContainer personContainer in personContainers) @@ -601,7 +556,7 @@ internal abstract class MapLogic return results; } - private static List<(long, string)> GetDisplayDirectoryAllFiles(string fileNameExtension, List personContainers) + private static List<(long, string)> GetDisplayDirectoryAllFiles(string fileNameExtension, ReadOnlyCollection personContainers) { List<(long, string)> results = new(); List distinct = new(); @@ -622,7 +577,7 @@ internal abstract class MapLogic return results; } - private static List<(long PersonKey, string File)> GetCollection(Configuration configuration, List personContainers, List<(string, string[], string)> collection) + 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; @@ -757,7 +712,7 @@ internal abstract class MapLogic } } - private static void SetLocationContainers(int maxDegreeOfParallelism, Configuration configuration, long ticks, List personContainers, string eDistanceContentDirectory, Dictionary>> idToLocationContainers, List<(string, string[], string)> sourceCollection) + 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); @@ -775,19 +730,13 @@ internal abstract class MapLogic }); } LookForPossibleDuplicates(configuration, results); - foreach (LocationContainer locationContainer in results) - { - if (!idToLocationContainers.ContainsKey(locationContainer.Id)) - idToLocationContainers.Add(locationContainer.Id, new()); - idToLocationContainers[locationContainer.Id].Add(locationContainer); - } + return results; } - internal static void Set(int maxDegreeOfParallelism, Configuration configuration, long ticks, List personContainers, string? a2PeopleSingletonDirectory, string eDistanceContentDirectory, Dictionary personKeyToPersonContainer, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> skipNotSkipCollection, Dictionary>> idToLocationContainers, Dictionary> idThenNormalizedRectangleToPersonContainers) + 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 personKeys = new(); List nullablePersonKeyCollection = new(); List personKeyFormattedCollection = new(); Dictionary personKeyFormattedToNewestPersonKeyFormatted = new(); @@ -796,16 +745,16 @@ internal abstract class MapLogic string[] ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(eDistanceContentDirectory); List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection = new(); List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer = new(); - SetPersonCollections(configuration, personContainers, a2PeopleSingletonDirectory, personKeys, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection, skipCollection, skipNotSkipCollection); - personContainers.AddRange(GetNonSpecificPeopleCollection(configuration, ticks, personKeys)); + 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); - SetLocationContainers(maxDegreeOfParallelism, configuration, ticks, personContainers, eDistanceContentDirectory, idToLocationContainers, collection); - (int unableToMatchCount, int duplicateCount) = SetCollectionsAndGetUnableToConvertCount(configuration, ticks, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedIdThenNormalizedRectangleCollection, collection); + 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 - {duplicateCount} Duplicate Count {unableToMatchCount} Unable To Match Count / {collection.Count} Collection - {totalSeconds} total second(s)"; + 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)) { @@ -818,7 +767,7 @@ internal abstract class MapLogic } 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, personKeys, personKeyCollection)); + notMappedPersonContainers.AddRange(GetNotMappedPersonContainers(configuration, personContainers, personKeyCollection)); if (possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Any()) SavePossiblyNewPersonContainers(configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), configuration.FacesFileNameExtension, a2PeopleSingletonDirectory, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); } diff --git a/Shared/Models/Stateless/Methods/Container.cs b/Shared/Models/Stateless/Methods/Container.cs index 8649ab0..79eaa56 100644 --- a/Shared/Models/Stateless/Methods/Container.cs +++ b/Shared/Models/Stateless/Methods/Container.cs @@ -162,6 +162,19 @@ internal abstract class Container return results; } + private static void CreateShell(Properties.IPropertyConfiguration propertyConfiguration, List directories) + { + string checkDirectory; + int startIndex = propertyConfiguration.RootDirectory.Length; + foreach (string directory in directories) + { + checkDirectory = directory.Insert(startIndex, "-Shell"); + if (Directory.Exists(checkDirectory)) + continue; + _ = Directory.CreateDirectory(checkDirectory); + } + } + internal static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) { List results = new(); @@ -169,6 +182,7 @@ internal abstract class Container List? items; Models.Container container; const string extension = ".json"; + List directories = new(); const string fileSearchFilter = "*"; const string directorySearchFilter = "*"; Dictionary> directoryToItems = new(); @@ -180,6 +194,8 @@ internal abstract class Container directory = Path.GetDirectoryName(files.First()); if (directory is null) continue; + if (!directories.Contains(directory)) + directories.Add(directory); if (!directoryToItems.TryGetValue(directory, out items)) { directoryToItems.Add(directory, new()); @@ -187,6 +203,7 @@ internal abstract class Container throw new Exception(); } } + CreateShell(propertyConfiguration, directories); List filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filesCollection); List collection = GetFilePairs(propertyConfiguration, aPropertySingletonDirectory, extension, filePairs); foreach (FilePair filePair in collection) @@ -211,4 +228,27 @@ internal abstract class Container return (collection.Count, results.ToArray()); } + internal static List GetFilteredDistinct(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) + { + List results = new(); + Models.Item[] filteredItems; + foreach (Models.Container container in containers) + { + if (!container.Items.Any()) + continue; + filteredItems = GetFilterItems(propertyConfiguration, container); + if (!filteredItems.Any()) + continue; + foreach (Models.Item item in filteredItems) + { + if (item.Property?.Id is null || item.ResizedFileHolder is null) + continue; + if (results.Contains(item.Property.Id.Value)) + continue; + results.Add(item.Property.Id.Value); + } + } + return results; + } + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs b/Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs index a600f22..7e11da9 100644 --- a/Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs +++ b/Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs @@ -332,7 +332,7 @@ internal abstract class GenealogicalDataCommunication _ = IPath.WriteAllText(Path.Combine(directory, $"{personKeyFormatted}.pged"), text, updateDateWhenMatches: false, compareBeforeWrite: true); } - internal static void CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, Models.PersonContainer[] personContainers, string[] genealogicalDataCommunicationHeaderLines, string[] genealogicalDataCommunicationFooterLines, long ticks, string a2PeopleContentDirectory, Dictionary> personKeyToIds) + internal static void CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, List personContainers, string[] genealogicalDataCommunicationHeaderLines, string[] genealogicalDataCommunicationFooterLines, long ticks, string a2PeopleContentDirectory, Dictionary> personKeyToIds) { string by; string[] matches; diff --git a/Shared/Models/Stateless/Methods/IContainer.cs b/Shared/Models/Stateless/Methods/IContainer.cs index fcbb717..6a5b59d 100644 --- a/Shared/Models/Stateless/Methods/IContainer.cs +++ b/Shared/Models/Stateless/Methods/IContainer.cs @@ -31,6 +31,11 @@ public interface IContainer (int, Models.Container[]) TestStatic_GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) => GetContainers(propertyConfiguration, aPropertySingletonDirectory); static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) => - Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory); + Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory); + + List TestStatic_GetFilteredDistinct(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) => + GetFilteredDistinct(propertyConfiguration, containers); + static List GetFilteredDistinct(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) => + Container.GetFilteredDistinct(propertyConfiguration, containers); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IDirectory.cs b/Shared/Models/Stateless/Methods/IDirectory.cs index 66b6dbb..a3ef9cf 100644 --- a/Shared/Models/Stateless/Methods/IDirectory.cs +++ b/Shared/Models/Stateless/Methods/IDirectory.cs @@ -36,4 +36,9 @@ public interface IDirectory static List GetFiles(List filesCollection, IReadOnlyDictionary> fileNamesToFiles, string extension, IReadOnlyDictionary> compareFileNamesToFiles) => XDirectory.GetFiles(filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles); + void TestStatic_MoveFiles(List files, string find, string replace) => + MoveFiles(files, find, replace); + static void MoveFiles(List files, string find, string replace) => + XDirectory.MoveFiles(files, find, replace); + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs b/Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs index b5ee030..856b029 100644 --- a/Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs +++ b/Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs @@ -30,9 +30,9 @@ public interface IGenealogicalDataCommunication static (string[] headerLines, Dictionary> individuals, string[] footerLines) GetIndividuals(string genealogicalDataCommunicationFile, bool requireNickName) => GenealogicalDataCommunication.GetIndividuals(genealogicalDataCommunicationFile, requireNickName); - void TestStatic_CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, Models.PersonContainer[] personContainers, string[] genealogicalDataCommunicationHeaderLines, string[] genealogicalDataCommunicationFooterLines, long ticks, string a2PeopleContentDirectory, Dictionary> personKeyToIds) => + void TestStatic_CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, List personContainers, string[] genealogicalDataCommunicationHeaderLines, string[] genealogicalDataCommunicationFooterLines, long ticks, string a2PeopleContentDirectory, Dictionary> personKeyToIds) => CreateTree(mappingDefaultName, personBirthdayFormat, resultAllInOne, personContainers, genealogicalDataCommunicationHeaderLines, genealogicalDataCommunicationFooterLines, ticks, a2PeopleContentDirectory, personKeyToIds); - static void CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, Models.PersonContainer[] personContainers, string[] genealogicalDataCommunicationHeaderLines, string[] genealogicalDataCommunicationFooterLines, long ticks, string a2PeopleContentDirectory, Dictionary> personKeyToIds) => + static void CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, List personContainers, string[] genealogicalDataCommunicationHeaderLines, string[] genealogicalDataCommunicationFooterLines, long ticks, string a2PeopleContentDirectory, Dictionary> personKeyToIds) => GenealogicalDataCommunication.CreateTree(mappingDefaultName, personBirthdayFormat, resultAllInOne, personContainers, genealogicalDataCommunicationHeaderLines, genealogicalDataCommunicationFooterLines, ticks, a2PeopleContentDirectory, personKeyToIds); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPersonContainer.cs b/Shared/Models/Stateless/Methods/IPersonContainer.cs index 6bf5d95..be93209 100644 --- a/Shared/Models/Stateless/Methods/IPersonContainer.cs +++ b/Shared/Models/Stateless/Methods/IPersonContainer.cs @@ -5,9 +5,19 @@ public interface IPersonContainer // ... - Models.PersonContainer[] TestStatic_GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) => + List TestStatic_GetPersonKeys(IEnumerable personContainers) => + GetPersonKeys(personContainers); + static List GetPersonKeys(IEnumerable personContainers) => + PersonContainer.GetPersonKeys(personContainers); + + List TestStatic_GetNonSpecificPeopleCollection(string mappingDefaultName, int personBirthdayFirstYear, char[] personCharacters, List personContainers, long ticks) => + GetNonSpecificPeopleCollection(mappingDefaultName, personBirthdayFirstYear, personCharacters, personContainers, ticks); + static List GetNonSpecificPeopleCollection(string mappingDefaultName, int personBirthdayFirstYear, char[] personCharacters, List personContainers, long ticks) => + PersonContainer.GetNonSpecificPeopleCollection(mappingDefaultName, personBirthdayFirstYear, personCharacters, personContainers, ticks); + + List TestStatic_GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) => GetPersonContainers(storage, mappingDefaultName, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals); - static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) => + static List GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) => PersonContainer.GetPersonContainers(storage, mappingDefaultName, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals); List<(long?, string)> TestStatic_GetDisplay(string personBirthdayFormat, Models.PersonContainer personContainer) => diff --git a/Shared/Models/Stateless/Methods/IProperty.cs b/Shared/Models/Stateless/Methods/IProperty.cs index 769d415..5fb21d7 100644 --- a/Shared/Models/Stateless/Methods/IProperty.cs +++ b/Shared/Models/Stateless/Methods/IProperty.cs @@ -56,10 +56,15 @@ public interface IProperty static DateTime? GetDateTimeFromName(Models.FileHolder fileHolder) => Property.GetDateTimeFromName(fileHolder); + bool TestStatic_NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) => + NameWithoutExtensionIsIdFormat(fileNameWithoutExtension); + static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) => + Property.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension); + bool TestStatic_NameWithoutExtensionIsIdFormat(Models.FileHolder fileHolder) => NameWithoutExtensionIsIdFormat(fileHolder); static bool NameWithoutExtensionIsIdFormat(Models.FileHolder fileHolder) => - Property.NameWithoutExtensionIsIdFormat(fileHolder); + NameWithoutExtensionIsIdFormat(fileHolder.NameWithoutExtension); List TestStatic_GetDateTimes(Models.Property property) => GetDateTimes(property); diff --git a/Shared/Models/Stateless/Methods/PersonContainer.cs b/Shared/Models/Stateless/Methods/PersonContainer.cs index 5c9c4d7..90cb2ef 100644 --- a/Shared/Models/Stateless/Methods/PersonContainer.cs +++ b/Shared/Models/Stateless/Methods/PersonContainer.cs @@ -277,9 +277,9 @@ internal abstract class PersonContainer return results; } - private static Models.PersonContainer[] GetPersonContainersGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, string[] groupDirectories) + private static List GetPersonContainersGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, string[] groupDirectories) { - Models.PersonContainer[] results; + List results; const int zero = 0; string groupDirectoryName; List collection; @@ -292,13 +292,13 @@ internal abstract class PersonContainer collection = GetPersonContainersInnerGroups(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, groupDirectory, groupDirectoryName); personContainers.AddRange(collection); } - results = (from l in personContainers orderby l.Key is not null, l.Key select l).ToArray(); + results = (from l in personContainers orderby l.Key is not null, l.Key select l).ToList(); return results; } - internal static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) + internal static List GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) { - Models.PersonContainer[] results; + List results; string a2PeopleSingletonDirectory = Path.Combine(storage.PeopleRootDirectory, "{}"); if (!Directory.Exists(a2PeopleSingletonDirectory)) _ = Directory.CreateDirectory(a2PeopleSingletonDirectory); @@ -311,7 +311,7 @@ internal abstract class PersonContainer } string[] groupDirectories = Directory.GetDirectories(a2PeopleSingletonDirectory, "*", SearchOption.TopDirectoryOnly); if (!groupDirectories.Any()) - results = Array.Empty(); + results = new(); else results = GetPersonContainersGroups(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, groupDirectories); return results; @@ -335,4 +335,48 @@ internal abstract class PersonContainer return results; } + internal static List GetPersonKeys(IEnumerable personContainers) + { + List results = new(); + long personKey; + foreach (Models.PersonContainer personContainer in personContainers) + { + if (personContainer.Person is null || personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) + continue; + foreach (Models.PersonBirthday personBirthday in personContainer.Birthdays) + { + personKey = personBirthday.Value.Ticks; + results.Add(personKey); + } + } + return results; + } + + internal static List GetNonSpecificPeopleCollection(string mappingDefaultName, int personBirthdayFirstYear, char[] personCharacters, List personContainers, long ticks) + { + List results = new(); + long personKey; + Models.Person person; + int? approximateYears = null; + Models.PersonBirthday personBirthday; + Models.PersonContainer personContainer; + List personKeys = GetPersonKeys(personContainers); + string[] personDisplayDirectoryAllFiles = Array.Empty(); + DateTime incrementDate = new(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(mappingDefaultName, personCharacters, mappingDefaultName, personKey, personBirthday); + personContainer = new(approximateYears, new Models.PersonBirthday[] { personBirthday }, personDisplayDirectoryAllFiles, mappingDefaultName, personKey, person); + results.Add(personContainer); + } + return results; + } + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/Property.cs b/Shared/Models/Stateless/Methods/Property.cs index 0390e37..ae71b25 100644 --- a/Shared/Models/Stateless/Methods/Property.cs +++ b/Shared/Models/Stateless/Methods/Property.cs @@ -331,15 +331,15 @@ internal abstract class Property return result; } - internal static bool NameWithoutExtensionIsIdFormat(Models.FileHolder fileHolder) + internal static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) { bool result; - if (fileHolder.NameWithoutExtension.Length < 5) + if (fileNameWithoutExtension.Length < 5) result = false; else { - bool skipOneAllAreNumbers = fileHolder.NameWithoutExtension[1..].All(l => char.IsNumber(l)); - result = (skipOneAllAreNumbers && fileHolder.NameWithoutExtension[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileHolder.NameWithoutExtension[0])); + bool skipOneAllAreNumbers = fileNameWithoutExtension[1..].All(l => char.IsNumber(l)); + result = (skipOneAllAreNumbers && fileNameWithoutExtension[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileNameWithoutExtension[0])); } return result; } diff --git a/Shared/Models/Stateless/Methods/XDirectory.cs b/Shared/Models/Stateless/Methods/XDirectory.cs index 7ae900f..7f4e8ec 100644 --- a/Shared/Models/Stateless/Methods/XDirectory.cs +++ b/Shared/Models/Stateless/Methods/XDirectory.cs @@ -73,7 +73,7 @@ internal abstract partial class XDirectory List? collection; string fileNameUpperExtension; int length = extension.Length; - List<(string, string)> rename = new(); + List renameCollection = new(); foreach (string[] files in jsonFilesCollection) { foreach (string file in files) @@ -86,17 +86,13 @@ internal abstract partial class XDirectory { fileNameUpperExtension = string.Concat(Path.GetFileNameWithoutExtension(fileName), Path.GetExtension(fileName).ToUpper()); if (fileName == fileNameUpperExtension || !fileNamesToFiles.TryGetValue(fileNameUpperExtension, out collection)) - rename.Add(new(file, string.Concat(file, ".del"))); + renameCollection.Add(file); } } } - foreach ((string from, string to) in rename) - { - if (File.Exists(to)) - continue; - File.Move(from, to); - } - return rename.Count; + if (renameCollection.Any()) + IDirectory.MoveFiles(renameCollection, "{}", "{abd}"); + return renameCollection.Count; } private static void IsNotUniqueLoop(string file, List collection) @@ -248,4 +244,33 @@ internal abstract partial class XDirectory return rename.Count; } + internal static void MoveFiles(List files, string find, string replace) + { + string checkFile; + string? checkDirectory; + List directories = new(); + foreach (string file in files) + { + checkDirectory = Path.GetDirectoryName(file.Replace(find, replace)); + if (string.IsNullOrEmpty(checkDirectory) || directories.Contains(checkDirectory)) + continue; + directories.Add(checkDirectory); + } + foreach (string directory in directories) + { + if (Directory.Exists(directory)) + continue; + _ = Directory.CreateDirectory(directory); + } + foreach (string file in files) + { + if (!File.Exists(file)) + continue; + checkFile = file.Replace(find, replace); + if (File.Exists(checkFile)) + continue; + File.Move(file, checkFile); + } + } + } \ No newline at end of file diff --git a/Tests/UnitTestHardCoded.cs b/Tests/UnitTestHardCoded.cs index 0e3c395..d764010 100644 --- a/Tests/UnitTestHardCoded.cs +++ b/Tests/UnitTestHardCoded.cs @@ -244,6 +244,40 @@ public partial class UnitTestHardCoded NonThrowTryCatch(); } + [TestMethod] + public void TestMethodRenameDelete() + { + string checkFile; + string source = @"D:\1) Images A\Images-9b89679-Results\A) Property\9b89679\{}"; + string[] files = Directory.GetFiles(source, "*.del", SearchOption.AllDirectories); + foreach (string file in files) + { + checkFile = file[..^4]; + if (File.Exists(checkFile)) + continue; + File.Move(file, checkFile); + } + Assert.IsTrue(true); + NonThrowTryCatch(); + } + + [TestMethod] + public void TestMethodRenameOld() + { + string checkFile; + string source = @"D:\2) Images B\Not-Copy-Copy-9b89679-Results\E) Distance\9b89679\()"; + string[] files = Directory.GetFiles(source, "*.old", SearchOption.AllDirectories); + foreach (string file in files) + { + checkFile = file[..^4]; + if (File.Exists(checkFile)) + continue; + File.Move(file, checkFile); + } + Assert.IsTrue(true); + NonThrowTryCatch(); + } + [TestMethod] public void TestMethodAncestryGenealogicalDataCommunication() {