diff --git a/Distance/Models/MapLogicSupport.cs b/Distance/Models/MapLogicSupport.cs index 6e1086f..86f0319 100644 --- a/Distance/Models/MapLogicSupport.cs +++ b/Distance/Models/MapLogicSupport.cs @@ -278,21 +278,20 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport }); } - void Shared.Models.Methods.IMapLogicSupport.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string? a2PeopleSingletonDirectory, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) + void Shared.Models.Methods.IMapLogicSupport.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, string? a2PeopleSingletonDirectory, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) { - char @char; string json; string[] files; string checkFile; string[] segments; const int zero = 0; + char personCharacter; string personKeyFormatted; string personDisplayDirectory; PersonBirthday personBirthday; string personDisplayDirectoryName; string checkPersonDisplayDirectory; string checkPersonKeyFormattedDirectory; - char[] chars = Shared.Models.Stateless.Methods.IAge.GetChars(); JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true }; foreach ((string[] personDisplayDirectoryNames, PersonContainer personContainer) in possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) { @@ -302,12 +301,12 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport personDisplayDirectoryName = personDisplayDirectoryNames[^1]; personDisplayDirectory = Path.Combine(personDisplayDirectoryNames); personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday); - segments = personDisplayDirectoryName.Split(chars); + segments = personDisplayDirectoryName.Split(personCharacters); if (segments.Length != 2) - @char = '_'; + personCharacter = '_'; else - @char = personDisplayDirectoryName[segments[zero].Length]; - checkPersonDisplayDirectory = Path.Combine(a2PeopleSingletonDirectory, @char.ToString(), personDisplayDirectoryName); + personCharacter = personDisplayDirectoryName[segments[zero].Length]; + checkPersonDisplayDirectory = Path.Combine(a2PeopleSingletonDirectory, personCharacter.ToString(), personDisplayDirectoryName); checkPersonKeyFormattedDirectory = Path.Combine(checkPersonDisplayDirectory, personKeyFormatted); if (Directory.Exists(checkPersonKeyFormattedDirectory)) continue; diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index d04691b..2d7acc2 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -122,7 +122,7 @@ public partial class DlibDotNet if (rootResultsDirectory is null) throw new Exception(); Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory); - _PersonContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.PersonBirthdayFormat, _Faces.FileNameExtension); + _PersonContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension); } if (!isSilent && configuration.TestDistanceResults) { @@ -272,6 +272,7 @@ public partial class DlibDotNet configuration.MappingDefaultName, configuration.PersonBirthdayFirstYear, configuration.PersonBirthdayFormat, + configuration.PersonCharacters, configuration.RangeDaysDeltaTolerance, configuration.RangeDistanceTolerance, configuration.SortingMaximumPerKey, @@ -873,6 +874,8 @@ public partial class DlibDotNet List filteredItems = GetItems(argZero, containers); mapLogic.SaveShortcutsForOutputResolutions(filteredItems, mappingCollection, personKeyToCount); } + if (_Configuration.PersonCharactersToCopyTo.Length == 1) + mapLogic.CopyAtLeastOneMappedFiles(_Configuration.PersonCharactersToCopyTo[0], dFacesContentDirectory, a2PeopleSingletonDirectory, mappingCollection); Dictionary> idToNormalizedRectangleToMapping = MapLogicSupport.GetIdToNormalizedRectangleToFace(mappingCollection); mapLogic.CopyManualFiles(dFacesContentDirectory, idToNormalizedRectangleToMapping); if (_Configuration.SaveNotMappedForOutputResolutions.Contains(outputResolution)) diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index 8aaddd1..529efdb 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -49,6 +49,8 @@ public class Configuration [Display(Name = "Override For Resize Images"), Required] public bool? OverrideForResizeImages { get; set; } [Display(Name = "Person Birthday First Year"), Required] public int? PersonBirthdayFirstYear { get; set; } [Display(Name = "Person Birthday Format"), Required] public string PersonBirthdayFormat { get; set; } + [Display(Name = "Person Characters"), Required] public string PersonCharacters { get; set; } + [Display(Name = "Person Characters To Copy To"), Required] public string PersonCharactersToCopyTo { get; set; } [Display(Name = "PersonKey Format"), Required] public string PersonKeyFormat { get; set; } [Display(Name = "Predictor Model Name"), Required] public string PredictorModelName { get; set; } [Display(Name = "Properties Changed For Distance"), Required] public bool? PropertiesChangedForDistance { get; set; } @@ -156,6 +158,10 @@ public class Configuration throw new NullReferenceException(nameof(configuration.PersonBirthdayFirstYear)); if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat)); + if (configuration.PersonCharacters is null) + throw new NullReferenceException(nameof(configuration.PersonCharacters)); + if (configuration.PersonCharactersToCopyTo is null) + throw new NullReferenceException(nameof(configuration.PersonCharactersToCopyTo)); if (configuration.PersonKeyFormat is null) throw new NullReferenceException(nameof(configuration.PersonKeyFormat)); if (configuration.PropertiesChangedForDistance is null) @@ -240,6 +246,8 @@ public class Configuration configuration.OverrideForResizeImages.Value, configuration.PersonBirthdayFirstYear.Value, configuration.PersonBirthdayFormat, + configuration.PersonCharacters, + configuration.PersonCharactersToCopyTo, configuration.PersonKeyFormat, configuration.PredictorModelName, configuration.PropertiesChangedForDistance.Value, diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index 5c39c6e..754ff19 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -46,6 +46,8 @@ public class Configuration public bool OverrideForResizeImages { init; get; } public int PersonBirthdayFirstYear { init; get; } public string PersonBirthdayFormat { init; get; } + public string PersonCharacters { init; get; } + public string PersonCharactersToCopyTo { init; get; } public string PersonKeyFormat { init; get; } public string PredictorModelName { init; get; } public bool PropertiesChangedForDistance { init; get; } @@ -112,6 +114,8 @@ public class Configuration bool overrideForResizeImages, int personBirthdayFirstYear, string personBirthdayFormat, + string personCharacters, + string personCharactersToCopyTo, string personKeyFormat, string predictorModelName, bool propertiesChangedForDistance, @@ -177,6 +181,8 @@ public class Configuration OverrideForResizeImages = overrideForResizeImages; PersonBirthdayFirstYear = personBirthdayFirstYear; PersonBirthdayFormat = personBirthdayFormat; + PersonCharacters = personCharacters; + PersonCharactersToCopyTo = personCharactersToCopyTo; PersonKeyFormat = personKeyFormat; PredictorModelName = predictorModelName; PropertiesChangedForDistance = propertiesChangedForDistance; diff --git a/Instance/Models/_G2_Identify.cs b/Instance/Models/_G2_Identify.cs index e1413ae..f7a71c5 100644 --- a/Instance/Models/_G2_Identify.cs +++ b/Instance/Models/_G2_Identify.cs @@ -94,7 +94,7 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify if (rootResultsDirectory is null) throw new Exception(); Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory); - PersonContainer[] personContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, _Configuration.PersonBirthdayFormat, facesFileNameExtension); + PersonContainer[] personContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, _Configuration.PersonBirthdayFormat, _Configuration.PersonCharacters.ToArray(), facesFileNameExtension); string[] peopleBirthDates = (from l in personContainers select Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, l.Person.Birthday)).ToArray(); Dictionary sourceKeyValuePairs = JsonSerializer.Deserialize>(json); foreach (KeyValuePair keyValuePair in sourceKeyValuePairs) diff --git a/Instance/appsettings.Development.json b/Instance/appsettings.Development.json index c83ebeb..a942641 100644 --- a/Instance/appsettings.Development.json +++ b/Instance/appsettings.Development.json @@ -10,8 +10,17 @@ }, "Windows": { "Configuration": { - "DistanceRenameToMatch": false, - "DistanceMoveUnableToMatch": false, + "DistanceRenameToMatch": true, + "DistanceMoveUnableToMatch": true, + "PersonCharacters": "!#]^_`~+", + "xPersonCharactersToCopyTo": "!", + "xxPersonCharactersToCopyTo": "#", + "xxxPersonCharactersToCopyTo": "]", + "xxxxPersonCharactersToCopyTo": "^", + "xxxxxPersonCharactersToCopyTo": "_", + "xxxxxxPersonCharactersToCopyTo": "`", + "xxxxxxxPersonCharactersToCopyTo": "~", + "xxxxxxxxPersonCharactersToCopyTo": "+", "xRootDirectory": "D:/Tmp/phares/Pictures", "xxRootDirectory": "D:/Tmp/Phares/Compare/Not-Copy-Copy-37c7b67", "xxxRootDirectory": "D:/Tmp/Phares/Compare/Corrupt", diff --git a/Instance/appsettings.json b/Instance/appsettings.json index 0246cfe..26c4bf6 100644 --- a/Instance/appsettings.json +++ b/Instance/appsettings.json @@ -87,6 +87,8 @@ "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", "PersonBirthdayFirstYear": 1500, "PersonBirthdayFormat": "yyyy-MM-dd_HH", + "PersonCharacters": "!#]^_`~+", + "PersonCharactersToCopyTo": "~", "PersonKeyFormat": "yyyy-MM-dd_HH", "PopulatePropertyId": true, "PredictorModelName": "Large", diff --git a/Map/Models/Configuration.cs b/Map/Models/Configuration.cs index fdf9c71..8077150 100644 --- a/Map/Models/Configuration.cs +++ b/Map/Models/Configuration.cs @@ -12,6 +12,7 @@ public class Configuration public string FacesFileNameExtension { init; get; } public string FacesHiddenFileNameExtension { init; get; } public string MappingDefaultName { init; get; } + public string PersonCharacters { init; get; } public int PersonBirthdayFirstYear { init; get; } public string PersonBirthdayFormat { init; get; } public int RangeDaysDeltaTolerance { init; get; } @@ -25,6 +26,7 @@ public class Configuration string mappingDefaultName, int personBirthdayFirstYear, string personBirthdayFormat, + string personCharacters, int[] rangeDaysDeltaTolerance, double[] rangeDistanceTolerance, int sortingMaximumPerKey, @@ -33,6 +35,7 @@ public class Configuration string facesHiddenFileNameExtension, string facePartsFileNameExtension) { + PersonCharacters = personCharacters; MappingDefaultName = mappingDefaultName; PersonBirthdayFormat = personBirthdayFormat; SortingMaximumPerKey = sortingMaximumPerKey; diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index 5591a4e..25d1fcc 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -687,11 +687,11 @@ public class MapLogic : Shared.Models.Methods.IMapLogic string mappingSegmentB; string personDirectory; string? facesDirectory; + int? normalizedRectangle; string personKeyFormatted; string personDisplayFileName; PersonBirthday personBirthday; string? personDisplayDirectory; - int? normalizedRectangle; WindowsShortcut windowsShortcut; Dictionary? normalizedRectangleToMapping; string by = nameof(Shared.Models.Stateless.IMapLogic.ManualCopy); @@ -731,7 +731,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic if (string.IsNullOrEmpty(directoryName)) throw new NotSupportedException(); shortcutFile = Path.Combine(personDisplayDirectory, $"{personDisplayFileName}.lnk"); - facesDirectory = GetFacesDirectory(dFacesContentDirectory, mapping.MappingFromItem); // Path.Combine($"{dFacesContentDirectory}{directoryName}", mapping.MappingFromItem.ImageFileHolder.NameWithoutExtension); + facesDirectory = GetFacesDirectory(dFacesContentDirectory, mapping.MappingFromItem); if (facesDirectory is null) continue; faceFileName = $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}"; @@ -768,6 +768,61 @@ public class MapLogic : Shared.Models.Methods.IMapLogic } } + public void CopyAtLeastOneMappedFiles(char personCharactersToCopyTo, string dFacesContentDirectory, string a2PeopleSingletonDirectory, Mapping[] mappingCollection) + { + if (_Configuration is null) + throw new NullReferenceException(nameof(_Configuration)); + long personKey; + string fileName; + string faceFile; + string directory; + string faceFileName; + string? directoryName; + string? facesDirectory; + PersonContainer? personContainer; + Dictionary personKeyToCount = new(); + foreach (Mapping mapping in mappingCollection) + { + directoryName = Path.GetDirectoryName(mapping.MappingFromItem.RelativePath); + if (directoryName is null) + throw new NotSupportedException(); + if (mapping.MappingFromItem.ResizedFileHolder.DirectoryName is null || !mapping.MappingFromItem.ResizedFileHolder.Exists) + continue; + if (mapping.By is null or Shared.Models.Stateless.IMapLogic.Sorting || mapping.MappingFromPerson?.ApproximateYears is null) + continue; + if (string.IsNullOrEmpty(mapping.MappingFromPerson.SegmentB)) + throw new NotSupportedException(); + if (string.IsNullOrEmpty(mapping.MappingFromPerson.DisplayDirectoryName)) + throw new NotSupportedException(); + facesDirectory = GetFacesDirectory(dFacesContentDirectory, mapping.MappingFromItem); + if (facesDirectory is null) + continue; + faceFileName = $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}"; + faceFile = Path.Combine(facesDirectory, faceFileName); + personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks; + if (!personKeyToCount.ContainsKey(personKey)) + personKeyToCount.Add(personKey, 0); + if (personKeyToCount[personKey] > 1) + continue; + if (!_PersonKeyToPersonContainer.TryGetValue(personKey, out personContainer)) + continue; + if (personContainer.Char is null || personContainer.Char != personCharactersToCopyTo) + continue; + if (personContainer.DisplayDirectoryAllFiles.Any(l => l.EndsWith(faceFileName))) + continue; + if (!File.Exists(faceFile)) + continue; + directory = Path.Combine(a2PeopleSingletonDirectory, personCharactersToCopyTo.ToString(), personContainer.DisplayDirectoryName); + if (!Directory.Exists(directory)) + continue; + fileName = Path.Combine(directory, faceFileName); + if (File.Exists(fileName)) + continue; + personKeyToCount[personKey] += 1; + File.Copy(faceFile, fileName); + } + } + public void SaveNotMappedTicks() { if (_Configuration is null) @@ -1000,18 +1055,6 @@ public class MapLogic : Shared.Models.Methods.IMapLogic } } foreach (Mapping mapping in mappingCollection) - { - if (mapping.MappingFromItem.ResizedFileHolder.DirectoryName is null || !mapping.MappingFromItem.ResizedFileHolder.Exists) - continue; - if (mapping.By is null or Shared.Models.Stateless.IMapLogic.Sorting || mapping.MappingFromPerson?.ApproximateYears is null) - continue; - if (string.IsNullOrEmpty(mapping.MappingFromPerson.SegmentB)) - throw new NotSupportedException(); - if (string.IsNullOrEmpty(mapping.MappingFromPerson.DisplayDirectoryName)) - throw new NotSupportedException(); - personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday); - } - foreach (Mapping mapping in mappingCollection) { directoryName = Path.GetDirectoryName(mapping.MappingFromItem.RelativePath); if (directoryName is null) @@ -1119,7 +1162,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic if (normalizedRectangles is not null && normalizedRectangles.Contains(mapping.MappingFromLocation.NormalizedRectangle)) continue; directoryName = Path.GetDirectoryName(mapping.MappingFromItem.RelativePath); - facesDirectory = GetFacesDirectory(dFacesContentDirectory, mapping.MappingFromItem); // Path.Combine($"{dFacesContentDirectory}{directoryName}", mapping.MappingFromItem.ImageFileHolder.NameWithoutExtension); + facesDirectory = GetFacesDirectory(dFacesContentDirectory, mapping.MappingFromItem); if (facesDirectory is null) continue; faceFileHolder = new(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}")); diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index ed13481..d336562 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -28,7 +28,7 @@ internal abstract class MapLogic if (personKeys.Contains(personKey)) continue; personBirthday = IPersonBirthday.GetPersonBirthday(personKey); - person = IPerson.GetPerson(configuration.MappingDefaultName, personKey, personBirthday); + person = IPerson.GetPerson(configuration.PersonCharacters.ToArray(), configuration.MappingDefaultName, personKey, personBirthday); personContainer = new(approximateYears, person, new PersonBirthday[] { personBirthday }, personDisplayDirectoryAllFiles, configuration.MappingDefaultName, personKey); results.Add(personContainer); } @@ -211,7 +211,7 @@ internal abstract class MapLogic { List results = new(); List<(long? PersonKey, string Line)> lines = new(); - _ = GetDistinctCollection(configuration, personContainers, new()); + _ = GetDistinctCollection(configuration, personContainers, new(), new()); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string[] ticksDirectories; if (string.IsNullOrEmpty(eDistanceContentDirectory)) @@ -251,16 +251,15 @@ internal abstract class MapLogic 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) + private static void SetKeyValuePairs(Configuration configuration, List personContainers, Dictionary> personKeyToPersonContainerCollection, Dictionary personKeyFormattedToPersonContainer, 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); + List<(long, PersonContainer)> collection = GetDistinctCollection(configuration, personContainers, personKeyToPersonContainerCollection, personKeyFormattedToPersonContainer); foreach ((long personKey, PersonContainer personContainer) in collection) personKeyToPersonContainer.Add(personKey, personContainer); + Dictionary>> idThenNormalizedRectangleToPersonContainerCollection = new(); + Dictionary>> incorrectIdThenNormalizedRectangleToPersonContainerCollection = new(); if (personKeyFormattedIdThenNormalizedRectangleCollection.Any()) { string personDisplayDirectory; @@ -276,7 +275,7 @@ internal abstract class MapLogic personDisplayDirectory = Path.Combine(personDisplayDirectoryNames); if (!personKeyFormattedToPersonContainer.ContainsKey(personKeyFormatted)) { - personContainer = new(personBirthday, personDisplayDirectoryName); + personContainer = new(configuration.PersonCharacters.ToArray(), personBirthday, personDisplayDirectoryName); personKeyFormattedToPersonContainer.Add(personKeyFormatted, personContainer); } if (personDisplayDirectoryName.Length != 1 && personDisplayDirectoryName != configuration.MappingDefaultName && !personDisplayDirectoryTo.ContainsKey(personDisplayDirectory)) @@ -311,7 +310,7 @@ internal abstract class MapLogic incorrectIdThenNormalizedRectangleToPersonContainerCollection.Add(id, new()); if (!personKeyFormattedToPersonContainer.ContainsKey(personKeyFormatted)) { - personContainer = new(personBirthday, configuration.MappingDefaultName); + personContainer = new(configuration.PersonCharacters.ToArray(), personBirthday, configuration.MappingDefaultName); personKeyFormattedToPersonContainer.Add(personKeyFormatted, personContainer); } if (!incorrectIdThenNormalizedRectangleToPersonContainerCollection[id].ContainsKey(normalizedRectangle)) @@ -330,12 +329,11 @@ internal abstract class MapLogic } } - private static List<(long, PersonContainer)> GetDistinctCollection(Configuration configuration, IEnumerable personContainers, Dictionary personKeyFormattedToPersonContainer) + private static List<(long, PersonContainer)> GetDistinctCollection(Configuration configuration, IEnumerable personContainers, Dictionary> personKeyToPersonContainerCollection, 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) @@ -547,7 +545,7 @@ internal abstract class MapLogic return result; } - private static void SetPersonKeyToPersonContainer(Configuration configuration, List personContainers, long[] personKeyCollection, Dictionary personKeyToPersonContainer) + private static void SetPersonKeyToPersonContainer(Configuration configuration, List personContainers, long[] personKeyCollection, Dictionary personKeyToPersonContainer, Dictionary> personKeyToPersonContainerCollection) { string? displayDirectoryName; foreach (PersonContainer personContainer in personContainers) @@ -561,16 +559,20 @@ internal abstract class MapLogic } if (personKeyCollection.Any()) { + const int zero = 0; int? approximateYears = null; PersonBirthday? personBirthday; - PersonContainer? personContainer; + 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); + if (!personKeyToPersonContainerCollection.ContainsKey(personKey)) + personContainer = new(approximateYears, personBirthday, displayDirectoryName, personKey); + else + personContainer = new(approximateYears, personBirthday, personKeyToPersonContainerCollection[personKey][zero].Char, displayDirectoryName, personKey); personKeyToPersonContainer.Add(personKey, personContainer); } } @@ -586,9 +588,11 @@ internal abstract class MapLogic List nullablePersonKeyCollection = new(); List personKeyFormattedCollection = new(); Dictionary personKeyFormattedToNewestPersonKeyFormatted = new(); - List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer = new(); - List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection = new(); + Dictionary personKeyFormattedToPersonContainer = new(); + Dictionary> personKeyToPersonContainerCollection = new(); List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection = new(); + List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection = new(); + List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer = new(); Dictionary> incorrectIdThenNormalizedRectangleToPersonContainers = new(); SetPersonCollections(configuration, personContainers, personKeys, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection, skipCollection); personContainers.AddRange(GetNonSpecificPeopleCollection(configuration, ticks, personKeys)); @@ -597,7 +601,7 @@ internal abstract class MapLogic 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); + SetKeyValuePairs(configuration, personContainers, personKeyToPersonContainerCollection, personKeyFormattedToPersonContainer, 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 }; @@ -611,11 +615,11 @@ 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); + SetPersonKeyToPersonContainer(configuration, personContainers, personKeyCollection, personKeyToPersonContainer, personKeyToPersonContainerCollection); notMappedPersonContainers.AddRange(GetNotMappedPersonContainers(configuration, personContainers, personKeys, personKeyCollection)); AppendToSkipCollection(skipCollection, idThenNormalizedRectangleToPersonContainers, incorrectIdThenNormalizedRectangleToPersonContainers); if (possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Any()) - mapLogicSupport.SavePossiblyNewPersonContainers(propertyConfiguration, configuration.PersonBirthdayFormat, configuration.FacesFileNameExtension, a2PeopleContentDirectory, personKeyToPersonContainer, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); + mapLogicSupport.SavePossiblyNewPersonContainers(propertyConfiguration, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), configuration.FacesFileNameExtension, a2PeopleContentDirectory, personKeyToPersonContainer, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); } private static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, long minimumDateTimeTicks, bool? isWrongYear) diff --git a/Shared/Models/Methods/IMapLogicSupport.cs b/Shared/Models/Methods/IMapLogicSupport.cs index d4b4519..d8e1b1d 100644 --- a/Shared/Models/Methods/IMapLogicSupport.cs +++ b/Shared/Models/Methods/IMapLogicSupport.cs @@ -4,6 +4,6 @@ public interface IMapLogicSupport { string GetCounts(); - void SavePossiblyNewPersonContainers(Properties.IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string? a2PeopleContentDirectory, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); + void SavePossiblyNewPersonContainers(Properties.IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, string? a2PeopleContentDirectory, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); } \ No newline at end of file diff --git a/Shared/Models/PersonContainer.cs b/Shared/Models/PersonContainer.cs index 5df83fb..92c0ed0 100644 --- a/Shared/Models/PersonContainer.cs +++ b/Shared/Models/PersonContainer.cs @@ -12,11 +12,13 @@ public class PersonContainer : Properties.IPersonContainer public string[] DisplayDirectoryAllFiles { init; get; } public string DisplayDirectoryName { init; get; } public long? Key { init; get; } + public char? Char { init; get; } [JsonConstructor] - public PersonContainer(int? approximateYears, Person? person, PersonBirthday[]? birthdays, string[] displayDirectoryAllFiles, string displayDirectoryName, long? key) + public PersonContainer(int? approximateYears, char? @char, Person? person, PersonBirthday[]? birthdays, string[] displayDirectoryAllFiles, string displayDirectoryName, long? key) { ApproximateYears = approximateYears; + Char = @char; Person = person; Birthdays = birthdays; DisplayDirectoryAllFiles = displayDirectoryAllFiles; @@ -24,16 +26,24 @@ public class PersonContainer : Properties.IPersonContainer Key = key; } - public PersonContainer(int? approximateYears, string[] displayDirectoryAllFiles, string displayDirectoryName) : - this(approximateYears, null, null, displayDirectoryAllFiles, displayDirectoryName, null) + public PersonContainer(char[] personCharacters, PersonBirthday birthday, string displayDirectoryName) : + this(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), null, Stateless.Methods.IPerson.GetPerson(personCharacters, displayDirectoryName, birthday.Value.Ticks, birthday), new PersonBirthday[] { birthday }, Array.Empty(), displayDirectoryName, birthday.Value.Ticks) { } public PersonContainer(int? approximateYears, PersonBirthday birthdays, string displayDirectoryName, long key) : - this(approximateYears, null, new PersonBirthday[] { birthdays }, Array.Empty(), displayDirectoryName, key) + this(approximateYears, null, null, new PersonBirthday[] { birthdays }, Array.Empty(), displayDirectoryName, key) { } - public PersonContainer(PersonBirthday birthday, string displayDirectoryName) : - this(Stateless.Methods.IAge.GetApproximateYears(displayDirectoryName), Stateless.Methods.IPerson.GetPerson(displayDirectoryName, birthday.Value.Ticks, birthday), new PersonBirthday[] { birthday }, Array.Empty(), displayDirectoryName, birthday.Value.Ticks) + public PersonContainer(int? approximateYears, PersonBirthday birthdays, char? @char, string displayDirectoryName, long key) : + this(approximateYears, @char, null, new PersonBirthday[] { birthdays }, Array.Empty(), displayDirectoryName, key) + { } + + public PersonContainer(int? approximateYears, char @char, string[] displayDirectoryAllFiles, string displayDirectoryName) : + this(approximateYears, @char, null, null, displayDirectoryAllFiles, displayDirectoryName, null) + { } + + public PersonContainer(int? approximateYears, Person? person, PersonBirthday[]? birthdays, string[] displayDirectoryAllFiles, string displayDirectoryName, long? key) : + this(approximateYears, null, person, birthdays, displayDirectoryAllFiles, displayDirectoryName, key) { } public override string ToString() diff --git a/Shared/Models/Stateless/Methods/Age.cs b/Shared/Models/Stateless/Methods/Age.cs index 671c0cf..869ab18 100644 --- a/Shared/Models/Stateless/Methods/Age.cs +++ b/Shared/Models/Stateless/Methods/Age.cs @@ -31,11 +31,11 @@ internal abstract class Age return (years, result); } - internal static int? GetApproximateYears(string personDisplayDirectoryName, char[] chars) + internal static int? GetApproximateYears(char[] personCharacters, string personDisplayDirectoryName) { int? result; const int zero = 0; - string[] segments = personDisplayDirectoryName.Split(chars); + string[] segments = personDisplayDirectoryName.Split(personCharacters); if (segments.Length == 1 || !int.TryParse(segments[1].Split('-')[zero], out int years)) result = null; else diff --git a/Shared/Models/Stateless/Methods/IAge.cs b/Shared/Models/Stateless/Methods/IAge.cs index 2e5f6be..c022bd9 100644 --- a/Shared/Models/Stateless/Methods/IAge.cs +++ b/Shared/Models/Stateless/Methods/IAge.cs @@ -18,19 +18,9 @@ public interface IAge static (int, TimeSpan) GetAge(DateTime minuend, DateTime subtrahend) => Age.GetAge(minuend, subtrahend); - char[] TestStatic_GetChars() => - GetChars(); - static char[] GetChars() => - new char[] { '!', '#', ']', '^', '_', '`', '~', '+' }; - - int? TestStatic_GetApproximateYears(string personDisplayDirectoryName, char[] chars) => - GetApproximateYears(personDisplayDirectoryName, chars); - static int? GetApproximateYears(string personDisplayDirectoryName, char[] chars) => - Age.GetApproximateYears(personDisplayDirectoryName, chars); - - int? TestStatic_GetApproximateYears(string personDisplayDirectoryName) => - GetApproximateYears(personDisplayDirectoryName); - static int? GetApproximateYears(string personDisplayDirectoryName) => - GetApproximateYears(personDisplayDirectoryName, GetChars()); + int? TestStatic_GetApproximateYears(char[] personCharacters, string personDisplayDirectoryName) => + GetApproximateYears(personCharacters, personDisplayDirectoryName); + static int? GetApproximateYears(char[] personCharacters, string personDisplayDirectoryName) => + Age.GetApproximateYears(personCharacters, personDisplayDirectoryName); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPerson.cs b/Shared/Models/Stateless/Methods/IPerson.cs index 089bf93..a6b01dd 100644 --- a/Shared/Models/Stateless/Methods/IPerson.cs +++ b/Shared/Models/Stateless/Methods/IPerson.cs @@ -10,10 +10,10 @@ public interface IPerson static string GetFileFullName(Properties.IStorage storage, string personBirthdayFormat, Models.Person person) => IPersonBirthday.GetFileFullName(storage, personBirthdayFormat, person.Birthday); - Models.Person TestStatic_GetPerson(string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => - GetPerson(personDisplayDirectoryName, personKey, personBirthday); - static Models.Person GetPerson(string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => - Person.GetPerson(personKey, personBirthday, personDisplayDirectoryName.Split(IAge.GetChars())); + Models.Person TestStatic_GetPerson(char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => + GetPerson(personCharacters, personDisplayDirectoryName, personKey, personBirthday); + static Models.Person GetPerson(char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => + Person.GetPerson(personKey, personBirthday, personDisplayDirectoryName.Split(personCharacters)); Models.Person TestStatic_GetPerson(long personKey, string[] segments) => GetPerson(personKey, segments); diff --git a/Shared/Models/Stateless/Methods/IPersonContainer.cs b/Shared/Models/Stateless/Methods/IPersonContainer.cs index 9c39bdd..0bfb8f8 100644 --- a/Shared/Models/Stateless/Methods/IPersonContainer.cs +++ b/Shared/Models/Stateless/Methods/IPersonContainer.cs @@ -5,10 +5,10 @@ public interface IPersonContainer // ... - Models.PersonContainer[] TestStatic_GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, string facesFileNameExtension) => - GetPersonContainers(storage, personBirthdayFormat, facesFileNameExtension); - static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, string facesFileNameExtension) => - PersonContainer.GetPersonContainers(storage, personBirthdayFormat, facesFileNameExtension); + Models.PersonContainer[] TestStatic_GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension) => + GetPersonContainers(storage, personBirthdayFormat, personCharacters, facesFileNameExtension); + static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension) => + PersonContainer.GetPersonContainers(storage, personBirthdayFormat, personCharacters, facesFileNameExtension); List<(long?, string)> TestStatic_GetDisplay(string personBirthdayFormat, Models.PersonContainer personContainer) => GetDisplay(personBirthdayFormat, personContainer); diff --git a/Shared/Models/Stateless/Methods/PersonContainer.cs b/Shared/Models/Stateless/Methods/PersonContainer.cs index b705e71..e54b23f 100644 --- a/Shared/Models/Stateless/Methods/PersonContainer.cs +++ b/Shared/Models/Stateless/Methods/PersonContainer.cs @@ -33,7 +33,7 @@ internal abstract class PersonContainer return results; } - private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(string facesFileNameExtension, char[] chars, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) + private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(string facesFileNameExtension, char[] personCharacters, char @char, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) { List<(long?, Models.PersonContainer)> results = new(); long personKey; @@ -45,7 +45,7 @@ internal abstract class PersonContainer string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory); foreach ((string personKeyFormatted, Models.PersonBirthday personBirthday) in collection) { - segments = personDisplayDirectoryName.Split(chars); + segments = personDisplayDirectoryName.Split(personCharacters); orderedPersonBirthdays = (from l in collection where !l.PersonKeyFormatted.Contains(numberSign) orderby l.PersonBirthday.Value.Ticks descending select l.PersonBirthday).ToArray(); if (!orderedPersonBirthdays.Any()) personKey = collection[zero].PersonBirthday.Value.Ticks; @@ -56,17 +56,17 @@ internal abstract class PersonContainer personKey = orderedPersonBirthdays[zero].Value.Ticks; } person = IPerson.GetPerson(personKey, segments); - personContainer = new(approximateYears, person, orderedPersonBirthdays, personDisplayDirectoryAllFiles, personDisplayDirectoryName, personKey); + personContainer = new(approximateYears, @char, person, orderedPersonBirthdays, personDisplayDirectoryAllFiles, personDisplayDirectoryName, personKey); results.Add(new(personKey, personContainer)); } return results; } - private static Models.PersonContainer GetPersonContainer(string facesFileNameExtension, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears) + private static Models.PersonContainer GetPersonContainer(string facesFileNameExtension, char @char, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears) { Models.PersonContainer result; string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory); - result = new(approximateYears, personDisplayDirectoryAllFiles, personDisplayDirectoryName); + result = new(approximateYears, @char, personDisplayDirectoryAllFiles, personDisplayDirectoryName); return result; } @@ -101,7 +101,7 @@ internal abstract class PersonContainer return result; } - private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(string personBirthdayFormat, string facesFileNameExtension, char[] chars, string[] personDisplayDirectories) + private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, char @char, string[] personDisplayDirectories) { List<(long?, Models.PersonContainer)> results = new(); string? minusOne; @@ -117,7 +117,7 @@ internal abstract class PersonContainer personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); if (string.IsNullOrEmpty(personDisplayDirectoryName)) continue; - approximateYears = Age.GetApproximateYears(personDisplayDirectoryName, chars); + approximateYears = Age.GetApproximateYears(personCharacters, personDisplayDirectoryName); personKeyDirectories = Directory.GetDirectories(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); collection = PersonBirthday.GetPersonBirthdays(personBirthdayFormat, personKeyDirectories, personDisplayDirectory, personDisplayDirectoryName); if (personDisplayDirectoryName.Contains('^')) @@ -130,10 +130,10 @@ internal abstract class PersonContainer if (changes.Any(l => l is not null)) continue; if (collection.Any()) - results.AddRange(GetPersonContainersCollections(facesFileNameExtension, chars, numberSign, personDisplayDirectory, personDisplayDirectoryName, approximateYears, collection)); + results.AddRange(GetPersonContainersCollections(facesFileNameExtension, personCharacters, @char, numberSign, personDisplayDirectory, personDisplayDirectoryName, approximateYears, collection)); else { - personContainer = GetPersonContainer(facesFileNameExtension, personDisplayDirectory, personDisplayDirectoryName, approximateYears); + personContainer = GetPersonContainer(facesFileNameExtension, @char, personDisplayDirectory, personDisplayDirectoryName, approximateYears); results.Add(new(null, personContainer)); } } @@ -142,7 +142,7 @@ internal abstract class PersonContainer return results; } - private static Models.PersonContainer[] GetPersonContainersGroups(string personBirthdayFormat, string facesFileNameExtension, char[] chars, string[] groupDirectories) + private static Models.PersonContainer[] GetPersonContainersGroups(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, string[] groupDirectories) { Models.PersonContainer[] results; const int zero = 0; @@ -153,27 +153,26 @@ internal abstract class PersonContainer foreach (string groupDirectory in groupDirectories) { groupDirectoryName = Path.GetFileName(groupDirectory); - if (!chars.Contains(groupDirectoryName[zero])) + if (!personCharacters.Contains(groupDirectoryName[zero])) continue; personDisplayDirectories = Directory.GetDirectories(groupDirectory, "*", SearchOption.TopDirectoryOnly); - collection = GetPersonContainersGroup(personBirthdayFormat, facesFileNameExtension, chars, personDisplayDirectories); + collection = GetPersonContainersGroup(personBirthdayFormat, facesFileNameExtension, personCharacters, groupDirectoryName[zero], personDisplayDirectories); personContainers.AddRange(collection); } results = (from l in personContainers orderby l.PersonKey is not null, l.PersonKey select l.PersonContainer).ToArray(); return results; } - internal static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, string facesFileNameExtension) + internal static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension) { Models.PersonContainer[] results; - char[] chars = IAge.GetChars(); string a2PeopleSingletonDirectory = Path.Combine(storage.PeopleRootDirectory, "{}"); if (!Directory.Exists(a2PeopleSingletonDirectory)) _ = Directory.CreateDirectory(a2PeopleSingletonDirectory); string a2PeopleSingletonDirectoryChar; - foreach (char @char in chars) + foreach (char personCharacter in personCharacters) { - a2PeopleSingletonDirectoryChar = Path.Combine(a2PeopleSingletonDirectory, @char.ToString()); + a2PeopleSingletonDirectoryChar = Path.Combine(a2PeopleSingletonDirectory, personCharacter.ToString()); if (!Directory.Exists(a2PeopleSingletonDirectoryChar)) _ = Directory.CreateDirectory(a2PeopleSingletonDirectoryChar); } @@ -181,7 +180,7 @@ internal abstract class PersonContainer if (!groupDirectories.Any()) results = Array.Empty(); else - results = GetPersonContainersGroups(personBirthdayFormat, facesFileNameExtension, chars, groupDirectories); + results = GetPersonContainersGroups(personBirthdayFormat, facesFileNameExtension, personCharacters, groupDirectories); return results; }