diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index af53f24..417ad2d 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -72,8 +72,9 @@ public partial class DlibDotNet _Log.Information(configuration.ModelDirectory); (Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(configuration); { - (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(configuration.OutputExtension, configuration.OutputQuality); - _Resize = new C_Resize(configuration.ForceResizeLastWriteTimeToCreationTime, configuration.OverrideForResizeImages, configuration.PropertiesChangedForResize, configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension); + (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetPngLowQuality(); + (ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFileNameExtension) = C_Resize.GetGifLowQuality(); + _Faces = new D_Face(configuration, argZero, model, modelParameter, predictorModel, imageCodecInfo, encoderParameters, filenameExtension, hiddenImageCodecInfo, hiddenEncoderParameters, hiddenFileNameExtension); } if (_FirstRun || !_ArgZeroIsConfigurationRootDirectory) personContainers = Array.Empty(); @@ -84,7 +85,7 @@ public partial class DlibDotNet ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using ProgressBar progressBar = new(1, message, options); progressBar.Tick(); - personContainers = A2_People.GetPersonContainers(configuration, propertyConfiguration); + personContainers = A2_People.GetPersonContainers(configuration, propertyConfiguration, _Faces.FileNameExtension); } if (!isSilent && configuration.TestDistanceResults) { @@ -97,9 +98,8 @@ public partial class DlibDotNet _FaceParts = new D2_FaceParts(configuration, imageCodecInfo, encoderParameters, filenameExtension); } { - (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetPngLowQuality(); - (ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFilenameExtension) = C_Resize.GetGifLowQuality(); - _Faces = new D_Face(configuration, argZero, model, modelParameter, predictorModel, imageCodecInfo, encoderParameters, filenameExtension, hiddenImageCodecInfo, hiddenEncoderParameters, hiddenFilenameExtension); + (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(configuration.OutputExtension, configuration.OutputQuality); + _Resize = new C_Resize(configuration.ForceResizeLastWriteTimeToCreationTime, configuration.OverrideForResizeImages, configuration.PropertiesChangedForResize, configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension); } if (!configuration.SkipSearch) Search(ticks, model, predictorModel, argZero, propertyRoot, personContainers); @@ -264,29 +264,30 @@ public partial class DlibDotNet private static Map.Models.Configuration Get(Models.Configuration configuration) { - Map.Models.Configuration result = new(configuration.FaceDistanceHiddenImageFactor, - configuration.FaceDistancePermyriad, - configuration.FaceDistanceMinimumConfidence, - configuration.FaceDistanceTolerance, - configuration.LocationDigits, - configuration.LocationFactor, - configuration.MapLogicSigma, - configuration.MappingDefaultName, - configuration.MappingMoveUnableToMatch, - configuration.MappingSaveFaceEncoding, - configuration.MappingSaveNotMapped, - configuration.MappingSaveMapped, - configuration.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping, - configuration.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping, - configuration.PersonBirthdayFirstYear, - configuration.PersonBirthdayFormat, - configuration.PersonKeyFormat, - configuration.SortingDaysDeltaTolerance, - configuration.SortingFacesToSkipAfterSortBeforeLoad, - configuration.SortingFacesToTakeAfterSortBeforeLoad, - configuration.SortingMaximumPerFaceShouldBeHigh, - configuration.SortingMaximumPerKey, - configuration.SortingSigma); + Map.Models.Configuration result = new( + configuration.FaceDistanceHiddenImageFactor, + configuration.FaceDistancePermyriad, + configuration.FaceDistanceMinimumConfidence, + configuration.FaceDistanceTolerance, + configuration.LocationDigits, + configuration.LocationFactor, + configuration.MapLogicSigma, + configuration.MappingDefaultName, + configuration.MappingMoveUnableToMatch, + configuration.MappingSaveFaceEncoding, + configuration.MappingSaveNotMapped, + configuration.MappingSaveMapped, + configuration.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping, + configuration.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping, + configuration.PersonBirthdayFirstYear, + configuration.PersonBirthdayFormat, + configuration.PersonKeyFormat, + configuration.SortingDaysDeltaTolerance, + configuration.SortingFacesToSkipAfterSortBeforeLoad, + configuration.SortingFacesToTakeAfterSortBeforeLoad, + configuration.SortingMaximumPerFaceShouldBeHigh, + configuration.SortingMaximumPerKey, + configuration.SortingSigma); return result; } @@ -554,21 +555,24 @@ public partial class DlibDotNet _Resize.AngleBracketCollection.Clear(); _Metadata.AngleBracketCollection.Clear(); propertyLogic.AngleBracketCollection.Clear(); - propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, + propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection( + _Configuration.PropertyConfiguration, container.SourceDirectory, aResultsFullGroupDirectory, contentDescription: string.Empty, singletonDescription: "Properties for each image", collectionDescription: string.Empty, converted: false)); - _Metadata.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, + _Metadata.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection( + _Configuration.PropertyConfiguration, container.SourceDirectory, bResultsFullGroupDirectory, contentDescription: string.Empty, singletonDescription: "Metadata as key value pairs", collectionDescription: string.Empty, converted: true)); - _Resize.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, + _Resize.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection( + _Configuration.PropertyConfiguration, container.SourceDirectory, cResultsFullGroupDirectory, contentDescription: "Resized image", @@ -576,7 +580,8 @@ public partial class DlibDotNet collectionDescription: string.Empty, converted: true)); if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) - _Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, + _Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection( + _Configuration.PropertyConfiguration, container.SourceDirectory, dResultsFullGroupDirectory, contentDescription: "n png file(s) for each face found", @@ -738,13 +743,13 @@ public partial class DlibDotNet List distinctFilteredFaces = SetMappingThenGetDistinctFilteredFacesWithMapping(argZero, containers); List selectedFilteredFaces = E_Distance.GetSelectedFilteredFaces(_MapConfiguration, distinctFilteredFaces); E_Distance.SetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, selectedFilteredFaces); - MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Resize.FilenameExtension, _Faces.FilenameExtension, _Faces.HiddenFilenameExtension, _FaceParts.FilenameExtension, ticks, personContainers, eResultsFullGroupDirectory, distinctFilteredFaces, distance); + MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Faces.FileNameExtension, _Faces.HiddenFileNameExtension, _FaceParts.FileNameExtension, ticks, personContainers, eResultsFullGroupDirectory, distinctFilteredFaces, distance); SortingContainer[] sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, selectedFilteredFaces); E_Distance.SaveFaceDistances(_Configuration.PropertyConfiguration, eResultsFullGroupDirectory, sortingContainers); int totalNotMapped = mapLogic.AddToMapping(distinctFilteredFaces); if (totalNotMapped > 0) mapLogic.ForceSingleImageThenSaveMapping(dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, distinctFilteredFaces, sortingContainers, totalNotMapped); - mapLogic.CopyManualFiles(_Resize.FilenameExtension); + mapLogic.CopyManualFiles(dResultsFullGroupDirectory, distinctFilteredFaces); if (_MapConfiguration.MappingSaveNotMapped) mapLogic.SaveNotMappedTicks(); if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) @@ -763,7 +768,7 @@ public partial class DlibDotNet string dResultsFullGroupDirectory; string eResultsFullGroupDirectory; string d2ResultsFullGroupDirectory; - A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Configuration.Reverse, model, predictorModel); + A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, model, predictorModel); 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 }; @@ -791,7 +796,7 @@ public partial class DlibDotNet if (_FileKeyValuePairs.Any()) _Random.Random(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], _FileKeyValuePairs); G2_Identify identify = new(_Configuration); - List identifiedCollection = identify.GetIdentifiedCollection(_Configuration.PropertyConfiguration, _IsEnvironment); + List identifiedCollection = identify.GetIdentifiedCollection(_IsEnvironment, _Configuration.PropertyConfiguration, _Faces.FileNameExtension); A2_People.WriteAllText(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], identifiedCollection); identify.WriteAllText(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], identifiedCollection); if (_Configuration.LoadOrCreateThenSaveIndex && _FilePropertiesKeyValuePairs.Any()) diff --git a/Instance/Models/_A2_People.cs b/Instance/Models/_A2_People.cs index 570350e..7f74b66 100644 --- a/Instance/Models/_A2_People.cs +++ b/Instance/Models/_A2_People.cs @@ -44,16 +44,16 @@ internal class A2_People } } - internal static PersonContainer[] GetPersonContainers(Configuration configuration, Property.Models.Configuration propertyConfiguration) + internal static PersonContainer[] GetPersonContainers(Configuration configuration, Property.Models.Configuration propertyConfiguration, string facesFileNameExtension) { PersonContainer[] results; - string rootDirectory = configuration.PropertyConfiguration.RootDirectory; + string rootDirectory = propertyConfiguration.RootDirectory; string peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A2_People)); string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory)); if (rootResultsDirectory is null) throw new Exception(); Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory); - results = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.PersonBirthdayFormat); + results = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.LocationDigits, configuration.PersonBirthdayFormat, facesFileNameExtension); return results; } diff --git a/Instance/Models/_D2_FaceParts.cs b/Instance/Models/_D2_FaceParts.cs index efad7ba..1af87cb 100644 --- a/Instance/Models/_D2_FaceParts.cs +++ b/Instance/Models/_D2_FaceParts.cs @@ -15,8 +15,8 @@ namespace View_by_Distance.Instance.Models; internal class D2_FaceParts { - protected readonly string _FilenameExtension; - public string FilenameExtension => _FilenameExtension; + protected readonly string _FileNameExtension; + public string FileNameExtension => _FileNameExtension; private readonly Serilog.ILogger? _Log; private readonly Configuration _Configuration; @@ -28,7 +28,7 @@ internal class D2_FaceParts _Configuration = configuration; _ImageCodecInfo = imageCodecInfo; _EncoderParameters = encoderParameters; - _FilenameExtension = filenameExtension; + _FileNameExtension = filenameExtension; _Log = Serilog.Log.ForContext(); } @@ -146,7 +146,7 @@ internal class D2_FaceParts continue; } deterministicHashCodeKeyDisplay = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value); - fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); + fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_FileNameExtension}")); if (!fileInfo.Exists) { if (fileInfo.Directory?.Parent is null) @@ -157,7 +157,7 @@ internal class D2_FaceParts } if (string.IsNullOrEmpty(fileInfo.DirectoryName)) continue; - rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKeyDisplay} - R{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); + rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKeyDisplay} - R{item.ImageFileHolder.ExtensionLowered}{_FileNameExtension}")); collection.Add(new(face, fileInfo.FullName, rotatedFileInfo.FullName)); if (check) continue; diff --git a/Instance/Models/_D_Face.cs b/Instance/Models/_D_Face.cs index ed7b8e0..7a96202 100644 --- a/Instance/Models/_D_Face.cs +++ b/Instance/Models/_D_Face.cs @@ -20,11 +20,11 @@ public class D_Face internal List AngleBracketCollection { get; } - protected readonly string _FilenameExtension; - public string FilenameExtension => _FilenameExtension; + protected readonly string _FileNameExtension; + public string FileNameExtension => _FileNameExtension; - protected readonly string _HiddenFilenameExtension; - public string HiddenFilenameExtension => _HiddenFilenameExtension; + protected readonly string _HiddenFileNameExtension; + public string HiddenFileNameExtension => _HiddenFileNameExtension; private readonly Model _Model; private readonly string _ArgZero; @@ -38,7 +38,7 @@ public class D_Face private readonly EncoderParameters _HiddenEncoderParameters; private readonly JsonSerializerOptions _WriteIndentedAndWhenWritingNull; - internal D_Face(Configuration configuration, string argZero, Model model, ModelParameter modelParameter, PredictorModel predictorModel, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension, ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFilenameExtension) + internal D_Face(Configuration configuration, string argZero, Model model, ModelParameter modelParameter, PredictorModel predictorModel, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension, ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFileNameExtension) { _Model = model; _ArgZero = argZero; @@ -47,12 +47,12 @@ public class D_Face _ModelParameter = modelParameter; _PredictorModel = predictorModel; _EncoderParameters = encoderParameters; - _FilenameExtension = filenameExtension; + _FileNameExtension = filenameExtension; _Log = Serilog.Log.ForContext(); AngleBracketCollection = new List(); _HiddenImageCodecInfo = hiddenImageCodecInfo; _HiddenEncoderParameters = hiddenEncoderParameters; - _HiddenFilenameExtension = hiddenFilenameExtension; + _HiddenFileNameExtension = hiddenFileNameExtension; _WriteIndentedAndWhenWritingNull = new JsonSerializerOptions { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; } @@ -148,9 +148,9 @@ public class D_Face { int width; int height; + Bitmap bitmap; Graphics graphics; Location? location; - Bitmap preRotated; Rectangle rectangle; using Bitmap source = new(resizedFileHolder.FullName); foreach ((Face face, FileInfo? fileInfo, string fileName) in collection) @@ -165,11 +165,11 @@ public class D_Face width = location.Right - location.Left; height = location.Bottom - location.Top; rectangle = new Rectangle(location.Left, location.Top, width, height); - using (preRotated = new(width, height)) + using (bitmap = new(width, height)) { - using (graphics = Graphics.FromImage(preRotated)) + using (graphics = Graphics.FromImage(bitmap)) graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel); - preRotated.Save(fileInfo.FullName, _ImageCodecInfo, _EncoderParameters); + bitmap.Save(fileInfo.FullName, _ImageCodecInfo, _EncoderParameters); } if (File.Exists(fileName)) File.Delete(fileName); @@ -179,11 +179,11 @@ public class D_Face width = location.Right - location.Left; height = location.Bottom - location.Top; rectangle = new Rectangle(location.Left, location.Top, width, height); - using (preRotated = new(width, height)) + using (bitmap = new(width, height)) { - using (graphics = Graphics.FromImage(preRotated)) + using (graphics = Graphics.FromImage(bitmap)) graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel); - preRotated.Save(fileName, _HiddenImageCodecInfo, _HiddenEncoderParameters); + bitmap.Save(fileName, _HiddenImageCodecInfo, _HiddenEncoderParameters); } File.SetAttributes(fileName, FileAttributes.Hidden); } @@ -374,7 +374,7 @@ public class D_Face continue; } deterministicHashCodeKeyDisplay = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value); - fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); + fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_FileNameExtension}")); if (!fileInfo.Exists) { if (fileInfo.Directory?.Parent is null) @@ -383,7 +383,7 @@ public class D_Face if (File.Exists(parentCheck)) File.Delete(parentCheck); } - collection.Add(new(face, fileInfo, Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_HiddenFilenameExtension}"))); + collection.Add(new(face, fileInfo, Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_HiddenFileNameExtension}"))); if (_Configuration.OverrideForFaceImages) check = true; else if (!fileInfo.Exists) diff --git a/Instance/Models/_E_Distance.cs b/Instance/Models/_E_Distance.cs index bc8a6df..6521b29 100644 --- a/Instance/Models/_E_Distance.cs +++ b/Instance/Models/_E_Distance.cs @@ -186,7 +186,7 @@ internal class E_Distance : Shared.Models.Methods.IFaceDistance return results; } - void Shared.Models.Methods.IFaceDistance.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string resizeFilenameExtension, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) + void Shared.Models.Methods.IFaceDistance.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) { char @char; string json; @@ -194,12 +194,12 @@ internal class E_Distance : Shared.Models.Methods.IFaceDistance string checkFile; string[] segments; const int zero = 0; - string checkPersonKeyFormattedDirectory; 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 }; string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A2_People), "{}"); @@ -226,7 +226,7 @@ internal class E_Distance : Shared.Models.Methods.IFaceDistance _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true); if (!Directory.Exists(personDisplayDirectory)) continue; - files = Directory.GetFiles(personDisplayDirectory, $"*{resizeFilenameExtension}", SearchOption.TopDirectoryOnly); + files = Directory.GetFiles(personDisplayDirectory, $"*{facesFileNameExtension}", SearchOption.TopDirectoryOnly); foreach (string file in files) { checkFile = Path.Combine(checkPersonDisplayDirectory, Path.GetFileName(file)); diff --git a/Instance/Models/_G2_Identify.cs b/Instance/Models/_G2_Identify.cs index e44d74f..9366b98 100644 --- a/Instance/Models/_G2_Identify.cs +++ b/Instance/Models/_G2_Identify.cs @@ -67,7 +67,7 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify return result; } - private void CheckLastWriteTimes(Property.Models.Configuration configuration, IsEnvironment isEnvironment, FileInfo named, string g2IdentifySingletonDirectory) + private void CheckLastWriteTimes(IsEnvironment isEnvironment, Property.Models.Configuration configuration, string facesFileNameExtension, FileInfo named, string g2IdentifySingletonDirectory) { string json; FileInfo fileInfo; @@ -88,7 +88,7 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify } json = File.ReadAllText(named.FullName); Dictionary resultKeyValuePairs = new(); - PersonContainer[] personContainers = A2_People.GetPersonContainers(_Configuration, configuration); + PersonContainer[] personContainers = A2_People.GetPersonContainers(_Configuration, configuration, 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) @@ -106,7 +106,7 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify } } - internal List GetIdentifiedCollection(Property.Models.Configuration configuration, IsEnvironment isEnvironment) + internal List GetIdentifiedCollection(IsEnvironment isEnvironment, Property.Models.Configuration configuration, string facesFileNameExtension) { List results = new(); string json; @@ -125,7 +125,7 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify string g2IdentifySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(G2_Identify), "[]"); string jsonRootDirectory = Path.Combine(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, " - Copied"), string.Concat(directoryName, " - 4) Info"), _Configuration.PropertyConfiguration.DateGroup, "[]"); if (named is not null && named.Exists) - CheckLastWriteTimes(configuration, isEnvironment, named, g2IdentifySingletonDirectory); + CheckLastWriteTimes(isEnvironment, configuration, facesFileNameExtension, named, g2IdentifySingletonDirectory); if (Directory.Exists(jsonRootDirectory)) { jsonFiles = Directory.GetFiles(jsonRootDirectory, "*.json", SearchOption.AllDirectories); diff --git a/Map/Map.csproj b/Map/Map.csproj index 047d693..f419436 100644 --- a/Map/Map.csproj +++ b/Map/Map.csproj @@ -34,6 +34,7 @@ + diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index 11940cb..0f30412 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -1,3 +1,4 @@ +using Humanizer; using ShellProgressBar; using System.Text.Json; using View_by_Distance.Shared.Models; @@ -19,26 +20,23 @@ public class MapLogic public Dictionary IndicesFromNew => throw new NotImplementedException(); private readonly long _Ticks; - private const int _Mapping = 1; - private const int _Sorting = 2; private readonly Serilog.ILogger? _Log; - private const int _ForceSingleImage = 3; private readonly int _MaxDegreeOfParallelism; private readonly Configuration? _Configuration; - private readonly string _FacesFilenameExtension; - private readonly string _FacePartsFilenameExtension; - private readonly string _FacesHiddenFilenameExtension; + private readonly string _FacesFileNameExtension; + private readonly string _FacePartsFileNameExtension; + private readonly string _FacesHiddenFileNameExtension; private readonly string _EDistanceContentTicksDirectory; - public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string resizeFilenameExtension, string facesFilenameExtension, string facesHiddenFilenameExtension, string facePartsFilenameExtension, long ticks, PersonContainer[] personContainers, string eResultsFullGroupDirectory, List distinctFilteredFaces, Shared.Models.Methods.IFaceDistance? faceDistance) + public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string facesFileNameExtension, string facesHiddenFileNameExtension, string facePartsFileNameExtension, long ticks, PersonContainer[] personContainers, string eResultsFullGroupDirectory, List distinctFilteredFaces, Shared.Models.Methods.IFaceDistance? faceDistance) { _Ticks = ticks; _Configuration = configuration; _Log = Serilog.Log.ForContext(); - _FacesFilenameExtension = facesFilenameExtension; + _FacesFileNameExtension = facesFileNameExtension; _MaxDegreeOfParallelism = maxDegreeOfParallelism; - _FacePartsFilenameExtension = facePartsFilenameExtension; - _FacesHiddenFilenameExtension = facesHiddenFilenameExtension; + _FacePartsFileNameExtension = facePartsFileNameExtension; + _FacesHiddenFileNameExtension = facesHiddenFileNameExtension; if (_Log is null) { } if (propertyConfiguration.VerifyToSeason is null || !propertyConfiguration.VerifyToSeason.Any()) @@ -68,7 +66,19 @@ public class MapLogic if (configuration is not null && faceDistance is not null) { List personContainerCollection = new(personContainers); - Stateless.MapLogic.Set(propertyConfiguration, configuration, resizeFilenameExtension, ticks, personContainerCollection, eDistanceContentDirectory, distinctFilteredFaces, faceDistance, personKeyToPersonContainer, personKeyToRanges, notMappedPersonContainers, skipCollection, idThenNormalizedPixelPercentageToPersonContainers); + Stateless.MapLogic.Set(propertyConfiguration, + configuration, + facesFileNameExtension, + ticks, + personContainerCollection, + eDistanceContentDirectory, + distinctFilteredFaces, + faceDistance, + personKeyToPersonContainer, + personKeyToRanges, + notMappedPersonContainers, + skipCollection, + idThenNormalizedPixelPercentageToPersonContainers); if (personContainerCollection.Count == personContainers.Length) throw new NotSupportedException(); } @@ -93,7 +103,7 @@ public class MapLogic } public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string outputExtension, long ticks, PersonContainer[] personContainers, string eResultsFullGroupDirectory) : - this(maxDegreeOfParallelism, propertyConfiguration, configuration, outputExtension, outputExtension, outputExtension, outputExtension, ticks, personContainers, eResultsFullGroupDirectory, new(), null) + this(maxDegreeOfParallelism, propertyConfiguration, configuration, outputExtension, outputExtension, outputExtension, ticks, personContainers, eResultsFullGroupDirectory, new(), null) { } public override string ToString() @@ -257,10 +267,10 @@ public class MapLogic if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); int result = 0; - int by = _Mapping; const int zero = 0; string mappingSegmentB; PersonBirthday personBirthday; + int by = Stateless.IMapLogic.Mapping; List personContainers = new(); Dictionary keyValuePairs; foreach (Face face in distinctFilteredFaces) @@ -292,6 +302,8 @@ public class MapLogic private void SaveContainers(List saveContainers) { + string checkFile; + string sourceFile; WindowsShortcut windowsShortcut; string[] directories = (from l in saveContainers select l.Directory).Distinct().ToArray(); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - _Ticks).TotalSeconds); @@ -310,16 +322,34 @@ public class MapLogic progressBar.Tick(); if (string.IsNullOrEmpty(saveContainer.Directory) || string.IsNullOrEmpty(saveContainer.CheckFile) || saveContainer.ResizedFileHolder is null || saveContainer.FaceFileHolder is null || !string.IsNullOrEmpty(saveContainer.Json)) continue; - if (File.Exists(saveContainer.CheckFile)) - continue; - if (saveContainer.FaceFileHolder.Exists) - File.Copy(saveContainer.FaceFileHolder.FullName, saveContainer.CheckFile); + if (!saveContainer.FaceFileHolder.Exists && saveContainer.ResizedFileHolder.Exists) + { + checkFile = saveContainer.CheckFile; + sourceFile = saveContainer.ResizedFileHolder.FullName; + } + else if (saveContainer.FaceFileHolder.Exists) + { + sourceFile = saveContainer.FaceFileHolder.FullName; + checkFile = $"{saveContainer.CheckFile}{_FacesFileNameExtension}"; + } else - File.Copy(saveContainer.ResizedFileHolder.FullName, saveContainer.CheckFile); + continue; + if (File.Exists(checkFile)) + continue; + File.Copy(sourceFile, checkFile); if (saveContainer.HiddenFaceFileHolder is not null && saveContainer.HiddenFaceFileHolder.Exists) - File.Copy(saveContainer.HiddenFaceFileHolder.FullName, Path.ChangeExtension(saveContainer.CheckFile, _FacesHiddenFilenameExtension)); + { + sourceFile = saveContainer.HiddenFaceFileHolder.FullName; + checkFile = $"{saveContainer.CheckFile}{_FacesHiddenFileNameExtension}"; + } else if (saveContainer.FacePartsFileHolder is not null && saveContainer.FacePartsFileHolder.Exists) - File.Copy(saveContainer.FacePartsFileHolder.FullName, Path.ChangeExtension(saveContainer.CheckFile, _FacePartsFilenameExtension)); + { + sourceFile = saveContainer.FacePartsFileHolder.FullName; + checkFile = $"{saveContainer.CheckFile}{_FacePartsFileNameExtension}"; + } + if (File.Exists(checkFile)) + continue; + File.Copy(sourceFile, checkFile); } foreach (SaveContainer saveContainer in saveContainers) { @@ -356,7 +386,7 @@ public class MapLogic SaveContainer saveContainer; PersonBirthday personBirthday; List saveContainers = new(); - const string facePopulatedKey = nameof(_Sorting); + const string facePopulatedKey = nameof(Stateless.IMapLogic.Sorting); foreach (PersonContainer personContainer in _NotMappedPersonContainers) { if (personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) @@ -462,11 +492,11 @@ public class MapLogic const int zero = 0; HashSet hashSet; string mappingSegmentB; - const int by = _Sorting; string personKeyFormatted; List checkCollection; PersonBirthday personBirthday; PersonContainer[] personContainers; + const int by = Stateless.IMapLogic.Sorting; Dictionary keyValuePairs; Dictionary> checkKeyValuePairs = new(); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - _Ticks).TotalSeconds); @@ -522,9 +552,9 @@ public class MapLogic throw new NullReferenceException(nameof(_Configuration)); const int zero = 0; string mappingSegmentB; - int by = _ForceSingleImage; PersonBirthday personBirthday; List normalizedPixelPercentages; + int by = Stateless.IMapLogic.ForceSingleImage; string displayDirectoryName = _Configuration.MappingDefaultName; Face[] orderedDistinctFilteredFaces = (from l in distinctFilteredFaces orderby l.Mapping is not null, l.Mapping?.MappingFromLocation.Confidence descending select l).ToArray(); foreach (Face face in orderedDistinctFilteredFaces) @@ -574,6 +604,7 @@ public class MapLogic Dictionary keyValuePairs = new(); string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()"); string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, "()"); + string forceSingleImageHumanized = nameof(Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title); foreach (Face face in filteredFaces) { if (face.Mapping is null) @@ -587,20 +618,20 @@ public class MapLogic throw new NotSupportedException(); personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, face.Mapping.MappingFromPerson.PersonBirthday); if (face.Mapping.MappingFromPerson.By is null) - by = $"{nameof(_Mapping)}Null"; + by = $"{nameof(Stateless.IMapLogic.Mapping)}Null"; else { - if (face.Mapping.MappingFromPerson.By == _Mapping && !_Configuration.MappingSaveMapped) + if (face.Mapping.MappingFromPerson.By == Stateless.IMapLogic.Mapping && !_Configuration.MappingSaveMapped) continue; by = face.Mapping.MappingFromPerson.By.Value switch { - _Mapping => nameof(_Mapping), - _Sorting => nameof(_Sorting), - _ForceSingleImage => nameof(_ForceSingleImage), + Stateless.IMapLogic.Mapping => nameof(Stateless.IMapLogic.Mapping), + Stateless.IMapLogic.Sorting => nameof(Stateless.IMapLogic.Sorting), + Stateless.IMapLogic.ForceSingleImage => forceSingleImageHumanized, _ => throw new NotImplementedException() }; } - directory = Path.Combine(_EDistanceContentTicksDirectory, by[1..], personKeyFormatted, face.Mapping.MappingFromPerson.SegmentB); + directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, face.Mapping.MappingFromPerson.SegmentB); if (!keyValuePairs.ContainsKey(directory)) keyValuePairs.Add(directory, 0); keyValuePairs[directory]++; @@ -613,9 +644,9 @@ public class MapLogic facesDirectory = Path.Combine($"{dFacesContentDirectory}{directoryName}", face.Mapping.MappingFromItem.ImageFileHolder.NameWithoutExtension); facePartsDirectory = Path.Combine($"{d2FacePartsContentDirectory}{directoryName}", face.Mapping.MappingFromItem.ImageFileHolder.NameWithoutExtension); checkFile = Path.Combine(directory, $"{face.Mapping.MappingFromLocation.DeterministicHashCodeKey}{face.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}"); - faceFileHolder = new(Path.Combine(facesDirectory, $"{face.Mapping.MappingFromLocation.DeterministicHashCodeKey}{face.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_FacesFilenameExtension}")); - hiddenFaceFileHolder = new(Path.Combine(facesDirectory, $"{face.Mapping.MappingFromLocation.DeterministicHashCodeKey}{face.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_FacesHiddenFilenameExtension}")); - facePartsFileHolder = new(Path.Combine(facePartsDirectory, $"{face.Mapping.MappingFromLocation.DeterministicHashCodeKey}{face.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_FacePartsFilenameExtension}")); + faceFileHolder = new(Path.Combine(facesDirectory, $"{face.Mapping.MappingFromLocation.DeterministicHashCodeKey}{face.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_FacesFileNameExtension}")); + hiddenFaceFileHolder = new(Path.Combine(facesDirectory, $"{face.Mapping.MappingFromLocation.DeterministicHashCodeKey}{face.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_FacesHiddenFileNameExtension}")); + facePartsFileHolder = new(Path.Combine(facePartsDirectory, $"{face.Mapping.MappingFromLocation.DeterministicHashCodeKey}{face.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_FacePartsFileNameExtension}")); if (string.IsNullOrEmpty(personDirectory)) shortcutFile = string.Empty; else @@ -652,22 +683,52 @@ public class MapLogic SaveContainers(saveContainers); } - public void CopyManualFiles(string resizeFilenameExtension) + private static Dictionary> GetKeyValuePairs(List distinctFilteredFaces) + { + Dictionary> results = new(); + Dictionary keyValuePairs; + foreach (Face face in distinctFilteredFaces) + { + if (face.Mapping is null) + throw new NotSupportedException(); + if (!results.ContainsKey(face.Mapping.MappingFromItem.Id)) + results.Add(face.Mapping.MappingFromItem.Id, new()); + keyValuePairs = results[face.Mapping.MappingFromItem.Id]; + if (keyValuePairs.ContainsKey(face.Mapping.MappingFromLocation.NormalizedPixelPercentage)) + throw new NotSupportedException(); + keyValuePairs.Add(face.Mapping.MappingFromLocation.NormalizedPixelPercentage, face); + } + return results; + } + + public void CopyManualFiles(string dResultsFullGroupDirectory, List distinctFilteredFaces) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); int? id; + Face face; + string faceFile; string checkFile; string directory; FileInfo fileInfo; const int zero = 0; + string faceFileName; + string shortcutFile; + string? directoryName; + string facesDirectory; string mappingSegmentB; string personDirectory; string personKeyFormatted; - string by = nameof(_Sorting); + string personDisplayFileName; PersonBirthday personBirthday; + string? personDisplayDirectory; int? normalizedPixelPercentage; + WindowsShortcut windowsShortcut; Dictionary keyValuePairs; + string by = nameof(Stateless.IMapLogic.ManualCopy); + string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()"); + string successfull = $"_ {nameof(Stateless.IMapLogic.ManualCopy).Humanize(LetterCasing.Title)} Successfull"; + Dictionary> idToNormalizedPixelPercentageToFace = GetKeyValuePairs(distinctFilteredFaces); foreach (KeyValuePair keyValuePair in _PersonKeyToPersonContainer) { if (keyValuePair.Value.Key is null || keyValuePair.Value.Birthdays is null || !keyValuePair.Value.Birthdays.Any()) @@ -675,10 +736,9 @@ public class MapLogic personBirthday = keyValuePair.Value.Birthdays[zero]; foreach (string personDisplayDirectoryAllFile in keyValuePair.Value.DisplayDirectoryAllFiles) { - fileInfo = new(personDisplayDirectoryAllFile); - if (!fileInfo.Exists || !personDisplayDirectoryAllFile.EndsWith(resizeFilenameExtension)) + if (!personDisplayDirectoryAllFile.EndsWith(_FacesFileNameExtension)) continue; - (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(_Configuration.LocationDigits, personDisplayDirectoryAllFile); + (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(_Configuration.LocationDigits, _FacesFileNameExtension, personDisplayDirectoryAllFile); if (id is null || normalizedPixelPercentage is null) continue; if (_IdThenNormalizedPixelPercentageToPersonContainers.ContainsKey(id.Value)) @@ -687,16 +747,51 @@ public class MapLogic if (keyValuePairs.ContainsKey(normalizedPixelPercentage.Value)) continue; } + fileInfo = new(personDisplayDirectoryAllFile); + if (!fileInfo.Exists) + continue; + personDisplayFileName = Path.GetFileName(personDisplayDirectoryAllFile); + personDisplayDirectory = Path.GetDirectoryName(personDisplayDirectoryAllFile); personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personBirthday); mappingSegmentB = GetMappingSegmentB(_Ticks, personBirthday, keyValuePair.Value.ApproximateYears, fileInfo.CreationTime, isWrongYear: null); - directory = Path.Combine(_EDistanceContentTicksDirectory, by[1..], personKeyFormatted, mappingSegmentB); + directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, mappingSegmentB); personDirectory = Path.Combine(directory, keyValuePair.Value.DisplayDirectoryName, "lnk"); if (!Directory.Exists(personDirectory)) _ = Directory.CreateDirectory(personDirectory); + if (!idToNormalizedPixelPercentageToFace.ContainsKey(id.Value)) + throw new NotSupportedException(); + face = idToNormalizedPixelPercentageToFace[id.Value][normalizedPixelPercentage.Value]; + if (face.Mapping is null) + throw new NotSupportedException(); + if (string.IsNullOrEmpty(personDisplayDirectory)) + throw new NotSupportedException(); + directoryName = Path.GetDirectoryName(face.RelativePath); + if (string.IsNullOrEmpty(directoryName)) + throw new NotSupportedException(); + shortcutFile = Path.Combine(personDisplayDirectory, $"{personDisplayFileName}.lnk"); + facesDirectory = Path.Combine($"{dFacesContentDirectory}{directoryName}", face.Mapping.MappingFromItem.ImageFileHolder.NameWithoutExtension); + faceFileName = $"{face.Mapping.MappingFromLocation.DeterministicHashCodeKey}{face.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_FacesFileNameExtension}"; checkFile = Path.Combine(directory, fileInfo.Name); - if (File.Exists(checkFile)) + if (!File.Exists(checkFile)) + File.Copy(personDisplayDirectoryAllFile, checkFile); + if (personDisplayDirectoryAllFile.Contains(successfull)) continue; - File.Copy(personDisplayDirectoryAllFile, checkFile); + directoryName = Path.Combine(personDisplayDirectory, successfull); + if (!Directory.Exists(directoryName)) + _ = Directory.CreateDirectory(directoryName); + checkFile = Path.Combine(directoryName, personDisplayFileName); + File.Move(personDisplayDirectoryAllFile, checkFile); + faceFile = Path.Combine(facesDirectory, faceFileName); + if (!File.Exists(faceFile)) + continue; + if (File.Exists(shortcutFile)) + continue; + windowsShortcut = new() { Path = faceFile }; + windowsShortcut.Save(shortcutFile); + windowsShortcut.Dispose(); + if (!File.Exists(shortcutFile)) + continue; + File.SetLastWriteTime(shortcutFile, face.Mapping.MappingFromItem.MinimumDateTime); } } } diff --git a/Map/Models/Stateless/IMapLogic.cs b/Map/Models/Stateless/IMapLogic.cs index 2046d49..8ec8526 100644 --- a/Map/Models/Stateless/IMapLogic.cs +++ b/Map/Models/Stateless/IMapLogic.cs @@ -3,6 +3,10 @@ namespace View_by_Distance.Map.Models.Stateless; public interface IMapLogic { // ... + const int ForceSingleImage = 3; + const int ManualCopy = 4; + const int Mapping = 1; const int Sigma = 3; + const int Sorting = 2; } \ No newline at end of file diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index 20076f7..382f197 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -1,3 +1,4 @@ +using Humanizer; using ShellProgressBar; using System.Text.Json; using View_by_Distance.Shared.Models; @@ -33,7 +34,7 @@ internal abstract class MapLogic return results; } - private static void SetPersonCollections(Configuration configuration, string resizeFilenameExtension, List personContainers, List personKeys, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List personKeyFormattedCollection, Dictionary> skipCollection) + private static void SetPersonCollections(Configuration configuration, string facesFileNameExtension, List personContainers, List personKeys, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List personKeyFormattedCollection, Dictionary> skipCollection) { int? id; long personKey; @@ -44,9 +45,9 @@ internal abstract class MapLogic { foreach (string personDisplayDirectoryAllFile in personContainer.DisplayDirectoryAllFiles) { - if (Path.GetExtension(personDisplayDirectoryAllFile) != resizeFilenameExtension) + if (!personDisplayDirectoryAllFile.EndsWith(facesFileNameExtension)) continue; - (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(configuration.LocationDigits, personDisplayDirectoryAllFile); + (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(configuration.LocationDigits, facesFileNameExtension, personDisplayDirectoryAllFile); if (id is null || normalizedPixelPercentage is null) continue; if (!skipCollection.ContainsKey(id.Value)) @@ -73,9 +74,9 @@ internal abstract class MapLogic } } - internal static List<(string, string[], string, int?, int?, List?)> DeleteEmptyDirectoriesAndGetCollection(Configuration configuration, long ticks, string eDistanceContentDirectory, List personKeyFormattedCollection, Dictionary> keyValuePairs) + internal static List<(string, string[], string, List?)> DeleteEmptyDirectoriesAndGetCollection(Configuration configuration, string facesFileNameExtension, long ticks, string eDistanceContentDirectory, List personKeyFormattedCollection, Dictionary> keyValuePairs) { - List<(string, string[], string, int?, int?, List?)> results = new(); + List<(string, string[], string, List?)> results = new(); int? id; bool check; string[] files; @@ -94,7 +95,9 @@ internal abstract class MapLogic string? personFirstInitialDirectory; string[] personDisplayDirectoryNames; bool keyValuePairsAny = keyValuePairs.Any(); + string manualCopyHumanized = nameof(IMapLogic.ManualCopy).Humanize(LetterCasing.Title); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); + string forceSingleImageHumanized = nameof(IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title); string[] ticksDirectories = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly); string message = $") {ticksDirectories.Length:000} compile from and clean ticks Director(ies) - A - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; @@ -141,17 +144,19 @@ internal abstract class MapLogic Directory.Move(personNameDirectory, personFirstInitialDirectory); } files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); - if (personKeyFormatted == nameof(Models.MapLogic.ForceSingleImage) && files.Any()) - throw new Exception($"Move personKey directories up one from {nameof(Models.MapLogic.ForceSingleImage)} and delete {nameof(Models.MapLogic.ForceSingleImage)} directory!"); - if (personKeyFormatted == nameof(Sorting) && files.Any()) - throw new Exception($"Move personKey directories up one from {nameof(Sorting)} and delete {nameof(Sorting)} directory!"); + if (personKeyFormatted == nameof(IMapLogic.Sorting) && files.Any()) + throw new Exception($"Move personKey directories up one from {nameof(IMapLogic.Sorting)} and delete {nameof(IMapLogic.Sorting)} directory!"); + if (personKeyFormatted == manualCopyHumanized && files.Any()) + throw new Exception($"Move personKey directories up one from {manualCopyHumanized} and delete {manualCopyHumanized} directory!"); + if (personKeyFormatted == forceSingleImageHumanized && files.Any()) + throw new Exception($"Move personKey directories up one from {forceSingleImageHumanized} and delete {forceSingleImageHumanized} directory!"); if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length) continue; foreach (string file in files) { if (file.EndsWith(".lnk") || file.EndsWith(".json")) continue; - (id, normalizedPixelPercentage, faces) = IMapping.GetReversedDeterministicHashCodeKey(configuration.LocationDigits, keyValuePairsAny, keyValuePairs, file); + (id, normalizedPixelPercentage, faces) = IMapping.GetReversedDeterministicHashCodeKey(configuration.LocationDigits, facesFileNameExtension, keyValuePairsAny, keyValuePairs, file); if (id is null || normalizedPixelPercentage is null) continue; if (configuration.MappingMoveUnableToMatch) @@ -175,7 +180,7 @@ internal abstract class MapLogic checks.Add(normalizedPixelPercentage.Value); } } - results.Add(new(personKeyFormatted, personDisplayDirectoryNames, file, id, normalizedPixelPercentage, faces)); + results.Add(new(personKeyFormatted, personDisplayDirectoryNames, file, faces)); } personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string personNameLinkDirectory in personNameLinkDirectories) @@ -340,27 +345,16 @@ internal abstract class MapLogic } } - private static string? GetCheckFile(string file, int id, int normalizedPixelPercentage) + private static string? GetCheckFile(string facesFileNameExtension, string file, int id, int normalizedPixelPercentage) { string? result; - string? fileName = Path.GetFileName(file); - if (fileName is null) + string fileName = Path.GetFileName(file); + string? directoryName = Path.GetDirectoryName(file); + (string? Id, string? NormalizedPixelPercentage, string? ExtensionLowered, bool? Check) segments = IMapping.GetSegments(facesFileNameExtension, fileName); + if (string.IsNullOrEmpty(directoryName) || string.IsNullOrEmpty(segments.Id) || string.IsNullOrEmpty(segments.NormalizedPixelPercentage) || string.IsNullOrEmpty(segments.ExtensionLowered)) result = null; else - { - string[] segments = fileName.Split('.'); - if (segments.Length != 3) - result = null; - else - { - string extensionLowered = $".{segments[2]}"; - string? directoryName = Path.GetDirectoryName(file); - if (string.IsNullOrEmpty(directoryName)) - result = null; - else - result = Path.Combine(directoryName, $"{IMapping.GetDeterministicHashCodeKey(id, normalizedPixelPercentage)}{extensionLowered}.json"); - } - } + result = Path.Combine(directoryName, $"{IMapping.GetDeterministicHashCodeKey(id, normalizedPixelPercentage)}{segments.ExtensionLowered}.json"); return result; } @@ -436,67 +430,70 @@ internal abstract class MapLogic { } } - private static int SetCollectionsAndGetUnableToMatchCount(Configuration configuration, long ticks, string eDistanceContentDirectory, Shared.Models.Methods.IFaceDistance? distance, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedPixelPercentageCollection, List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, List<(string, string[], string, int?, int?, List?)> collection) + private static int SetCollectionsAndGetUnableToMatchCount(Configuration configuration, string facesFileNameExtension, long ticks, string eDistanceContentDirectory, Shared.Models.Methods.IFaceDistance? distance, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedPixelPercentageCollection, List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, List<(string, string[], string, List?)> collection) { + int? id; int result = 0; string? checkFile; List checkFaces = new(); + int? normalizedPixelPercentage; string newestPersonKeyFormatted; string personDisplayDirectoryName; int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") {collection.Count:000} join from ticks Director(ies) - B - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using ProgressBar progressBar = new(collection.Count, message, options); - foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string file, int? id, int? normalizedPixelPercentage, List? faces) in collection) + foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string file, List? faces) in collection) { progressBar.Tick(); + (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(configuration.LocationDigits, facesFileNameExtension, file); if (id is null || normalizedPixelPercentage is null) - continue; - if (faces is null) + { result++; - else + continue; + } + checkFile = GetCheckFile(facesFileNameExtension, file, id.Value, normalizedPixelPercentage.Value); + if (string.IsNullOrEmpty(checkFile)) + throw new NotSupportedException(); + if (faces is null) + { + result++; + continue; + } + checkFaces.Clear(); + foreach (Face face in faces) + { + if (face.Mapping is null) + throw new NotSupportedException(); + if (normalizedPixelPercentage.Value != face.Mapping.MappingFromLocation.NormalizedPixelPercentage) + continue; + checkFaces.Add(face); + } + if (checkFaces.Count != 1 && distance is not null && File.Exists(checkFile)) { checkFaces.Clear(); - foreach (Face face in faces) - { - if (face.Mapping is null) - throw new NotSupportedException(); - if (normalizedPixelPercentage.Value != face.Mapping.MappingFromLocation.NormalizedPixelPercentage) - continue; - checkFaces.Add(face); - } - checkFile = GetCheckFile(file, id.Value, normalizedPixelPercentage.Value); - if (string.IsNullOrEmpty(checkFile)) - { - result++; - continue; - } - if (checkFaces.Count != 1 && distance is not null && File.Exists(checkFile)) - { - checkFaces.Clear(); - checkFaces.AddRange(distance.GetMatchingFaces(configuration.FaceDistanceTolerance, checkFile, faces)); - } - if (!checkFaces.Any()) - { - result++; - if (configuration.MappingMoveUnableToMatch) - MoveUnableToMatch(configuration, eDistanceContentDirectory, file, checkFile); - continue; - } - if (checkFaces.Count != 1) - { - result++; - if (configuration.MappingMoveUnableToMatch) - MoveUnableToMatch(configuration, eDistanceContentDirectory, file, checkFile); - continue; - } - if (!Valid(checkFile, checkFaces)) - { - result++; - if (configuration.MappingMoveUnableToMatch) - MoveUnableToMatch(configuration, eDistanceContentDirectory, file, checkFile); - continue; - } + checkFaces.AddRange(distance.GetMatchingFaces(configuration.FaceDistanceTolerance, checkFile, faces)); + } + if (!checkFaces.Any()) + { + result++; + if (configuration.MappingMoveUnableToMatch) + MoveUnableToMatch(configuration, eDistanceContentDirectory, file, checkFile); + continue; + } + if (checkFaces.Count != 1) + { + result++; + if (configuration.MappingMoveUnableToMatch) + MoveUnableToMatch(configuration, eDistanceContentDirectory, file, checkFile); + continue; + } + if (!Valid(checkFile, checkFaces)) + { + result++; + if (configuration.MappingMoveUnableToMatch) + MoveUnableToMatch(configuration, eDistanceContentDirectory, file, checkFile); + continue; } if (!personKeyFormattedToNewestPersonKeyFormatted.ContainsKey(personKeyFormatted)) newestPersonKeyFormatted = personKeyFormatted; @@ -658,7 +655,7 @@ internal abstract class MapLogic } } - internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string resizeFilenameExtension, long ticks, List personContainers, string eDistanceContentDirectory, List distinctFilteredFaces, Shared.Models.Methods.IFaceDistance faceDistance, Dictionary personKeyToPersonContainer, Dictionary personKeyToRanges, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> idThenNormalizedPixelPercentageToPersonContainers) + internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string facesFileNameExtension, long ticks, List personContainers, string eDistanceContentDirectory, List distinctFilteredFaces, Shared.Models.Methods.IFaceDistance faceDistance, Dictionary personKeyToPersonContainer, Dictionary personKeyToRanges, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> idThenNormalizedPixelPercentageToPersonContainers) { if (configuration is null) throw new NullReferenceException(nameof(configuration)); @@ -671,7 +668,14 @@ internal abstract class MapLogic List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedPixelPercentageCollection = new(); List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection = new(); Dictionary> incorrectIdThenNormalizedPixelPercentageToPersonContainers = new(); - SetPersonCollections(configuration, resizeFilenameExtension, personContainers, personKeys, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection, skipCollection); + SetPersonCollections( + configuration, + facesFileNameExtension, + personContainers, + personKeys, + personKeyFormattedToNewestPersonKeyFormatted, + personKeyFormattedCollection, + skipCollection); personContainers.AddRange(AddToPersonKeysThenGetNonSpecificPeopleCollection(configuration, personKeys)); foreach (Face face in distinctFilteredFaces) { @@ -683,9 +687,34 @@ internal abstract class MapLogic keyValuePairs.Add(face.Mapping.MappingFromItem.Id, new()); keyValuePairs[face.Mapping.MappingFromItem.Id].Add(face); } - List<(string, string[], string, int?, int?, List?)> collection = DeleteEmptyDirectoriesAndGetCollection(configuration, ticks, eDistanceContentDirectory, personKeyFormattedCollection, keyValuePairs); - int unableToMatchCount = SetCollectionsAndGetUnableToMatchCount(configuration, ticks, eDistanceContentDirectory, faceDistance, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedIdThenNormalizedPixelPercentageCollection, incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, collection); - SetKeyValuePairs(configuration, ticks, personContainers, distinctFilteredFaces, personKeyFormattedIdThenNormalizedPixelPercentageCollection, incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, personKeyToPersonContainer, idThenNormalizedPixelPercentageToPersonContainers, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer, incorrectIdThenNormalizedPixelPercentageToPersonContainers, personKeyToRanges); + List<(string, string[], string, List?)> collection = DeleteEmptyDirectoriesAndGetCollection(configuration, + facesFileNameExtension, + ticks, + eDistanceContentDirectory, + personKeyFormattedCollection, + keyValuePairs); + int unableToMatchCount = SetCollectionsAndGetUnableToMatchCount( + configuration, + facesFileNameExtension, + ticks, + eDistanceContentDirectory, + faceDistance, + personKeyFormattedToNewestPersonKeyFormatted, + personKeyFormattedIdThenNormalizedPixelPercentageCollection, + incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, + collection); + SetKeyValuePairs( + configuration, + ticks, + personContainers, + distinctFilteredFaces, + personKeyFormattedIdThenNormalizedPixelPercentageCollection, + incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, + personKeyToPersonContainer, + idThenNormalizedPixelPercentageToPersonContainers, + possiblyNewPersonDisplayDirectoryNamesAndPersonContainer, + incorrectIdThenNormalizedPixelPercentageToPersonContainers, + personKeyToRanges); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") {collection.Count:000} message from ticks Director(ies) - C - {unableToMatchCount} Unable To Match Count / {collection.Count} Collection - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; @@ -701,9 +730,17 @@ 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); notMappedPersonContainers.AddRange(GetNotMappedPersonContainers(configuration, personContainers, personKeyCollection)); - AppendToSkipCollection(skipCollection, idThenNormalizedPixelPercentageToPersonContainers, incorrectIdThenNormalizedPixelPercentageToPersonContainers); + AppendToSkipCollection( + skipCollection, + idThenNormalizedPixelPercentageToPersonContainers, + incorrectIdThenNormalizedPixelPercentageToPersonContainers); if (possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Any()) - faceDistance.SavePossiblyNewPersonContainers(propertyConfiguration, configuration.PersonBirthdayFormat, resizeFilenameExtension, personKeyToPersonContainer, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); + faceDistance.SavePossiblyNewPersonContainers( + propertyConfiguration, + configuration.PersonBirthdayFormat, + facesFileNameExtension, + personKeyToPersonContainer, + possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); } } \ No newline at end of file diff --git a/Resize/Models/_C_Resize.cs b/Resize/Models/_C_Resize.cs index 435b79f..ce21b05 100644 --- a/Resize/Models/_C_Resize.cs +++ b/Resize/Models/_C_Resize.cs @@ -17,8 +17,8 @@ public class C_Resize public List AngleBracketCollection { get; } - protected readonly string _FilenameExtension; - public string FilenameExtension => _FilenameExtension; + protected readonly string _FileNameExtension; + public string FileNameExtension => _FileNameExtension; private readonly Serilog.ILogger? _Log; private readonly int _TempResolutionWidth; @@ -47,7 +47,7 @@ public class C_Resize _ValidResolutions = validResolutions; _OutputResolutionOrientationIndex = 2; _EncoderParameters = encoderParameters; - _FilenameExtension = filenameExtension; + _FileNameExtension = filenameExtension; _Log = Serilog.Log.ForContext(); AngleBracketCollection = new List(); _OverrideForResizeImages = overrideForResizeImages; @@ -344,7 +344,7 @@ public class C_Resize if (File.Exists(parentCheck)) { File.Move(parentCheck, fileInfo.FullName); - item.SetResizedFileHolder(_FilenameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(item.ResizedFileHolder)); + item.SetResizedFileHolder(_FileNameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(item.ResizedFileHolder)); fileInfo.Refresh(); } } @@ -358,7 +358,7 @@ public class C_Resize if (!fileInfo.Exists) { File.Copy(item.ImageFileHolder.FullName, fileInfo.FullName); - item.SetResizedFileHolder(_FilenameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(item.ResizedFileHolder)); + item.SetResizedFileHolder(_FileNameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(item.ResizedFileHolder)); subFileTuples.Add(new Tuple(nameof(C_Resize), DateTime.Now)); } } @@ -376,7 +376,7 @@ public class C_Resize if (check) { _ = SaveResizedSubfile(item, resize, returnAndDoNotWrite: false); - item.SetResizedFileHolder(_FilenameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(item.ResizedFileHolder)); + item.SetResizedFileHolder(_FileNameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(item.ResizedFileHolder)); subFileTuples.Add(new Tuple(nameof(C_Resize), DateTime.Now)); } } @@ -544,7 +544,7 @@ public class C_Resize } } Shared.Models.FileHolder fileHolder = new(Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(item.ImageFileHolder.FullName))); - item.SetResizedFileHolder(_FilenameExtension, fileHolder); + item.SetResizedFileHolder(_FileNameExtension, fileHolder); return results; } diff --git a/Shared/Models/Methods/IFaceDistance.cs b/Shared/Models/Methods/IFaceDistance.cs index 13686d6..6040ec0 100644 --- a/Shared/Models/Methods/IFaceDistance.cs +++ b/Shared/Models/Methods/IFaceDistance.cs @@ -4,6 +4,6 @@ public interface IFaceDistance { List GetMatchingFaces(double faceDistanceTolerance, string checkFile, List faces); - void SavePossiblyNewPersonContainers(Properties.IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string resizeFilenameExtension, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); + void SavePossiblyNewPersonContainers(Properties.IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IMapping.cs b/Shared/Models/Stateless/Methods/IMapping.cs index ed43816..9f85a51 100644 --- a/Shared/Models/Stateless/Methods/IMapping.cs +++ b/Shared/Models/Stateless/Methods/IMapping.cs @@ -6,14 +6,19 @@ public interface IMapping static string GetDeterministicHashCodeKey(int id, int normalizedPixelPercentage) => $"{id}.{normalizedPixelPercentage}"; - (int?, int?, List?) TestStatic_GetReversedDeterministicHashCodeKey(int locationDigits, string file) => - GetReversedDeterministicHashCodeKey(locationDigits, file); - static (int?, int?, List?) GetReversedDeterministicHashCodeKey(int locationDigits, string file) => - Mapping.GetReversedDeterministicHashCodeKey(locationDigits, false, new(), file); + (string?, string?, string?, bool?) TestStatic_GetSegments(string facesFileNameExtension, string fileName) + => GetSegments(facesFileNameExtension, fileName); + static (string?, string?, string?, bool?) GetSegments(string facesFileNameExtension, string fileName) + => Mapping.GetSegments(facesFileNameExtension, fileName); - (int?, int?, List?) TestStatic_GetReversedDeterministicHashCodeKey(int locationDigits, bool keyValuePairsAny, Dictionary> keyValuePairs, string file) => - GetReversedDeterministicHashCodeKey(locationDigits, keyValuePairsAny, keyValuePairs, file); - static (int?, int?, List?) GetReversedDeterministicHashCodeKey(int locationDigits, bool keyValuePairsAny, Dictionary> keyValuePairs, string file) => - Mapping.GetReversedDeterministicHashCodeKey(locationDigits, keyValuePairsAny, keyValuePairs, file); + (int?, int?, List?) TestStatic_GetReversedDeterministicHashCodeKey(int locationDigits, string facesFileNameExtension, string file) => + GetReversedDeterministicHashCodeKey(locationDigits, facesFileNameExtension, file); + static (int?, int?, List?) GetReversedDeterministicHashCodeKey(int locationDigits, string facesFileNameExtension, string file) => + Mapping.GetReversedDeterministicHashCodeKey(locationDigits, facesFileNameExtension, false, new(), file); + + (int?, int?, List?) TestStatic_GetReversedDeterministicHashCodeKey(int locationDigits, string facesFileNameExtension, bool keyValuePairsAny, Dictionary> keyValuePairs, string file) => + GetReversedDeterministicHashCodeKey(locationDigits, facesFileNameExtension, keyValuePairsAny, keyValuePairs, file); + static (int?, int?, List?) GetReversedDeterministicHashCodeKey(int locationDigits, string facesFileNameExtension, bool keyValuePairsAny, Dictionary> keyValuePairs, string file) => + Mapping.GetReversedDeterministicHashCodeKey(locationDigits, facesFileNameExtension, keyValuePairsAny, keyValuePairs, file); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPersonContainer.cs b/Shared/Models/Stateless/Methods/IPersonContainer.cs index 6083ad2..7cb58e8 100644 --- a/Shared/Models/Stateless/Methods/IPersonContainer.cs +++ b/Shared/Models/Stateless/Methods/IPersonContainer.cs @@ -5,9 +5,9 @@ public interface IPersonContainer // ... - Models.PersonContainer[] TestStatic_GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat) => - GetPersonContainers(storage, personBirthdayFormat); - static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat) => - PersonContainer.GetPersonContainers(storage, personBirthdayFormat); + Models.PersonContainer[] TestStatic_GetPersonContainers(Properties.IStorage storage, int locationDigits, string personBirthdayFormat, string facesFileNameExtension) => + GetPersonContainers(storage, locationDigits, personBirthdayFormat, facesFileNameExtension); + static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, int locationDigits, string personBirthdayFormat, string facesFileNameExtension) => + PersonContainer.GetPersonContainers(storage, locationDigits, personBirthdayFormat, facesFileNameExtension); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/Mapping.cs b/Shared/Models/Stateless/Methods/Mapping.cs index aa1247d..6346f4a 100644 --- a/Shared/Models/Stateless/Methods/Mapping.cs +++ b/Shared/Models/Stateless/Methods/Mapping.cs @@ -3,28 +3,29 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class Mapping { - private static void IfNotAlreadyFileMove(string file, int idValue, int normalizedPixelPercentageValue, string extensionLowered) + private static void IfNotAlreadyFileMove(string facesFileNameExtension, string file, int idValue, int normalizedPixelPercentageValue, string extensionLowered) { string? directoryName = Path.GetDirectoryName(file); if (string.IsNullOrEmpty(directoryName)) throw new Exception(); - string checkFile = Path.Combine(directoryName, $"{IMapping.GetDeterministicHashCodeKey(idValue, normalizedPixelPercentageValue)}{extensionLowered}"); + string checkFile = Path.Combine(directoryName, $"{IMapping.GetDeterministicHashCodeKey(idValue, normalizedPixelPercentageValue)}{extensionLowered}{facesFileNameExtension}"); if (!File.Exists(checkFile)) File.Move(file, checkFile); } - private static (int?, int?, List?) GetReversedDeterministicHashCodeKeysFromSegments(int locationDigits, bool keyValuePairsAny, Dictionary> keyValuePairs, string file, string[] segments) + private static (int?, int?, List?) GetReversedDeterministicHashCodeKeysFromSegments(int locationDigits, string facesFileNameExtension, bool keyValuePairsAny, Dictionary> keyValuePairs, string file, string fileName) { int? id; List? faces; int? normalizedPixelPercentage; - if (segments.Length != 3) + (string? Id, string? NormalizedPixelPercentage, string? ExtensionLowered, bool? Check) segments = GetSegments(facesFileNameExtension, fileName); + if (string.IsNullOrEmpty(segments.Id) || string.IsNullOrEmpty(segments.NormalizedPixelPercentage) || string.IsNullOrEmpty(segments.ExtensionLowered) || segments.Check is null) { id = null; faces = null; normalizedPixelPercentage = null; } - else if (!int.TryParse(segments[0], out int idValue) || !int.TryParse(ILocation.GetRightPadded(locationDigits, segments[1]), out int normalizedPixelPercentageValue)) + else if (!int.TryParse(segments.Id, out int idValue) || !int.TryParse(ILocation.GetRightPadded(locationDigits, segments.NormalizedPixelPercentage), out int normalizedPixelPercentageValue)) { id = null; faces = null; @@ -33,10 +34,9 @@ internal abstract class Mapping else { id = idValue; - string extensionLowered = $".{segments[2]}"; normalizedPixelPercentage = normalizedPixelPercentageValue; - if (segments[1].Length != locationDigits) - IfNotAlreadyFileMove(file, idValue, normalizedPixelPercentageValue, extensionLowered); + if (segments.Check.Value || segments.NormalizedPixelPercentage.Length != locationDigits) + IfNotAlreadyFileMove(facesFileNameExtension, file, idValue, normalizedPixelPercentageValue, segments.ExtensionLowered); if (!keyValuePairsAny || !keyValuePairs.ContainsKey(idValue)) faces = null; else @@ -45,7 +45,31 @@ internal abstract class Mapping return new(id, normalizedPixelPercentage, faces); } - internal static (int?, int?, List?) GetReversedDeterministicHashCodeKey(int locationDigits, bool keyValuePairsAny, Dictionary> keyValuePairs, string file) + internal static (string?, string?, string?, bool?) GetSegments(string facesFileNameExtension, string fileName) + { + string[] segments = fileName.Split('.'); + string? id; + string? extensionLowered; + bool? needsFacesFileNameExtension; + string? normalizedPixelPercentage; + if (segments.Length < 3 || (segments.Length == 4 && $".{segments[3]}" != facesFileNameExtension)) + { + id = null; + extensionLowered = null; + normalizedPixelPercentage = null; + needsFacesFileNameExtension = null; + } + else + { + id = segments[0]; + extensionLowered = $".{segments[2]}"; + normalizedPixelPercentage = segments[1]; + needsFacesFileNameExtension = segments.Length == 3; + } + return new(id, normalizedPixelPercentage, extensionLowered, needsFacesFileNameExtension); + } + + internal static (int?, int?, List?) GetReversedDeterministicHashCodeKey(int locationDigits, string facesFileNameExtension, bool keyValuePairsAny, Dictionary> keyValuePairs, string file) { int? id; List? faces; @@ -58,10 +82,13 @@ internal abstract class Mapping normalizedPixelPercentage = null; } else - { - string[] segments = fileName.Split('.'); - (id, normalizedPixelPercentage, faces) = GetReversedDeterministicHashCodeKeysFromSegments(locationDigits, keyValuePairsAny, keyValuePairs, file, segments); - } + (id, normalizedPixelPercentage, faces) = GetReversedDeterministicHashCodeKeysFromSegments( + locationDigits, + facesFileNameExtension, + keyValuePairsAny, + keyValuePairs, + file, + fileName); return new(id, normalizedPixelPercentage, faces); } diff --git a/Shared/Models/Stateless/Methods/PersonContainer.cs b/Shared/Models/Stateless/Methods/PersonContainer.cs index c4f35c8..790f52f 100644 --- a/Shared/Models/Stateless/Methods/PersonContainer.cs +++ b/Shared/Models/Stateless/Methods/PersonContainer.cs @@ -3,7 +3,37 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class PersonContainer { - private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(string personBirthdayFormat, char[] chars, string personDisplayDirectory, string personDisplayDirectoryName, string[] personKeyDirectories, int? approximateYears, List collections) + private static string[] GetFiles(int locationDigits, string facesFileNameExtension, string personDisplayDirectory) + { + string[] results = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); + int? id; + string checkFile; + string? checkDirectory; + int? normalizedPixelPercentage; + foreach (string personDisplayDirectoryAllFile in results) + { + if (personDisplayDirectoryAllFile.EndsWith(".lnk")) + continue; + (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(locationDigits, facesFileNameExtension, personDisplayDirectoryAllFile); + if (id is not null && normalizedPixelPercentage is not null) + continue; + checkDirectory = Path.GetDirectoryName(personDisplayDirectoryAllFile); + if (string.IsNullOrEmpty(checkDirectory)) + continue; + checkDirectory = Path.Combine(checkDirectory, "_ Invalid"); + if (!Directory.Exists(checkDirectory)) + _ = Directory.CreateDirectory(checkDirectory); + checkFile = Path.Combine(checkDirectory, Path.GetFileName(personDisplayDirectoryAllFile)); + if (File.Exists(checkFile)) + File.Delete(personDisplayDirectoryAllFile); + else + File.Move(personDisplayDirectoryAllFile, checkFile); + } + results = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.AllDirectories); + return results; + } + + private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(int locationDigits, string personBirthdayFormat, string facesFileNameExtension, char[] chars, string personDisplayDirectory, string personDisplayDirectoryName, string[] personKeyDirectories, int? approximateYears, List collections) { List<(long?, Models.PersonContainer)> results = new(); long personKey; @@ -14,7 +44,7 @@ internal abstract class PersonContainer Models.PersonBirthday? personBirthday; Models.PersonContainer personContainer; Models.PersonBirthday[] personBirthdays = collections.OrderByDescending(l => l.Value).ToArray(); - string[] personDisplayDirectoryAllFiles = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.AllDirectories); + string[] personDisplayDirectoryAllFiles = GetFiles(locationDigits, facesFileNameExtension, personDisplayDirectory); foreach (string personKeyDirectory in personKeyDirectories) { personKeyFormatted = Path.GetFileName(personKeyDirectory); @@ -30,15 +60,15 @@ internal abstract class PersonContainer return results; } - private static Models.PersonContainer GetPersonContainer(string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears) + private static Models.PersonContainer GetPersonContainer(int locationDigits, string facesFileNameExtension, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears) { Models.PersonContainer result; - string[] personDisplayDirectoryAllFiles = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.AllDirectories); + string[] personDisplayDirectoryAllFiles = GetFiles(locationDigits, facesFileNameExtension, personDisplayDirectory); result = new(approximateYears, personDisplayDirectoryAllFiles, personDisplayDirectoryName); return result; } - private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(string personBirthdayFormat, char[] chars, string[] personDisplayDirectories) + private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(int locationDigits, string personBirthdayFormat, string facesFileNameExtension, char[] chars, string[] personDisplayDirectories) { List<(long?, Models.PersonContainer)> results = new(); int? approximateYears; @@ -55,17 +85,17 @@ internal abstract class PersonContainer personKeyDirectories = Directory.GetDirectories(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); collections = PersonBirthday.GetPersonBirthdays(personBirthdayFormat, personKeyDirectories, personDisplayDirectory); if (collections.Any()) - results.AddRange(GetPersonContainersCollections(personBirthdayFormat, chars, personDisplayDirectory, personDisplayDirectoryName, personKeyDirectories, approximateYears, collections)); + results.AddRange(GetPersonContainersCollections(locationDigits, personBirthdayFormat, facesFileNameExtension, chars, personDisplayDirectory, personDisplayDirectoryName, personKeyDirectories, approximateYears, collections)); else { - personContainer = GetPersonContainer(personDisplayDirectory, personDisplayDirectoryName, approximateYears); + personContainer = GetPersonContainer(locationDigits, facesFileNameExtension, personDisplayDirectory, personDisplayDirectoryName, approximateYears); results.Add(new(null, personContainer)); } } return results; } - private static Models.PersonContainer[] GetPersonContainersGroups(string personBirthdayFormat, char[] chars, string[] groupDirectories) + private static Models.PersonContainer[] GetPersonContainersGroups(int locationDigits, string personBirthdayFormat, string facesFileNameExtension, char[] chars, string[] groupDirectories) { Models.PersonContainer[] results; const int zero = 0; @@ -79,14 +109,14 @@ internal abstract class PersonContainer if (!chars.Contains(groupDirectoryName[zero])) continue; personDisplayDirectories = Directory.GetDirectories(groupDirectory, "*", SearchOption.TopDirectoryOnly); - collection = GetPersonContainersGroup(personBirthdayFormat, chars, personDisplayDirectories); + collection = GetPersonContainersGroup(locationDigits, personBirthdayFormat, facesFileNameExtension, chars, 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) + internal static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, int locationDigits, string personBirthdayFormat, string facesFileNameExtension) { Models.PersonContainer[] results; char[] chars = IAge.GetChars(); @@ -104,7 +134,7 @@ internal abstract class PersonContainer if (!groupDirectories.Any()) results = Array.Empty(); else - results = GetPersonContainersGroups(personBirthdayFormat, chars, groupDirectories); + results = GetPersonContainersGroups(locationDigits, personBirthdayFormat, facesFileNameExtension, chars, groupDirectories); return results; } diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 777179b..565c681 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -28,6 +28,7 @@ + diff --git a/Tests/UnitTestCalculations.cs b/Tests/UnitTestCalculations.cs index e6c679a..0481590 100644 --- a/Tests/UnitTestCalculations.cs +++ b/Tests/UnitTestCalculations.cs @@ -1,3 +1,4 @@ +using Humanizer; using Microsoft.Extensions.Configuration; using Microsoft.VisualStudio.TestTools.UnitTesting; using Phares.Shared; @@ -122,6 +123,13 @@ public class UnitTestCalculations Assert.IsTrue($"({l}{d.ToString("0.00")[1..]})" == "(637967784888423594.45)"); } + [TestMethod] + public void TestMethodHumanize() + { + string successfull = $"_ {"ManualCopy".Humanize(LetterCasing.Title)} Successfull"; + Assert.IsTrue(successfull == "_ Manual Copy Successfull"); + } + [TestMethod] public void TestMethodDirectory() {