From be7a6abbf4cb814cfc245e810b0ebba0ca596602 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Fri, 19 Aug 2022 21:37:36 -0700 Subject: [PATCH] AppSettings and Configuration changes, major changes to E_Distance and minor for D_Face --- Compare/Compare.cs | 26 +- Compare/Models/AppSettings.cs | 22 +- Compare/Models/Binder/AppSettings.cs | 38 +- Compare/Models/Stateless/AppSettings.cs | 40 -- Compare/Program.cs | 6 +- Date-Group/DateGroup.cs | 14 +- Date-Group/Models/AppSettings.cs | 22 +- Date-Group/Models/Binder/AppSettings.cs | 38 +- Date-Group/Models/Stateless/AppSettings.cs | 40 -- Date-Group/Program.cs | 6 +- FaceRecognitionDotNet/FaceRecognition.cs | 6 +- FaceRecognitionDotNet/Image.cs | 18 +- Instance/DlibDotNet.cs | 411 ++++++++---------- Instance/Models/AppSettings.cs | 22 +- Instance/Models/Binder/AppSettings.cs | 38 +- Instance/Models/Binder/Configuration.cs | 194 +++++++-- Instance/Models/Configuration.cs | 216 ++++----- Instance/Models/DistanceHolder.cs | 48 ++ Instance/Models/Stateless/AppSettings.cs | 40 -- Instance/Models/Stateless/Configuration.cs | 44 -- Instance/Models/_D2_FaceLandmark.cs | 4 +- Instance/Models/_D_Face.cs | 73 ++-- Instance/Models/_E_Distance.cs | 351 +++++++-------- Instance/Models/_F_Random.cs | 4 +- Instance/Models/_G_Index.cs | 4 +- Instance/Program.cs | 6 +- Instance/appsettings.Staging.json | 1 + Instance/appsettings.json | 1 + Not-Copy-Copy/Models/AppSettings.cs | 22 +- Not-Copy-Copy/Models/Binder/AppSettings.cs | 38 +- Not-Copy-Copy/Models/Stateless/AppSettings.cs | 40 -- Not-Copy-Copy/Not-Copy-Copy.cs | 6 +- Not-Copy-Copy/Program.cs | 6 +- PrepareForOld/Models/AppSettings.cs | 22 +- PrepareForOld/Models/Binder/AppSettings.cs | 38 +- PrepareForOld/Models/Stateless/AppSettings.cs | 40 -- PrepareForOld/PrepareForOld.cs | 10 +- PrepareForOld/Program.cs | 6 +- Property/Models/Closest.cs | 16 +- Property/Models/Item.cs | 90 ++-- Property/Models/Named.cs | 66 ++- Property/Models/PropertyLogic.cs | 152 +++++-- Property/Models/Stateless/Container.cs | 2 +- Resize/Models/_C_Resize.cs | 12 +- Shared/Models/Location.cs | 22 +- Shared/Models/Properties/ILocation.cs | 3 +- Shared/Models/Stateless/Methods/ILocation.cs | 8 + .../Stateless/Methods/IPersonBirthday.cs | 3 - .../Stateless/Methods/PersonBirthday.cs | 4 +- Tests/Models/AppSettings.cs | 22 +- Tests/Models/Binder/AppSettings.cs | 38 +- Tests/Models/Stateless/AppSettings.cs | 40 -- Tests/UnitTestExample.cs | 2 +- Tests/UnitTestResize.cs | 16 +- .../Models/AppSettings.cs | 22 +- .../Models/Binder/AppSettings.cs | 38 +- .../Models/Stateless/AppSettings.cs | 40 -- .../TestsWithFaceRecognitionDotNet.csproj | 5 + .../UnitTestExample.cs | 2 +- .../UnitTestFace.cs | 49 ++- 60 files changed, 1269 insertions(+), 1344 deletions(-) delete mode 100644 Compare/Models/Stateless/AppSettings.cs delete mode 100644 Date-Group/Models/Stateless/AppSettings.cs create mode 100644 Instance/Models/DistanceHolder.cs delete mode 100644 Instance/Models/Stateless/AppSettings.cs delete mode 100644 Instance/Models/Stateless/Configuration.cs delete mode 100644 Not-Copy-Copy/Models/Stateless/AppSettings.cs delete mode 100644 PrepareForOld/Models/Stateless/AppSettings.cs create mode 100644 Shared/Models/Stateless/Methods/ILocation.cs delete mode 100644 Tests/Models/Stateless/AppSettings.cs delete mode 100644 TestsWithFaceRecognitionDotNet/Models/Stateless/AppSettings.cs diff --git a/Compare/Compare.cs b/Compare/Compare.cs index 41aedd4..05a016a 100644 --- a/Compare/Compare.cs +++ b/Compare/Compare.cs @@ -34,8 +34,6 @@ public class Compare string renameTo; string[] segments; _AppSettings = appSettings; - if (appSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); _RenameFindReplace = new(); _RenameBFindReplace = new(); _RenameCFindReplace = new(); @@ -106,7 +104,7 @@ public class Compare _RenameCFindReplace.Add(new(renameFrom, renameTo)); } groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories); - if (appSettings.MaxDegreeOfParallelism.Value < 2) + if (appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); _Log.Information($"{nameof(Property.Models.Stateless.Container.GetGroupCollection)} has finished"); _Configuration = configuration; @@ -118,7 +116,7 @@ public class Compare topDirectories.Clear(); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories); - if (appSettings.MaxDegreeOfParallelism.Value < 2) + if (appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); } _Log.Information($"{nameof(PossiblyRename)} has finished"); @@ -127,7 +125,7 @@ public class Compare topDirectories.Clear(); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories); - if (appSettings.MaxDegreeOfParallelism.Value < 2) + if (appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); } _Log.Information($"{nameof(PossiblyRenameB)} has finished"); @@ -136,7 +134,7 @@ public class Compare topDirectories.Clear(); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories); - if (appSettings.MaxDegreeOfParallelism.Value < 2) + if (appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); } _Log.Information($"{nameof(PossiblyRenameC)} has finished"); @@ -145,7 +143,7 @@ public class Compare topDirectories.Clear(); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories); - if (appSettings.MaxDegreeOfParallelism.Value < 2) + if (appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); } _Log.Information($"{nameof(PossiblyCorrect)} has finished"); @@ -158,7 +156,7 @@ public class Compare topDirectories.Clear(); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories); - if (appSettings.MaxDegreeOfParallelism.Value < 2) + if (appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); } if (_IsEnvironment.Development && propertyConfiguration.PopulatePropertyId.Value && !propertyLogic.KeyValuePairs.Any()) @@ -389,11 +387,9 @@ public class Compare private PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel) { PropertyLogic result; - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); if (_Configuration?.PropertyConfiguration is null) throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, reverse, model, predictorModel); + result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, reverse, model, predictorModel); string fromPrepareForOld = "34720-637858334555170379.tsv"; string fromPrepareForOldFile = Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, fromPrepareForOld); if (File.Exists(fromPrepareForOldFile)) @@ -433,8 +429,6 @@ public class Compare { if (_Log is null) throw new NullReferenceException(nameof(_Log)); - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); if (_Configuration?.PropertyConfiguration is null) throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); @@ -461,7 +455,7 @@ public class Compare throw new Exception("Invalid directory should end with {}!"); diffRootDirectory = Property.Models.Stateless.A_Property.GetDiffRootDirectory(_Configuration.DiffPropertyDirectory); } - PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory); + PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory); if (string.IsNullOrEmpty(_Configuration.DiffPropertyDirectory) || !Directory.Exists(_Configuration.DiffPropertyDirectory)) diffPropertyCompareCollection = Array.Empty(); else @@ -509,14 +503,12 @@ public class Compare private void ChangeExtensionFromDeleteToJson(string aPropertySingletonDirectory) { - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); string searchPattern = "*.delete"; long ticks = DateTime.Now.Ticks; List topDirectories = new(); List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection; groupCollection = Property.Models.Stateless.Container.GetGroupCollection(aPropertySingletonDirectory, searchPattern, topDirectories); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) + if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection) { diff --git a/Compare/Models/AppSettings.cs b/Compare/Models/AppSettings.cs index 6c0b44d..bae2431 100644 --- a/Compare/Models/AppSettings.cs +++ b/Compare/Models/AppSettings.cs @@ -6,24 +6,16 @@ namespace View_by_Distance.Compare.Models; public class AppSettings { - protected string _Company; - protected string _WorkingDirectoryName; - protected int? _MaxDegreeOfParallelism; - public string Company => _Company; - public string WorkingDirectoryName => _WorkingDirectoryName; - public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism; - - // public AppSettings() - // { - - // } + public string Company { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string WorkingDirectoryName { init; get; } [JsonConstructor] - public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism) + public AppSettings(string company, int maxDegreeOfParallelism, string workingDirectoryName) { - _Company = company; - _WorkingDirectoryName = workingDirectoryName; - _MaxDegreeOfParallelism = maxDegreeOfParallelism; + Company = company; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + WorkingDirectoryName = workingDirectoryName; } public override string ToString() diff --git a/Compare/Models/Binder/AppSettings.cs b/Compare/Models/Binder/AppSettings.cs index d9c160d..ef8806e 100644 --- a/Compare/Models/Binder/AppSettings.cs +++ b/Compare/Models/Binder/AppSettings.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Configuration; using System.Text.Json; namespace View_by_Distance.Compare.Models.Binder; @@ -6,16 +6,13 @@ namespace View_by_Distance.Compare.Models.Binder; public class AppSettings { - [Display(Name = "Company"), Required] public string Company { get; set; } - [Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; } - [Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; } +#nullable disable - public AppSettings() - { - Company = string.Empty; - WorkingDirectoryName = string.Empty; - MaxDegreeOfParallelism = -1; - } + public string Company { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string WorkingDirectoryName { get; set; } + +#nullable restore public override string ToString() { @@ -23,4 +20,25 @@ public class AppSettings return result; } + private static Models.AppSettings Get(AppSettings appSettings) + { + Models.AppSettings result; + if (appSettings.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + result = new( + appSettings.Company, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + } \ No newline at end of file diff --git a/Compare/Models/Stateless/AppSettings.cs b/Compare/Models/Stateless/AppSettings.cs deleted file mode 100644 index 395e813..0000000 --- a/Compare/Models/Stateless/AppSettings.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.Extensions.Configuration; -using System.Text.Json; - -namespace View_by_Distance.Compare.Models.Stateless; - -public abstract class AppSettings -{ - - public static Models.AppSettings Get(IConfigurationRoot configurationRoot) - { - Models.AppSettings? result; - Binder.AppSettings appSettings = configurationRoot.Get(); - string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true }); - result = JsonSerializer.Deserialize(json); - if (result is null) - throw new Exception(json); - if (string.IsNullOrEmpty(result.Company)) - throw new Exception(json); - string jsonThis = result.ToString(); - if (jsonThis != json) - { - int? check = null; - int min = new int[] { json.Length, jsonThis.Length }.Min(); - for (int i = 0; i < min; i++) - { - if (json[i] == jsonThis[i]) - continue; - check = i; - break; - } - if (check is null) - throw new Exception(); - string a = json[..check.Value].Split(',')[^1]; - string b = json[check.Value..].Split(',')[0]; - throw new Exception($"{a}{b}"); - } - return result; - } - -} \ No newline at end of file diff --git a/Compare/Program.cs b/Compare/Program.cs index 8618984..b7e031d 100644 --- a/Compare/Program.cs +++ b/Compare/Program.cs @@ -21,10 +21,8 @@ public class Program .AddEnvironmentVariables() .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); IConfigurationRoot configurationRoot = configurationBuilder.Build(); - AppSettings appSettings = Models.Stateless.AppSettings.Get(configurationRoot); - if (appSettings.MaxDegreeOfParallelism is null) - throw new Exception("MaxDegreeOfParallelism must be set!"); - if (appSettings.MaxDegreeOfParallelism.Value > Environment.ProcessorCount) + AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount) throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!"); if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) throw new Exception("Working directory name must have a value!"); diff --git a/Date-Group/DateGroup.cs b/Date-Group/DateGroup.cs index 295da4d..7839a06 100644 --- a/Date-Group/DateGroup.cs +++ b/Date-Group/DateGroup.cs @@ -30,8 +30,6 @@ public class DateGroup if (console is null) { } _AppSettings = appSettings; - if (appSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); _IsEnvironment = isEnvironment; _Exceptions = new List(); _Log = Serilog.Log.ForContext(); @@ -58,11 +56,11 @@ public class DateGroup string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories); foreach (string dbFile in dbFiles) File.Delete(dbFile); - if (true || appSettings.MaxDegreeOfParallelism.Value < 2) + if (true || appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(File.Delete)); for (int i = 1; i < 10; i++) _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); - if (true || appSettings.MaxDegreeOfParallelism.Value < 2) + if (true || appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.IPath.DeleteEmptyDirectories)); List containers = Property.Models.Stateless.A_Property.Get(propertyConfiguration, propertyLogic); if (configuration.ByCreateDateShortcut.HasValue && configuration.ByCreateDateShortcut.Value) @@ -72,7 +70,7 @@ public class DateGroup List topDirectories = new(); List directoryInfoCollection = new(); propertyLogic.ParallelWork(ticks, containers, firstPass: true); - if (appSettings.MaxDegreeOfParallelism.Value < 2) + if (appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(PropertyLogic.ParallelWork)); if (propertyLogic.ExceptionsDirectories.Any()) throw new Exception(); @@ -80,7 +78,7 @@ public class DateGroup { if (Property.Models.Stateless.A_Property.Any(containers)) propertyLogic.ParallelWork(ticks, containers, firstPass: false); - if (appSettings.MaxDegreeOfParallelism.Value < 2) + if (appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(PropertyLogic.ParallelWork)); if (propertyLogic.ExceptionsDirectories.Any()) throw new Exception(); @@ -331,11 +329,9 @@ public class DateGroup private PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel) { PropertyLogic result; - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); if (_Configuration?.PropertyConfiguration is null) throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, reverse, model, predictorModel); + result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, reverse, model, predictorModel); return result; } diff --git a/Date-Group/Models/AppSettings.cs b/Date-Group/Models/AppSettings.cs index 998922e..e30a6e2 100644 --- a/Date-Group/Models/AppSettings.cs +++ b/Date-Group/Models/AppSettings.cs @@ -6,24 +6,16 @@ namespace View_by_Distance.Date.Group.Models; public class AppSettings { - protected string _Company; - protected string _WorkingDirectoryName; - protected int? _MaxDegreeOfParallelism; - public string Company => _Company; - public string WorkingDirectoryName => _WorkingDirectoryName; - public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism; - - // public AppSettings() - // { - - // } + public string Company { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string WorkingDirectoryName { init; get; } [JsonConstructor] - public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism) + public AppSettings(string company, int maxDegreeOfParallelism, string workingDirectoryName) { - _Company = company; - _WorkingDirectoryName = workingDirectoryName; - _MaxDegreeOfParallelism = maxDegreeOfParallelism; + Company = company; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + WorkingDirectoryName = workingDirectoryName; } public override string ToString() diff --git a/Date-Group/Models/Binder/AppSettings.cs b/Date-Group/Models/Binder/AppSettings.cs index 01cf4a1..ec9380a 100644 --- a/Date-Group/Models/Binder/AppSettings.cs +++ b/Date-Group/Models/Binder/AppSettings.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Configuration; using System.Text.Json; namespace View_by_Distance.Date.Group.Models.Binder; @@ -6,16 +6,13 @@ namespace View_by_Distance.Date.Group.Models.Binder; public class AppSettings { - [Display(Name = "Company"), Required] public string Company { get; set; } - [Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; } - [Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; } +#nullable disable - public AppSettings() - { - Company = string.Empty; - WorkingDirectoryName = string.Empty; - MaxDegreeOfParallelism = -1; - } + public string Company { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string WorkingDirectoryName { get; set; } + +#nullable restore public override string ToString() { @@ -23,4 +20,25 @@ public class AppSettings return result; } + private static Models.AppSettings Get(AppSettings appSettings) + { + Models.AppSettings result; + if (appSettings.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + result = new( + appSettings.Company, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + } \ No newline at end of file diff --git a/Date-Group/Models/Stateless/AppSettings.cs b/Date-Group/Models/Stateless/AppSettings.cs deleted file mode 100644 index 7c590af..0000000 --- a/Date-Group/Models/Stateless/AppSettings.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.Extensions.Configuration; -using System.Text.Json; - -namespace View_by_Distance.Date.Group.Models.Stateless; - -public abstract class AppSettings -{ - - public static Models.AppSettings Get(IConfigurationRoot configurationRoot) - { - Models.AppSettings? result; - Binder.AppSettings appSettings = configurationRoot.Get(); - string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true }); - result = JsonSerializer.Deserialize(json); - if (result is null) - throw new Exception(json); - if (string.IsNullOrEmpty(result.Company)) - throw new Exception(json); - string jsonThis = result.ToString(); - if (jsonThis != json) - { - int? check = null; - int min = new int[] { json.Length, jsonThis.Length }.Min(); - for (int i = 0; i < min; i++) - { - if (json[i] == jsonThis[i]) - continue; - check = i; - break; - } - if (check is null) - throw new Exception(); - string a = json[..check.Value].Split(',')[^1]; - string b = json[check.Value..].Split(',')[0]; - throw new Exception($"{a}{b}"); - } - return result; - } - -} \ No newline at end of file diff --git a/Date-Group/Program.cs b/Date-Group/Program.cs index 8a36aba..4326818 100644 --- a/Date-Group/Program.cs +++ b/Date-Group/Program.cs @@ -21,10 +21,8 @@ public class Program .AddEnvironmentVariables() .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); IConfigurationRoot configurationRoot = configurationBuilder.Build(); - AppSettings appSettings = Models.Stateless.AppSettings.Get(configurationRoot); - if (appSettings.MaxDegreeOfParallelism is null) - throw new Exception("MaxDegreeOfParallelism must be set!"); - if (appSettings.MaxDegreeOfParallelism.Value > Environment.ProcessorCount) + AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount) throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!"); if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) throw new Exception("Working directory name must have a value!"); diff --git a/FaceRecognitionDotNet/FaceRecognition.cs b/FaceRecognitionDotNet/FaceRecognition.cs index dfd8fea..968952d 100644 --- a/FaceRecognitionDotNet/FaceRecognition.cs +++ b/FaceRecognitionDotNet/FaceRecognition.cs @@ -471,7 +471,7 @@ public sealed class FaceRecognition : DisposableObject /// An enumerable collection of face location correspond to all faces in specified image. /// is null. /// or this object is disposed. - public List FaceLocations(Model model, Image image, int numberOfTimesToUpsample, bool sortByPixelPercentage) + public List FaceLocations(Model model, Image image, int numberOfTimesToUpsample, bool sortByNormalizedPixelPercentage) { if (image == null) throw new NullReferenceException(nameof(image)); @@ -487,8 +487,8 @@ public sealed class FaceRecognition : DisposableObject face.Dispose(); results.Add(new Location(confidence, ret, image.Width, image.Height)); } - if (sortByPixelPercentage) - results = (from l in results orderby l.PixelPercentage select l).ToList(); + if (sortByNormalizedPixelPercentage) + results = (from l in results orderby l.NormalizedPixelPercentage select l).ToList(); return results; } diff --git a/FaceRecognitionDotNet/Image.cs b/FaceRecognitionDotNet/Image.cs index 5d29653..a59cc9a 100644 --- a/FaceRecognitionDotNet/Image.cs +++ b/FaceRecognitionDotNet/Image.cs @@ -64,31 +64,31 @@ public sealed class Image : DisposableObject /// /// Saves this to the specified file. /// - /// A string that contains the name of the file to which to save this . + /// A string that contains the name of the file to which to save this . /// The for this . - /// is null. + /// is null. /// This object is disposed. - public void Save(string filename, ImageFormat format) + public void Save(string fileName, ImageFormat format) { - if (filename == null) - throw new NullReferenceException(nameof(filename)); + if (fileName == null) + throw new NullReferenceException(nameof(fileName)); ThrowIfDisposed(); - string? directory = Path.GetDirectoryName(filename); + string? directory = Path.GetDirectoryName(fileName); if (!Directory.Exists(directory) && !string.IsNullOrWhiteSpace(directory)) _ = Directory.CreateDirectory(directory); switch (format) { case ImageFormat.Bmp: - DlibDotNet.Dlib.SaveBmp(Matrix, filename); + DlibDotNet.Dlib.SaveBmp(Matrix, fileName); break; case ImageFormat.Jpeg: - DlibDotNet.Dlib.SaveJpeg(Matrix, filename); + DlibDotNet.Dlib.SaveJpeg(Matrix, fileName); break; case ImageFormat.Png: - DlibDotNet.Dlib.SavePng(Matrix, filename); + DlibDotNet.Dlib.SavePng(Matrix, fileName); break; } } diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 418dc4e..f92ff32 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -40,8 +40,6 @@ public class DlibDotNet string argZero; Person[] people; _AppSettings = appSettings; - if (appSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); _IsEnvironment = isEnvironment; _Exceptions = new List(); _Log = Serilog.Log.ForContext(); @@ -50,7 +48,7 @@ public class DlibDotNet Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory); _Log.Information(propertyConfiguration.RootDirectory); Property.Models.Configuration.Verify(propertyConfiguration); - Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); + Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); Verify(configuration); VerifyExtra(args, propertyConfiguration, configuration); _Configuration = configuration; @@ -60,47 +58,31 @@ public class DlibDotNet _Rename = new E3_Rename(configuration); _Distance = new E_Distance(configuration); _FaceLandmarks = new D2_FaceLandmarks(configuration); - if (configuration.ForceMetadataLastWriteTimeToCreationTime is null) - throw new NullReferenceException(nameof(configuration.ForceMetadataLastWriteTimeToCreationTime)); - if (configuration.ForceResizeLastWriteTimeToCreationTime is null) - throw new NullReferenceException(nameof(configuration.ForceResizeLastWriteTimeToCreationTime)); if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); - if (configuration.OutputQuality is null) - throw new NullReferenceException(nameof(configuration.OutputQuality)); - if (configuration.OverrideForResizeImages is null) - throw new NullReferenceException(nameof(configuration.OverrideForResizeImages)); - if (configuration.PropertiesChangedForMetadata is null) - throw new NullReferenceException(nameof(configuration.PropertiesChangedForMetadata)); - if (configuration.PropertiesChangedForResize is null) - throw new NullReferenceException(nameof(configuration.PropertiesChangedForResize)); - if (configuration.Reverse is null) - throw new NullReferenceException(nameof(configuration.Reverse)); - _Metadata = new(configuration.ForceMetadataLastWriteTimeToCreationTime.Value, configuration.PropertiesChangedForMetadata.Value); + _Metadata = new(configuration.ForceMetadataLastWriteTimeToCreationTime, configuration.PropertiesChangedForMetadata); if (args.Count > 0) argZero = Path.GetFullPath(args[0]); else argZero = Path.GetFullPath(propertyConfiguration.RootDirectory); _ArgZeroIsConfigurationRootDirectory = propertyConfiguration.RootDirectory == argZero; - (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters) = C_Resize.GetTuple(configuration.OutputExtension, configuration.OutputQuality.Value); - _Resize = new C_Resize(configuration.ForceResizeLastWriteTimeToCreationTime.Value, configuration.OverrideForResizeImages.Value, configuration.PropertiesChangedForResize.Value, configuration.ValidResolutions, imageCodecInfo, encoderParameters); + (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters) = C_Resize.GetTuple(configuration.OutputExtension, configuration.OutputQuality); + _Resize = new C_Resize(configuration.ForceResizeLastWriteTimeToCreationTime, configuration.OverrideForResizeImages, configuration.PropertiesChangedForResize, configuration.ValidResolutions, imageCodecInfo, encoderParameters); _Log.Information(configuration.ModelDirectory); (Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(configuration); _Faces = new D_Face(configuration, argZero, model, modelParameter, predictorModel); - if (configuration.SkipSearch is null) - throw new NullReferenceException(nameof(configuration.SkipSearch)); if (!_ArgZeroIsConfigurationRootDirectory) people = Array.Empty(); else people = _People.GetPeople(propertyConfiguration); - if (!isSilent && configuration.TestDistanceResults.HasValue && configuration.TestDistanceResults.Value) + if (!isSilent && configuration.TestDistanceResults) { E2_Navigate e2Navigate = new(console, configuration, argZero); e2Navigate.Navigate(propertyConfiguration, model, predictorModel, configuration.OutputResolutions[0]); _Log.Information(propertyConfiguration.RootDirectory); } - if (!configuration.SkipSearch.Value) - Search(propertyConfiguration, configuration.Reverse.Value, model, predictorModel, argZero, people, isSilent); + if (!configuration.SkipSearch) + Search(propertyConfiguration, configuration.Reverse, model, predictorModel, argZero, people, isSilent); if (_Exceptions.Count == 0 && _ArgZeroIsConfigurationRootDirectory) { long ticks = DateTime.Now.Ticks; @@ -113,7 +95,7 @@ public class DlibDotNet string d2FaceLandmarksRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(D2_FaceLandmarks)); _Log.Information(string.Concat("Cleaning <", d2FaceLandmarksRootDirectory, ">")); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(d2FaceLandmarksRootDirectory); - if (appSettings.MaxDegreeOfParallelism.Value < 2) + if (appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.IPath.DeleteEmptyDirectories)); } string message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}"; @@ -125,7 +107,7 @@ public class DlibDotNet long ticks = DateTime.Now.Ticks; foreach (string outputResolution in configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions) _Distance.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions(propertyConfiguration, model, predictorModel, outputResolution); - if (appSettings.MaxDegreeOfParallelism.Value < 2) + if (appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(E_Distance.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions)); } } @@ -141,6 +123,17 @@ public class DlibDotNet return result; } + private long LogDeltaInMinutes(long ticks, string methodName) + { + long result; + if (_Log is null) + throw new NullReferenceException(nameof(_Log)); + double delta = new TimeSpan(DateTime.Now.Ticks - ticks).Minutes; + _Log.Debug($"{methodName} took {Math.Floor(delta)} minutes(s)"); + result = DateTime.Now.Ticks; + return result; + } + #pragma warning disable CA1416 #pragma warning restore CA1416 @@ -201,82 +194,18 @@ public class DlibDotNet throw new Exception($"One or more {nameof(configuration.SaveShortcutsForOutputResolutions)} are not in the ValidResolutions list!"); if ((from l in configuration.SaveFaceLandmarkForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) throw new Exception($"One or more {nameof(configuration.SaveFaceLandmarkForOutputResolutions)} are not in the ValidResolutions list!"); - if (configuration.CheckJsonForDistanceResults is null) - throw new NullReferenceException(nameof(configuration.CheckJsonForDistanceResults)); - if (configuration.CrossDirectoryMaxItemsInDistanceCollection is null) - throw new NullReferenceException(nameof(configuration.CrossDirectoryMaxItemsInDistanceCollection)); - if (configuration.DistanceFactor is null) + if (configuration.DistanceFactor + configuration.LocationConfidenceFactor != 10) throw new NullReferenceException(nameof(configuration.DistanceFactor)); - if (configuration.ForceMetadataLastWriteTimeToCreationTime is null) - throw new NullReferenceException(nameof(configuration.ForceMetadataLastWriteTimeToCreationTime)); - if (configuration.ForceResizeLastWriteTimeToCreationTime is null) - throw new NullReferenceException(nameof(configuration.ForceResizeLastWriteTimeToCreationTime)); - if (configuration.IgnoreExtensions is null) - throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); - if (configuration.IgnoreRelativePaths is null) - throw new NullReferenceException(nameof(configuration.IgnoreRelativePaths)); - if (configuration.LoadOrCreateThenSaveIndex is null) - throw new NullReferenceException(nameof(configuration.LoadOrCreateThenSaveIndex)); - if (configuration.LocationConfidenceFactor is null) - throw new NullReferenceException(nameof(configuration.LocationConfidenceFactor)); - if (configuration.MappedMaxIndex is null) - throw new NullReferenceException(nameof(configuration.MappedMaxIndex)); - if (configuration.MappedMaxIndex.HasValue && configuration.LoadOrCreateThenSaveIndex.Value && !_IsEnvironment.DebuggerWasAttachedDuringConstructor) - throw new NullReferenceException(nameof(configuration.MappedMaxIndex)); - if (configuration.MaxItemsInDistanceCollection is null) - throw new NullReferenceException(nameof(configuration.MaxItemsInDistanceCollection)); - if (configuration.MixedYearRelativePaths is null) - throw new NullReferenceException(nameof(configuration.MixedYearRelativePaths)); - if (configuration.NumberOfJitters is null) - throw new NullReferenceException(nameof(configuration.NumberOfJitters)); - if (configuration.NumberOfTimesToUpsample is null) - throw new NullReferenceException(nameof(configuration.NumberOfTimesToUpsample)); - if (configuration.OutputQuality is null) - throw new NullReferenceException(nameof(configuration.OutputQuality)); - if (configuration.OutputResolutions is null) - throw new NullReferenceException(nameof(configuration.OutputResolutions)); - if (configuration.OverrideForFaceImages is null) - throw new NullReferenceException(nameof(configuration.OverrideForFaceImages)); - if (configuration.OverrideForFaceLandmarkImages is null) - throw new NullReferenceException(nameof(configuration.OverrideForFaceLandmarkImages)); - if (configuration.OverrideForResizeImages is null) - throw new NullReferenceException(nameof(configuration.OverrideForResizeImages)); - if (configuration.PaddingLoops is null) - throw new NullReferenceException(nameof(configuration.PaddingLoops)); - if (configuration.PropertiesChangedForDistance is null) - throw new NullReferenceException(nameof(configuration.PropertiesChangedForDistance)); - if (configuration.PropertiesChangedForFaces is null) - throw new NullReferenceException(nameof(configuration.PropertiesChangedForFaces)); - if (configuration.PropertiesChangedForIndex is null) - throw new NullReferenceException(nameof(configuration.PropertiesChangedForIndex)); - if (configuration.PropertiesChangedForMetadata is null) - throw new NullReferenceException(nameof(configuration.PropertiesChangedForMetadata)); - if (configuration.PropertiesChangedForResize is null) - throw new NullReferenceException(nameof(configuration.PropertiesChangedForResize)); - if (configuration.Reverse is null) - throw new NullReferenceException(nameof(configuration.Reverse)); - if (configuration.SaveFaceLandmarkForOutputResolutions is null) - throw new NullReferenceException(nameof(configuration.SaveFaceLandmarkForOutputResolutions)); - if (configuration.SaveFullYearOfRandomFiles is null) - throw new NullReferenceException(nameof(configuration.SaveFullYearOfRandomFiles)); - if (configuration.SaveResizedSubfiles is null) - throw new NullReferenceException(nameof(configuration.SaveResizedSubfiles)); - if (configuration.SkipSearch is null) - throw new NullReferenceException(nameof(configuration.SkipSearch)); - if (configuration.TestDistanceResults is null) - throw new NullReferenceException(nameof(configuration.TestDistanceResults)); - if (configuration.ValidResolutions is null) - throw new NullReferenceException(nameof(configuration.ValidResolutions)); - if (string.IsNullOrEmpty(configuration.ModelDirectory) || !Directory.Exists(configuration.ModelDirectory)) - throw new NullReferenceException(nameof(configuration.ModelDirectory)); if (string.IsNullOrEmpty(configuration.ModelName)) throw new NullReferenceException(nameof(configuration.ModelName)); if (string.IsNullOrEmpty(configuration.OutputExtension)) throw new NullReferenceException(nameof(configuration.OutputExtension)); if (string.IsNullOrEmpty(configuration.PredictorModelName)) throw new NullReferenceException(nameof(configuration.PredictorModelName)); - if (configuration.DistanceFactor.Value + configuration.LocationConfidenceFactor.Value != 10) - throw new NullReferenceException(nameof(configuration.DistanceFactor)); + if (string.IsNullOrEmpty(configuration.ModelDirectory) || !Directory.Exists(configuration.ModelDirectory)) + throw new NullReferenceException(nameof(configuration.ModelDirectory)); + if (configuration.MappedMaxIndex.HasValue && configuration.LoadOrCreateThenSaveIndex && !_IsEnvironment.DebuggerWasAttachedDuringConstructor) + throw new NullReferenceException(nameof(configuration.MappedMaxIndex)); } private void VerifyExtra(List args, Property.Models.Configuration propertyConfiguration, Models.Configuration configuration) @@ -309,10 +238,6 @@ public class DlibDotNet { if (item.ImageFileHolder is null) throw new NullReferenceException(nameof(item.ImageFileHolder)); - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); - if (_Configuration.SaveResizedSubfiles is null) - throw new NullReferenceException(nameof(_Configuration.SaveResizedSubfiles)); if (_Configuration?.PropertyConfiguration is null) throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); if (_Configuration.PropertyConfiguration.WriteBitmapDataBytes is null) @@ -343,24 +268,24 @@ public class DlibDotNet } } (int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(bResultsFullGroupDirectory, subFileTuples, parseExceptions, item); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) + if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection)); FileHolder resizedFileHolder = new(Path.Combine(_Resize.AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(item.ImageFileHolder.FullName))); item.SetResizedFileHolder(resizedFileHolder); - imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, property, item); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) + imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, item); + if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(C_Resize.GetResizeKeyValuePairs)); - if (_Configuration.SaveResizedSubfiles.Value) + if (_Configuration.SaveResizedSubfiles) { - _Resize.SaveResizedSubfile(outputResolution, cResultsFullGroupDirectory, subFileTuples, item, original, property, imageResizeKeyValuePairs); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) + _Resize.SaveResizedSubfile(outputResolution, cResultsFullGroupDirectory, subFileTuples, item, original, imageResizeKeyValuePairs); + if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(C_Resize.SaveResizedSubfile)); item.SetResizedFileHolder(FileHolder.Refresh(resizedFileHolder)); } else if (outputResolution == _Configuration.OutputResolutions[0] && false) { byte[] bytes = _Resize.GetResizedBytes(outputResolution, cResultsFullGroupDirectory, subFileTuples, item, property, imageResizeKeyValuePairs); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) + if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(C_Resize.GetResizedBytes)); string path = Path.Combine(resizedFileHolder.DirectoryName, resizedFileHolder.NameWithoutExtension); File.WriteAllBytes(path, bytes); @@ -374,15 +299,15 @@ public class DlibDotNet int outputResolutionHeight = outputResolutionCollection[1]; int outputResolutionOrientation = outputResolutionCollection[2]; faceCollection = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, item, property, resizedFileHolder, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) + if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.GetFaces)); _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, item, faceCollection); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) + if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.SaveFaces)); if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) { _FaceLandmarks.SaveFaceLandmarkImages(d2ResultsFullGroupDirectory, sourceDirectory, subFileTuples, parseExceptions, item, faceCollection); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) + if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D2_FaceLandmarks.SaveFaceLandmarkImages)); } } @@ -402,9 +327,7 @@ public class DlibDotNet int result = 0; if (_Log is null) throw new NullReferenceException(nameof(_Log)); - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(AppSettings.MaxDegreeOfParallelism)); - ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism.Value }; + ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; if (faceCollections.Count != filteredItems.Length || metadataCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || propertyCollection.Count != filteredItems.Length) { @@ -478,14 +401,8 @@ public class DlibDotNet private void WriteGroup(Property.Models.Configuration configuration, PropertyLogic propertyLogic, List propertyCollection, List>> metadataCollection, List> faceCollections, List> resizeKeyValuePairs, string sourceDirectory, string outputResolution, Item[] filteredItems) { - if (_Configuration.PropertiesChangedForMetadata is null) - throw new NullReferenceException(nameof(_Configuration.PropertiesChangedForMetadata)); if (configuration.PropertiesChangedForProperty is null) throw new NullReferenceException(nameof(configuration.PropertiesChangedForProperty)); - if (_Configuration.PropertiesChangedForResize is null) - throw new NullReferenceException(nameof(_Configuration.PropertiesChangedForResize)); - if (_Configuration.PropertiesChangedForFaces is null) - throw new NullReferenceException(nameof(_Configuration.PropertiesChangedForFaces)); Item item; string key; string json; @@ -560,19 +477,70 @@ public class DlibDotNet } } - private void FullDoWork(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string argZero, Dictionary> peopleCollection, PropertyLogic propertyLogic, List containers, bool isSilent) + private (string, string, string, string, string, string, string) GetResultsFullGroupDirectories(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution) + { + string aResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( + configuration, model, predictorModel, nameof(A_Property), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false); + string bResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( + configuration, model, predictorModel, nameof(B_Metadata), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false); + string cResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( + configuration, model, predictorModel, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false); + string dResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( + configuration, model, predictorModel, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); + string d2ResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( + configuration, model, predictorModel, nameof(D2_FaceLandmarks), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); + string eResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( + configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); + string zResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( + configuration, model, predictorModel, $"Z_{nameof(Item)}", outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); + return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory, zResultsFullGroupDirectory); + } + + private void SetAngleBracketCollections(Property.Models.Configuration configuration, PropertyLogic propertyLogic, string outputResolution, Container container, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory) + { + _Faces.AngleBracketCollection.Clear(); + _Resize.AngleBracketCollection.Clear(); + _Metadata.AngleBracketCollection.Clear(); + propertyLogic.AngleBracketCollection.Clear(); + propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, + 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, + 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, + container.SourceDirectory, + cResultsFullGroupDirectory, + contentDescription: "Resized image", + singletonDescription: "Resize dimensions for each resolution", + collectionDescription: string.Empty, + converted: true)); + if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) + _Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, + container.SourceDirectory, + dResultsFullGroupDirectory, + contentDescription: "n png file(s) for each face found", + singletonDescription: string.Empty, + collectionDescription: "For each image a json file with all faces found", + converted: true)); + } + + private void FullDoWork(bool isSilent, string argZero, Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, long ticks, Dictionary> peopleCollection, PropertyLogic propertyLogic, List containers) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); - if (_Configuration.SaveResizedSubfiles is null) - throw new NullReferenceException(nameof(_Configuration.SaveResizedSubfiles)); int[] ids; int distinctCount; int exceptionCount; Item[] filteredItems; - long ticks = DateTime.Now.Ticks; string aResultsFullGroupDirectory; string bResultsFullGroupDirectory; string cResultsFullGroupDirectory; @@ -592,20 +560,7 @@ public class DlibDotNet { _FileKeyValuePairs.Clear(); _FilePropertiesKeyValuePairs.Clear(); - aResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( - configuration, model, predictorModel, nameof(A_Property), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false); - bResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( - configuration, model, predictorModel, nameof(B_Metadata), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false); - cResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( - configuration, model, predictorModel, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false); - d2ResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( - configuration, model, predictorModel, nameof(D2_FaceLandmarks), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); - dResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( - configuration, model, predictorModel, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); - eResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( - configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); - zResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( - configuration, model, predictorModel, $"Z_{nameof(Item)}", outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); + (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory, zResultsFullGroupDirectory) = GetResultsFullGroupDirectories(configuration, model, predictorModel, outputResolution); foreach (Container container in containers) { if (!container.Items.Any()) @@ -621,39 +576,7 @@ public class DlibDotNet resizeKeyValuePairs.Clear(); sourceDirectoryChanges.Clear(); propertyFileHolderCollection.Clear(); - _Faces.AngleBracketCollection.Clear(); - _Resize.AngleBracketCollection.Clear(); - _Metadata.AngleBracketCollection.Clear(); - propertyLogic.AngleBracketCollection.Clear(); - propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, - 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, - 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, - container.SourceDirectory, - cResultsFullGroupDirectory, - contentDescription: "Resized image", - singletonDescription: "Resize dimensions for each resolution", - collectionDescription: string.Empty, - converted: true)); - if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) - _Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, - container.SourceDirectory, - dResultsFullGroupDirectory, - contentDescription: "n png file(s) for each face found", - singletonDescription: string.Empty, - collectionDescription: "For each image a json file with all faces found", - converted: true)); + SetAngleBracketCollections(configuration, propertyLogic, outputResolution, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory); exceptionCount = FullParallelWork(ticks, propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, faceCollections, containers.Count, container, filteredItems); #pragma warning disable ids = (from l in filteredItems where l.Property?.Id is not null select l.Property.Id.Value).ToArray(); @@ -665,35 +588,14 @@ public class DlibDotNet throw new Exception("Counts don't match!"); if (exceptionCount != 0) _Exceptions.Add(container.SourceDirectory); + for (int i = 0; i < faceCollections.Count; i++) + filteredItems[i].Faces.AddRange(from l in faceCollections[i] select l); if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0) WriteGroup(configuration, propertyLogic, propertyCollection, metadataCollection, faceCollections, resizeKeyValuePairs, container.SourceDirectory, outputResolution, filteredItems); if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0 && outputResolution == _Configuration.OutputResolutions[0]) propertyLogic.AddToPropertyLogicAllCollection(filteredItems); - if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0 && propertyLogic.NamedFaceInfoDeterministicHashCodeIds.Any()) - { - if (outputResolution == _Configuration.OutputResolutions[0] || _Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) - { - if (isSilent && container.SourceDirectory.EndsWith("Bohdi Ray 2016")) // 7#.1 - break; - // if (isSilent && container.SourceDirectory.EndsWith("Halloween 2013")) // 12#.1 - // break; - // if (isSilent && container.SourceDirectory.EndsWith("zzz =2014.4 Winter Tracy Pictures")) // 30#.2 - // break; - // if (isSilent && container.SourceDirectory.EndsWith("=2009.0 Winter Logan Michael")) //34#.2 - // break; - // if (isSilent && container.SourceDirectory.EndsWith("Animal Kingdom")) //35#.3 - // break; - // if (isSilent && container.SourceDirectory.EndsWith("Texas 2015")) //46#.4 - // break; - for (int i = 0; i < faceCollections.Count; i++) - filteredItems[i].Faces.AddRange(from l in faceCollections[i] select l); - Item.AddToNamed(propertyLogic, filteredItems); - if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) - D_Face.SaveShortcuts(_Configuration.JuliePhares, dResultsFullGroupDirectory, ticks, peopleCollection, propertyLogic, filteredItems); - } - } if (exceptionCount == 0 && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) - _Distance.LoadOrCreateThenSaveDistanceResultsForOutputResolutions(configuration, eResultsFullGroupDirectory, container.SourceDirectory, outputResolution, sourceDirectoryChanges, filteredItems, faceCollections); + _Distance.LoadOrCreateThenSaveDistanceResults(configuration, eResultsFullGroupDirectory, container.SourceDirectory, outputResolution, sourceDirectoryChanges, filteredItems); if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any()) { for (int y = 0; y < int.MaxValue; y++) @@ -704,7 +606,54 @@ public class DlibDotNet } _Log.Information(". . ."); } + if (isSilent && container.SourceDirectory.EndsWith("Bohdi Ray 2016")) // 7#.1 + break; + // if (isSilent && container.SourceDirectory.EndsWith("Halloween 2013")) // 12#.1 + // break; + // if (isSilent && container.SourceDirectory.EndsWith("zzz =2014.4 Winter Tracy Pictures")) // 30#.2 + // break; + // if (isSilent && container.SourceDirectory.EndsWith("=2009.0 Winter Logan Michael")) //34#.2 + // break; + // if (isSilent && container.SourceDirectory.EndsWith("Animal Kingdom")) //35#.3 + // break; + // if (isSilent && container.SourceDirectory.EndsWith("Texas 2015")) //46#.4 + // break; } + } + } + + private PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel) + { + PropertyLogic result; + if (_Configuration?.PropertyConfiguration is null) + throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); + result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, reverse, model, predictorModel); + return result; + } + + private void Search(Property.Models.Configuration configuration, bool reverse, Model? model, PredictorModel? predictorModel, string argZero, Person[] people, bool isSilent) + { + if (_Log is null) + throw new NullReferenceException(nameof(_Log)); + List containers; + long ticks = DateTime.Now.Ticks; + string aResultsFullGroupDirectory; + string bResultsFullGroupDirectory; + string cResultsFullGroupDirectory; + string dResultsFullGroupDirectory; + string eResultsFullGroupDirectory; + string zResultsFullGroupDirectory; + string d2ResultsFullGroupDirectory; + Dictionary> peopleCollection = A2_People.Convert(people); + PropertyLogic propertyLogic = GetPropertyLogic(reverse, model, predictorModel); + if (string.IsNullOrEmpty(configuration.RootDirectory)) + containers = Property.Models.Stateless.A_Property.Get(configuration, propertyLogic); + else + containers = Property.Models.Stateless.Container.GetContainers(configuration, propertyLogic); + FullDoWork(isSilent, argZero, configuration, model, predictorModel, ticks, peopleCollection, propertyLogic, containers); + foreach (string outputResolution in _Configuration.OutputResolutions) + { + (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory, zResultsFullGroupDirectory) = GetResultsFullGroupDirectories(configuration, model, predictorModel, outputResolution); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(aResultsFullGroupDirectory, "{}")); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(bResultsFullGroupDirectory, "{}")); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(cResultsFullGroupDirectory, "{}")); @@ -716,10 +665,18 @@ public class DlibDotNet _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]")); if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(d2ResultsFullGroupDirectory, "[]")); - if (_ArgZeroIsConfigurationRootDirectory && outputResolution == _Configuration.OutputResolutions[0]) + if (_ArgZeroIsConfigurationRootDirectory && _Exceptions.Count == 0 && outputResolution == _Configuration.OutputResolutions[0] && (propertyLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs.Any() || propertyLogic.NamedDeterministicHashCodeKeyValuePairs.Any())) { + if (!string.IsNullOrEmpty(propertyLogic.DeterministicHashCodeRootDirectory) && !propertyLogic.IncorrectDeterministicHashCodeKeyValuePairs.Any()) + propertyLogic.UpdateKeyValuePairs(containers); + foreach (Container container in containers) + { + Item.AddToNamed(propertyLogic, container.Items); + if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) + D_Face.SaveShortcuts(_Configuration.JuliePhares, dResultsFullGroupDirectory, ticks, peopleCollection, propertyLogic, container.Items); + } propertyLogic.SaveAllCollection(); - if (_Configuration.SaveResizedSubfiles.Value && propertyLogic.NamedFaceInfoDeterministicHashCodeIds.Any()) + if (_Configuration.SaveResizedSubfiles) { string dFacesContentDirectory; string eDistanceContentDirectory; @@ -730,57 +687,31 @@ public class DlibDotNet zPropertyHolderSingletonDirectory = Path.Combine(zResultsFullGroupDirectory, "{}"); eDistanceCollectionDirectory = Path.Combine(eResultsFullGroupDirectory, $"[{ticks}]"); List<(DateTime, bool?, PersonBirthday, FaceRecognitionDotNet.FaceEncoding[])> collection; - collection = E_Distance.ParallelWork(_AppSettings.MaxDegreeOfParallelism.Value, argZero, containers); - _ = LogDelta(ticks, nameof(E_Distance.ParallelWork)); + collection = E_Distance.ParallelWork(_AppSettings.MaxDegreeOfParallelism, argZero, propertyLogic, containers); + _ = LogDeltaInMinutes(ticks, nameof(E_Distance.ParallelWork)); E_Distance.SavePropertyHolders(argZero, containers, zPropertyHolderSingletonDirectory); - _ = LogDelta(ticks, nameof(E_Distance.SavePropertyHolders)); + _ = LogDeltaInMinutes(ticks, nameof(E_Distance.SavePropertyHolders)); E_Distance.SaveThreeSigmaFaceEncodings(collection, peopleCollection, eDistanceCollectionDirectory); - _ = LogDelta(ticks, nameof(E_Distance.SaveThreeSigmaFaceEncodings)); - E_Distance.SaveClosest(argZero, containers, peopleCollection, propertyLogic, eDistanceContentDirectory, dFacesContentDirectory); - _ = LogDelta(ticks, nameof(E_Distance.SaveClosest)); + _ = LogDeltaInMinutes(ticks, nameof(E_Distance.SaveThreeSigmaFaceEncodings)); + E_Distance.SaveClosest(argZero, containers, peopleCollection, eDistanceContentDirectory, dFacesContentDirectory); + _ = LogDeltaInMinutes(ticks, nameof(E_Distance.SaveClosest)); } if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any()) break; - if (_Exceptions.Count == 0) - { - if (_FileKeyValuePairs.Any()) - _Random.Random(configuration, _Configuration.OutputResolutions[0], _FileKeyValuePairs); - if (_IsEnvironment.Development) - continue; - G2_Identify identify = new(_Configuration); - List identifiedCollection = identify.GetIdentifiedCollection(configuration, _IsEnvironment, _People); - _People.WriteAllText(configuration, _Configuration.OutputResolutions[0], identifiedCollection); - identify.WriteAllText(configuration, _Configuration.OutputResolutions[0], identifiedCollection); - if (_Configuration.LoadOrCreateThenSaveIndex.HasValue && _Configuration.LoadOrCreateThenSaveIndex.Value && _FilePropertiesKeyValuePairs.Any()) - _Index.SetIndex(configuration, model, predictorModel, _Configuration.OutputResolutions[0], _FilePropertiesKeyValuePairs); - } + if (_FileKeyValuePairs.Any()) + _Random.Random(configuration, _Configuration.OutputResolutions[0], _FileKeyValuePairs); + if (_IsEnvironment.Development) + continue; + G2_Identify identify = new(_Configuration); + List identifiedCollection = identify.GetIdentifiedCollection(configuration, _IsEnvironment, _People); + _People.WriteAllText(configuration, _Configuration.OutputResolutions[0], identifiedCollection); + identify.WriteAllText(configuration, _Configuration.OutputResolutions[0], identifiedCollection); + if (_Configuration.LoadOrCreateThenSaveIndex && _FilePropertiesKeyValuePairs.Any()) + _Index.SetIndex(configuration, model, predictorModel, _Configuration.OutputResolutions[0], _FilePropertiesKeyValuePairs); } } } - private PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel) - { - PropertyLogic result; - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); - if (_Configuration?.PropertyConfiguration is null) - throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, reverse, model, predictorModel); - return result; - } - - private void Search(Property.Models.Configuration configuration, bool reverse, Model? model, PredictorModel? predictorModel, string argZero, Person[] people, bool isSilent) - { - List containers; - Dictionary> peopleCollection = A2_People.Convert(people); - PropertyLogic propertyLogic = GetPropertyLogic(reverse, model, predictorModel); - if (string.IsNullOrEmpty(configuration.RootDirectory)) - containers = Property.Models.Stateless.A_Property.Get(configuration, propertyLogic); - else - containers = Property.Models.Stateless.Container.GetContainers(configuration, propertyLogic); - FullDoWork(configuration, model, predictorModel, argZero, peopleCollection, propertyLogic, containers, isSilent); - } - internal void RenameQueue(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel) => _Rename.RenameQueue(configuration, model, predictorModel); } \ No newline at end of file diff --git a/Instance/Models/AppSettings.cs b/Instance/Models/AppSettings.cs index dfb43d7..9962a71 100644 --- a/Instance/Models/AppSettings.cs +++ b/Instance/Models/AppSettings.cs @@ -6,24 +6,16 @@ namespace View_by_Distance.Instance.Models; public class AppSettings { - protected string _Company; - protected string _WorkingDirectoryName; - protected int? _MaxDegreeOfParallelism; - public string Company => _Company; - public string WorkingDirectoryName => _WorkingDirectoryName; - public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism; - - // public AppSettings() - // { - - // } + public string Company { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string WorkingDirectoryName { init; get; } [JsonConstructor] - public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism) + public AppSettings(string company, int maxDegreeOfParallelism, string workingDirectoryName) { - _Company = company; - _WorkingDirectoryName = workingDirectoryName; - _MaxDegreeOfParallelism = maxDegreeOfParallelism; + Company = company; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + WorkingDirectoryName = workingDirectoryName; } public override string ToString() diff --git a/Instance/Models/Binder/AppSettings.cs b/Instance/Models/Binder/AppSettings.cs index f10b9e7..e5909f6 100644 --- a/Instance/Models/Binder/AppSettings.cs +++ b/Instance/Models/Binder/AppSettings.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Configuration; using System.Text.Json; namespace View_by_Distance.Instance.Models.Binder; @@ -6,16 +6,13 @@ namespace View_by_Distance.Instance.Models.Binder; public class AppSettings { - [Display(Name = "Company"), Required] public string Company { get; set; } - [Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; } - [Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; } +#nullable disable - public AppSettings() - { - Company = string.Empty; - WorkingDirectoryName = string.Empty; - MaxDegreeOfParallelism = -1; - } + public string Company { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string WorkingDirectoryName { get; set; } + +#nullable restore public override string ToString() { @@ -23,4 +20,25 @@ public class AppSettings return result; } + private static Models.AppSettings Get(AppSettings appSettings) + { + Models.AppSettings result; + if (appSettings.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + result = new( + appSettings.Company, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + } \ No newline at end of file diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index cfa51f6..7bfe922 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -1,3 +1,5 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; using System.ComponentModel.DataAnnotations; using System.Text.Json; @@ -6,9 +8,12 @@ namespace View_by_Distance.Instance.Models.Binder; public class Configuration { +#nullable disable + [Display(Name = "Check Json For Distance Results"), Required] public bool? CheckJsonForDistanceResults { get; set; } [Display(Name = "CrossDirectory Max Items In Distance Collection"), Required] public int? CrossDirectoryMaxItemsInDistanceCollection { get; set; } [Display(Name = "Distance Factor"), Required] public int? DistanceFactor { get; set; } + [Display(Name = "Force Face Last Write Time to Creation Time"), Required] public bool? ForceFaceLastWriteTimeToCreationTime { get; set; } [Display(Name = "Force Metadata Last Write Time to Creation Time"), Required] public bool? ForceMetadataLastWriteTimeToCreationTime { get; set; } [Display(Name = "Force Resize Last Write Time to Creation Time"), Required] public bool? ForceResizeLastWriteTimeToCreationTime { get; set; } [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; } @@ -39,7 +44,7 @@ public class Configuration [Display(Name = "Properties Changed For Index"), Required] public bool? PropertiesChangedForIndex { get; set; } [Display(Name = "Properties Changed For Metadata"), Required] public bool? PropertiesChangedForMetadata { get; set; } [Display(Name = "Properties Changed For Resize"), Required] public bool? PropertiesChangedForResize { get; set; } - [Display(Name = "Property Configuration"), Required] public Property.Models.Configuration? PropertyConfiguration { get; set; } + [Display(Name = "Property Configuration"), Required] public Property.Models.Configuration PropertyConfiguration { get; set; } [Display(Name = "Reverse"), Required] public bool? Reverse { get; set; } [Display(Name = "Save Face Landmark For Output Resolutions"), Required] public string[] SaveFaceLandmarkForOutputResolutions { get; set; } [Display(Name = "Save Full Year Of Random Files"), Required] public bool? SaveFullYearOfRandomFiles { get; set; } @@ -49,50 +54,7 @@ public class Configuration [Display(Name = "Test Distance Results"), Required] public bool? TestDistanceResults { get; set; } [Display(Name = "Valid Resolutions"), Required] public string[] ValidResolutions { get; set; } - public Configuration() - { - CheckJsonForDistanceResults = null; - CrossDirectoryMaxItemsInDistanceCollection = null; - DistanceFactor = null; - ForceMetadataLastWriteTimeToCreationTime = null; - ForceResizeLastWriteTimeToCreationTime = null; - IgnoreExtensions = Array.Empty(); - IgnoreRelativePaths = Array.Empty(); - JuliePhares = Array.Empty(); - LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = Array.Empty(); - LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty(); - LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = Array.Empty(); - LoadOrCreateThenSaveIndex = null; - LocationConfidenceFactor = null; - MappedMaxIndex = null; - MaxItemsInDistanceCollection = null; - MixedYearRelativePaths = Array.Empty(); - ModelDirectory = string.Empty; - ModelName = string.Empty; - NumberOfJitters = null; - NumberOfTimesToUpsample = null; - OutputExtension = string.Empty; - OutputQuality = null; - OutputResolutions = Array.Empty(); - OverrideForFaceImages = null; - OverrideForFaceLandmarkImages = null; - OverrideForResizeImages = null; - PaddingLoops = null; - PredictorModelName = string.Empty; - PropertiesChangedForDistance = null; - PropertiesChangedForFaces = null; - PropertiesChangedForIndex = null; - PropertiesChangedForMetadata = null; - PropertiesChangedForResize = null; - Reverse = null; - SaveFaceLandmarkForOutputResolutions = Array.Empty(); - SaveFullYearOfRandomFiles = null; - SaveResizedSubfiles = null; - SaveShortcutsForOutputResolutions = Array.Empty(); - SkipSearch = null; - TestDistanceResults = null; - ValidResolutions = Array.Empty(); - } +#nullable restore public override string ToString() { @@ -100,4 +62,146 @@ public class Configuration return result; } + private static Models.Configuration Get(Configuration configuration) + { + Models.Configuration result; + if (configuration.CheckJsonForDistanceResults is null) + throw new NullReferenceException(nameof(configuration.CheckJsonForDistanceResults)); + if (configuration.CrossDirectoryMaxItemsInDistanceCollection is null) + throw new NullReferenceException(nameof(configuration.CrossDirectoryMaxItemsInDistanceCollection)); + if (configuration.DistanceFactor is null) + throw new NullReferenceException(nameof(configuration.DistanceFactor)); + if (configuration.ForceFaceLastWriteTimeToCreationTime is null) + throw new NullReferenceException(nameof(configuration.ForceFaceLastWriteTimeToCreationTime)); + if (configuration.ForceMetadataLastWriteTimeToCreationTime is null) + throw new NullReferenceException(nameof(configuration.ForceMetadataLastWriteTimeToCreationTime)); + if (configuration.ForceResizeLastWriteTimeToCreationTime is null) + throw new NullReferenceException(nameof(configuration.ForceResizeLastWriteTimeToCreationTime)); + if (configuration.IgnoreExtensions is null) + throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); + if (configuration.IgnoreRelativePaths is null) + throw new NullReferenceException(nameof(configuration.IgnoreRelativePaths)); + if (configuration.LoadOrCreateThenSaveIndex is null) + throw new NullReferenceException(nameof(configuration.LoadOrCreateThenSaveIndex)); + if (configuration.LocationConfidenceFactor is null) + throw new NullReferenceException(nameof(configuration.LocationConfidenceFactor)); + if (configuration.MaxItemsInDistanceCollection is null) + throw new NullReferenceException(nameof(configuration.MaxItemsInDistanceCollection)); + if (configuration.MixedYearRelativePaths is null) + throw new NullReferenceException(nameof(configuration.MixedYearRelativePaths)); + if (configuration.NumberOfJitters is null) + throw new NullReferenceException(nameof(configuration.NumberOfJitters)); + if (configuration.NumberOfTimesToUpsample is null) + throw new NullReferenceException(nameof(configuration.NumberOfTimesToUpsample)); + if (configuration.OutputQuality is null) + throw new NullReferenceException(nameof(configuration.OutputQuality)); + if (configuration.OutputResolutions is null) + throw new NullReferenceException(nameof(configuration.OutputResolutions)); + if (configuration.OverrideForFaceImages is null) + throw new NullReferenceException(nameof(configuration.OverrideForFaceImages)); + if (configuration.OverrideForFaceLandmarkImages is null) + throw new NullReferenceException(nameof(configuration.OverrideForFaceLandmarkImages)); + if (configuration.OverrideForResizeImages is null) + throw new NullReferenceException(nameof(configuration.OverrideForResizeImages)); + if (configuration.PaddingLoops is null) + throw new NullReferenceException(nameof(configuration.PaddingLoops)); + if (configuration.PropertiesChangedForDistance is null) + throw new NullReferenceException(nameof(configuration.PropertiesChangedForDistance)); + if (configuration.PropertiesChangedForFaces is null) + throw new NullReferenceException(nameof(configuration.PropertiesChangedForFaces)); + if (configuration.PropertiesChangedForIndex is null) + throw new NullReferenceException(nameof(configuration.PropertiesChangedForIndex)); + if (configuration.PropertiesChangedForMetadata is null) + throw new NullReferenceException(nameof(configuration.PropertiesChangedForMetadata)); + if (configuration.PropertiesChangedForResize is null) + throw new NullReferenceException(nameof(configuration.PropertiesChangedForResize)); + if (configuration.Reverse is null) + throw new NullReferenceException(nameof(configuration.Reverse)); + if (configuration.SaveFaceLandmarkForOutputResolutions is null) + throw new NullReferenceException(nameof(configuration.SaveFaceLandmarkForOutputResolutions)); + if (configuration.SaveFullYearOfRandomFiles is null) + throw new NullReferenceException(nameof(configuration.SaveFullYearOfRandomFiles)); + if (configuration.SaveResizedSubfiles is null) + throw new NullReferenceException(nameof(configuration.SaveResizedSubfiles)); + if (configuration.SkipSearch is null) + throw new NullReferenceException(nameof(configuration.SkipSearch)); + if (configuration.TestDistanceResults is null) + throw new NullReferenceException(nameof(configuration.TestDistanceResults)); + if (configuration.ValidResolutions is null) + throw new NullReferenceException(nameof(configuration.ValidResolutions)); + if (configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions is null) + configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = Array.Empty(); + if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) + configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty(); + if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) + configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = Array.Empty(); + if (configuration.SaveFaceLandmarkForOutputResolutions is null) + configuration.SaveFaceLandmarkForOutputResolutions = Array.Empty(); + if (configuration.SaveShortcutsForOutputResolutions is null) + configuration.SaveShortcutsForOutputResolutions = Array.Empty(); + result = new(configuration.PropertyConfiguration, + configuration.CheckJsonForDistanceResults.Value, + configuration.CrossDirectoryMaxItemsInDistanceCollection.Value, + configuration.DistanceFactor.Value, + configuration.ForceFaceLastWriteTimeToCreationTime.Value, + configuration.ForceMetadataLastWriteTimeToCreationTime.Value, + configuration.ForceResizeLastWriteTimeToCreationTime.Value, + configuration.IgnoreExtensions, + configuration.IgnoreRelativePaths, + configuration.JuliePhares, + configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, + configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, + configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, + configuration.LoadOrCreateThenSaveIndex.Value, + configuration.LocationConfidenceFactor.Value, + configuration.MappedMaxIndex, + configuration.MaxItemsInDistanceCollection.Value, + configuration.MixedYearRelativePaths, + configuration.ModelDirectory, + configuration.ModelName, + configuration.NumberOfJitters.Value, + configuration.NumberOfTimesToUpsample.Value, + configuration.OutputExtension, + configuration.OutputQuality.Value, + configuration.OutputResolutions, + configuration.OverrideForFaceImages.Value, + configuration.OverrideForFaceLandmarkImages.Value, + configuration.OverrideForResizeImages.Value, + configuration.PaddingLoops.Value, + configuration.PredictorModelName, + configuration.PropertiesChangedForDistance.Value, + configuration.PropertiesChangedForFaces.Value, + configuration.PropertiesChangedForIndex.Value, + configuration.PropertiesChangedForMetadata.Value, + configuration.PropertiesChangedForResize.Value, + configuration.Reverse.Value, + configuration.SaveFaceLandmarkForOutputResolutions, + configuration.SaveFullYearOfRandomFiles.Value, + configuration.SaveResizedSubfiles.Value, + configuration.SaveShortcutsForOutputResolutions, + configuration.SkipSearch.Value, + configuration.TestDistanceResults.Value, + configuration.ValidResolutions); + return result; + } + + public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, Property.Models.Configuration propertyConfiguration) + { + Models.Configuration result; + Configuration configuration; + if (isEnvironment is null) + configuration = configurationRoot.Get(); + else + { + string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment); + string section = string.Concat(environmentName, ":", nameof(Configuration)); + IConfigurationSection configurationSection = configurationRoot.GetSection(section); + configuration = configurationSection.Get(); + } + result = Get(configuration); + result.Set(propertyConfiguration); + result.Update(); + return result; + } + } \ No newline at end of file diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index 91b0c8c..a3717c0 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -6,136 +6,98 @@ namespace View_by_Distance.Instance.Models; public class Configuration { - protected readonly bool? _CheckJsonForDistanceResults; - protected readonly int? _CrossDirectoryMaxItemsInDistanceCollection; - protected readonly int? _DistanceFactor; - protected readonly bool? _ForceMetadataLastWriteTimeToCreationTime; - protected readonly bool? _ForceResizeLastWriteTimeToCreationTime; - protected readonly string[] _IgnoreExtensions; - protected readonly string[] _IgnoreRelativePaths; - protected readonly string[] _JuliePhares; - protected readonly string[] _LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions; - protected readonly string[] _LoadOrCreateThenSaveDistanceResultsForOutputResolutions; - protected readonly string[] _LoadOrCreateThenSaveImageFacesResultsForOutputResolutions; - protected readonly bool? _LoadOrCreateThenSaveIndex; - protected readonly int? _LocationConfidenceFactor; - protected readonly int? _MappedMaxIndex; - protected readonly int? _MaxItemsInDistanceCollection; - protected readonly string[] _MixedYearRelativePaths; - protected readonly string _ModelDirectory; - protected readonly string _ModelName; - protected readonly int? _NumberOfJitters; - protected readonly int? _NumberOfTimesToUpsample; - protected readonly string _OutputExtension; - protected readonly int? _OutputQuality; - protected readonly string[] _OutputResolutions; - protected readonly bool? _OverrideForFaceImages; - protected readonly bool? _OverrideForFaceLandmarkImages; - protected readonly bool? _OverrideForResizeImages; - protected readonly int? _PaddingLoops; - protected readonly string _PredictorModelName; - protected readonly bool? _PropertiesChangedForDistance; - protected readonly bool? _PropertiesChangedForFaces; - protected readonly bool? _PropertiesChangedForIndex; - protected readonly bool? _PropertiesChangedForMetadata; - protected readonly bool? _PropertiesChangedForResize; - protected Property.Models.Configuration? _PropertyConfiguration; - protected readonly bool? _Reverse; - protected readonly string[] _SaveFaceLandmarkForOutputResolutions; - protected readonly bool? _SaveFullYearOfRandomFiles; - protected readonly bool? _SaveResizedSubfiles; - protected readonly string[] _SaveShortcutsForOutputResolutions; - protected readonly bool? _SkipSearch; - protected readonly bool? _TestDistanceResults; - protected readonly string[] _ValidResolutions; - public bool? CheckJsonForDistanceResults => _CheckJsonForDistanceResults; - public int? CrossDirectoryMaxItemsInDistanceCollection => _CrossDirectoryMaxItemsInDistanceCollection; - public int? DistanceFactor => _DistanceFactor; - public bool? ForceMetadataLastWriteTimeToCreationTime => _ForceMetadataLastWriteTimeToCreationTime; - public bool? ForceResizeLastWriteTimeToCreationTime => _ForceResizeLastWriteTimeToCreationTime; - public string[] IgnoreExtensions => _IgnoreExtensions; - public string[] IgnoreRelativePaths => _IgnoreRelativePaths; - public string[] JuliePhares => _JuliePhares; - public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions => _LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions; - public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions => _LoadOrCreateThenSaveDistanceResultsForOutputResolutions; - public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions => _LoadOrCreateThenSaveImageFacesResultsForOutputResolutions; - public bool? LoadOrCreateThenSaveIndex => _LoadOrCreateThenSaveIndex; - public int? LocationConfidenceFactor => _LocationConfidenceFactor; - public int? MappedMaxIndex => _MappedMaxIndex; - public int? MaxItemsInDistanceCollection => _MaxItemsInDistanceCollection; - public string[] MixedYearRelativePaths => _MixedYearRelativePaths; - public string ModelDirectory => _ModelDirectory; - public string ModelName => _ModelName; - public int? NumberOfJitters => _NumberOfJitters; - public int? NumberOfTimesToUpsample => _NumberOfTimesToUpsample; - public string OutputExtension => _OutputExtension; - public int? OutputQuality => _OutputQuality; - public string[] OutputResolutions => _OutputResolutions; - public bool? OverrideForFaceImages => _OverrideForFaceImages; - public bool? OverrideForFaceLandmarkImages => _OverrideForFaceLandmarkImages; - public bool? OverrideForResizeImages => _OverrideForResizeImages; - public int? PaddingLoops => _PaddingLoops; - public string PredictorModelName => _PredictorModelName; - public bool? PropertiesChangedForDistance => _PropertiesChangedForDistance; - public bool? PropertiesChangedForFaces => _PropertiesChangedForFaces; - public bool? PropertiesChangedForIndex => _PropertiesChangedForIndex; - public bool? PropertiesChangedForMetadata => _PropertiesChangedForMetadata; - public bool? PropertiesChangedForResize => _PropertiesChangedForResize; - public Property.Models.Configuration? PropertyConfiguration => _PropertyConfiguration; - public bool? Reverse => _Reverse; - public string[] SaveFaceLandmarkForOutputResolutions => _SaveFaceLandmarkForOutputResolutions; - public bool? SaveFullYearOfRandomFiles => _SaveFullYearOfRandomFiles; - public bool? SaveResizedSubfiles => _SaveResizedSubfiles; - public string[] SaveShortcutsForOutputResolutions => _SaveShortcutsForOutputResolutions; - public bool? SkipSearch => _SkipSearch; - public bool? TestDistanceResults => _TestDistanceResults; - public string[] ValidResolutions => _ValidResolutions; + protected Property.Models.Configuration _PropertyConfiguration; + public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration; + + public bool CheckJsonForDistanceResults { init; get; } + public int CrossDirectoryMaxItemsInDistanceCollection { init; get; } + public int DistanceFactor { init; get; } + public bool ForceFaceLastWriteTimeToCreationTime { init; get; } + public bool ForceMetadataLastWriteTimeToCreationTime { init; get; } + public bool ForceResizeLastWriteTimeToCreationTime { init; get; } + public string[] IgnoreExtensions { init; get; } + public string[] IgnoreRelativePaths { init; get; } + public string[] JuliePhares { init; get; } + public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { init; get; } + public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } + public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } + public bool LoadOrCreateThenSaveIndex { init; get; } + public int LocationConfidenceFactor { init; get; } + public int? MappedMaxIndex { init; get; } + public int MaxItemsInDistanceCollection { init; get; } + public string[] MixedYearRelativePaths { init; get; } + public string ModelDirectory { init; get; } + public string ModelName { init; get; } + public int NumberOfJitters { init; get; } + public int NumberOfTimesToUpsample { init; get; } + public string OutputExtension { init; get; } + public int OutputQuality { init; get; } + public string[] OutputResolutions { init; get; } + public bool OverrideForFaceImages { init; get; } + public bool OverrideForFaceLandmarkImages { init; get; } + public bool OverrideForResizeImages { init; get; } + public int PaddingLoops { init; get; } + public string PredictorModelName { init; get; } + public bool PropertiesChangedForDistance { init; get; } + public bool PropertiesChangedForFaces { init; get; } + public bool PropertiesChangedForIndex { init; get; } + public bool PropertiesChangedForMetadata { init; get; } + public bool PropertiesChangedForResize { init; get; } + public bool Reverse { init; get; } + public string[] SaveFaceLandmarkForOutputResolutions { init; get; } + public bool SaveFullYearOfRandomFiles { init; get; } + public bool SaveResizedSubfiles { init; get; } + public string[] SaveShortcutsForOutputResolutions { init; get; } + public bool SkipSearch { init; get; } + public bool TestDistanceResults { init; get; } + public string[] ValidResolutions { init; get; } [JsonConstructor] - public Configuration(bool? checkJsonForDistanceResults, int? crossDirectoryMaxItemsInDistanceCollection, int? distanceFactor, bool? forceMetadataLastWriteTimeToCreationTime, bool? forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool? loadOrCreateThenSaveIndex, int? locationConfidenceFactor, int? mappedMaxIndex, int? maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int? numberOfJitters, int? numberOfTimesToUpsample, string outputExtension, int? outputQuality, string[] outputResolutions, bool? overrideForFaceImages, bool? overrideForFaceLandmarkImages, bool? overrideForResizeImages, int? paddingLoops, string predictorModelName, bool? propertiesChangedForDistance, bool? propertiesChangedForFaces, bool? propertiesChangedForIndex, bool? propertiesChangedForMetadata, bool? propertiesChangedForResize, Property.Models.Configuration? propertyConfiguration, bool? reverse, string[] saveFaceLandmarkForOutputResolutions, bool? saveFullYearOfRandomFiles, bool? saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool? skipSearch, bool? testDistanceResults, string[] validResolutions) + public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions) { - _CheckJsonForDistanceResults = checkJsonForDistanceResults; - _CrossDirectoryMaxItemsInDistanceCollection = crossDirectoryMaxItemsInDistanceCollection; - _DistanceFactor = distanceFactor; - _ForceMetadataLastWriteTimeToCreationTime = forceMetadataLastWriteTimeToCreationTime; - _ForceResizeLastWriteTimeToCreationTime = forceResizeLastWriteTimeToCreationTime; - _IgnoreExtensions = ignoreExtensions; - _IgnoreRelativePaths = ignoreRelativePaths; - _JuliePhares = juliePhares; - _LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions; - _LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; - _LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; - _LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex; - _LocationConfidenceFactor = locationConfidenceFactor; - _MappedMaxIndex = mappedMaxIndex; - _MaxItemsInDistanceCollection = maxItemsInDistanceCollection; - _MixedYearRelativePaths = mixedYearRelativePaths; - _ModelDirectory = modelDirectory; - _ModelName = modelName; - _NumberOfJitters = numberOfJitters; - _NumberOfTimesToUpsample = numberOfTimesToUpsample; - _OutputExtension = outputExtension; - _OutputQuality = outputQuality; - _OutputResolutions = outputResolutions; - _OverrideForFaceImages = overrideForFaceImages; - _OverrideForFaceLandmarkImages = overrideForFaceLandmarkImages; - _OverrideForResizeImages = overrideForResizeImages; - _PaddingLoops = paddingLoops; - _PredictorModelName = predictorModelName; - _PropertiesChangedForDistance = propertiesChangedForDistance; - _PropertiesChangedForFaces = propertiesChangedForFaces; - _PropertiesChangedForIndex = propertiesChangedForIndex; - _PropertiesChangedForMetadata = propertiesChangedForMetadata; - _PropertiesChangedForResize = propertiesChangedForResize; _PropertyConfiguration = propertyConfiguration; - _Reverse = reverse; - _SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions; - _SaveFullYearOfRandomFiles = saveFullYearOfRandomFiles; - _SaveResizedSubfiles = saveResizedSubfiles; - _SaveShortcutsForOutputResolutions = saveShortcutsForOutputResolutions; - _SkipSearch = skipSearch; - _TestDistanceResults = testDistanceResults; - _ValidResolutions = validResolutions; + CheckJsonForDistanceResults = checkJsonForDistanceResults; + CrossDirectoryMaxItemsInDistanceCollection = crossDirectoryMaxItemsInDistanceCollection; + DistanceFactor = distanceFactor; + ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime; + ForceMetadataLastWriteTimeToCreationTime = forceMetadataLastWriteTimeToCreationTime; + ForceResizeLastWriteTimeToCreationTime = forceResizeLastWriteTimeToCreationTime; + IgnoreExtensions = ignoreExtensions; + IgnoreRelativePaths = ignoreRelativePaths; + JuliePhares = juliePhares; + LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions; + LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; + LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; + LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex; + LocationConfidenceFactor = locationConfidenceFactor; + MappedMaxIndex = mappedMaxIndex; + MaxItemsInDistanceCollection = maxItemsInDistanceCollection; + MixedYearRelativePaths = mixedYearRelativePaths; + ModelDirectory = modelDirectory; + ModelName = modelName; + NumberOfJitters = numberOfJitters; + NumberOfTimesToUpsample = numberOfTimesToUpsample; + OutputExtension = outputExtension; + OutputQuality = outputQuality; + OutputResolutions = outputResolutions; + OverrideForFaceImages = overrideForFaceImages; + OverrideForFaceLandmarkImages = overrideForFaceLandmarkImages; + OverrideForResizeImages = overrideForResizeImages; + PaddingLoops = paddingLoops; + PredictorModelName = predictorModelName; + PropertiesChangedForDistance = propertiesChangedForDistance; + PropertiesChangedForFaces = propertiesChangedForFaces; + PropertiesChangedForIndex = propertiesChangedForIndex; + PropertiesChangedForMetadata = propertiesChangedForMetadata; + PropertiesChangedForResize = propertiesChangedForResize; + Reverse = reverse; + SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions; + SaveFullYearOfRandomFiles = saveFullYearOfRandomFiles; + SaveResizedSubfiles = saveResizedSubfiles; + SaveShortcutsForOutputResolutions = saveShortcutsForOutputResolutions; + SkipSearch = skipSearch; + TestDistanceResults = testDistanceResults; + ValidResolutions = validResolutions; } public override string ToString() @@ -146,6 +108,6 @@ public class Configuration public void Set(Property.Models.Configuration configuration) => _PropertyConfiguration = configuration; - public void Update() => _PropertyConfiguration?.Update(); + public void Update() => _PropertyConfiguration.Update(); } \ No newline at end of file diff --git a/Instance/Models/DistanceHolder.cs b/Instance/Models/DistanceHolder.cs new file mode 100644 index 0000000..4555a9a --- /dev/null +++ b/Instance/Models/DistanceHolder.cs @@ -0,0 +1,48 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using View_by_Distance.FaceRecognitionDotNet; +using View_by_Distance.Property.Models; +using View_by_Distance.Shared.Models.Properties; + +namespace View_by_Distance.Instance.Models; + +internal class DistanceHolder +{ + + public IFace Face { init; get; } + public FaceEncoding? FaceEncoding { init; get; } + public FileHolder FileHolder { init; get; } + public int Id { init; get; } + public string JSONDirectory { init; get; } + public ILocation Location { init; get; } + public string TSVDirectory { init; get; } + public double Sort { get; set; } + + [JsonConstructor] + public DistanceHolder( + IFace face, + FaceEncoding? faceEncoding, + FileHolder fileHolder, + int id, + string jsonDirectory, + ILocation location, + string tsvDirectory + ) + { + FileHolder = fileHolder; + Sort = double.MaxValue; + Face = face; + FaceEncoding = faceEncoding; + Id = id; + JSONDirectory = jsonDirectory; + Location = location; + TSVDirectory = tsvDirectory; + } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + +} diff --git a/Instance/Models/Stateless/AppSettings.cs b/Instance/Models/Stateless/AppSettings.cs deleted file mode 100644 index 43f093e..0000000 --- a/Instance/Models/Stateless/AppSettings.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.Extensions.Configuration; -using System.Text.Json; - -namespace View_by_Distance.Instance.Models.Stateless; - -public abstract class AppSettings -{ - - public static Models.AppSettings Get(IConfigurationRoot configurationRoot) - { - Models.AppSettings? result; - Binder.AppSettings appSettings = configurationRoot.Get(); - string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true }); - result = JsonSerializer.Deserialize(json); - if (result is null) - throw new Exception(json); - if (string.IsNullOrEmpty(result.Company)) - throw new Exception(json); - string jsonThis = result.ToString(); - if (jsonThis != json) - { - int? check = null; - int min = new int[] { json.Length, jsonThis.Length }.Min(); - for (int i = 0; i < min; i++) - { - if (json[i] == jsonThis[i]) - continue; - check = i; - break; - } - if (check is null) - throw new Exception(); - string a = json[..check.Value].Split(',')[^1]; - string b = json[check.Value..].Split(',')[0]; - throw new Exception($"{a}{b}"); - } - return result; - } - -} \ No newline at end of file diff --git a/Instance/Models/Stateless/Configuration.cs b/Instance/Models/Stateless/Configuration.cs deleted file mode 100644 index 96e636c..0000000 --- a/Instance/Models/Stateless/Configuration.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Phares.Shared; -using System.Text.Json; - -namespace View_by_Distance.Instance.Models.Stateless; - -public abstract class Configuration -{ - - public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, string workingDirectory, Property.Models.Configuration propertyConfiguration) - { - Models.Configuration? result; - string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment); - string section = string.Concat(environmentName, ":", nameof(Binder.Configuration)); - IConfigurationSection configurationSection = configurationRoot.GetSection(section); - Binder.Configuration configuration = configurationSection.Get(); - string json = JsonSerializer.Serialize(configuration, new JsonSerializerOptions() { WriteIndented = true }); - result = JsonSerializer.Deserialize(json); - if (result is null) - throw new Exception(json); - string jsonThis = result.ToString(); - result.Set(propertyConfiguration); - result.Update(); - if (jsonThis != json) - { - int? check = null; - int min = new int[] { json.Length, jsonThis.Length }.Min(); - for (int i = 0; i < min; i++) - { - if (json[i] == jsonThis[i]) - continue; - check = i; - break; - } - if (check is null) - throw new Exception(); - string a = json[..check.Value].Split(',')[^1]; - string b = json[check.Value..].Split(',')[0]; - throw new Exception($"{a}{b}"); - } - return result; - } - -} \ No newline at end of file diff --git a/Instance/Models/_D2_FaceLandmark.cs b/Instance/Models/_D2_FaceLandmark.cs index 3b18223..c89c653 100644 --- a/Instance/Models/_D2_FaceLandmark.cs +++ b/Instance/Models/_D2_FaceLandmark.cs @@ -157,9 +157,7 @@ internal class D2_FaceLandmarks imageFiles.Add(new string[] { fileInfo.FullName, rotatedFileInfo.FullName }); if (check) continue; - if (_Configuration.OverrideForFaceLandmarkImages is null) - check = false; - else if (_Configuration.OverrideForFaceLandmarkImages.Value) + else if (_Configuration.OverrideForFaceLandmarkImages) check = true; else if (!fileInfo.Exists) check = true; diff --git a/Instance/Models/_D_Face.cs b/Instance/Models/_D_Face.cs index 221d085..6cd0944 100644 --- a/Instance/Models/_D_Face.cs +++ b/Instance/Models/_D_Face.cs @@ -254,14 +254,8 @@ public class D_Face : Shared.Models.Properties.IFace, IFace private List GetFaces(FileHolder resizedFileHolder, Item item, A_Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string facesDirectory) { List results = new(); - if (_Configuration.PaddingLoops is null) - throw new NullReferenceException(nameof(_Configuration.PaddingLoops)); if (item.ImageFileHolder is null) throw new NullReferenceException(nameof(item.ImageFileHolder)); - if (_Configuration.NumberOfJitters is null) - throw new NullReferenceException(nameof(_Configuration.NumberOfJitters)); - if (_Configuration.NumberOfTimesToUpsample is null) - throw new NullReferenceException(nameof(_Configuration.NumberOfTimesToUpsample)); List locations; FaceRecognitionDotNet.Image? unknownImage = null; if (resizedFileHolder.Exists) @@ -275,7 +269,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace else { FaceRecognition faceRecognition = FaceRecognition.Create(_ModelParameter); - locations = faceRecognition.FaceLocations(_Model, unknownImage, _Configuration.NumberOfTimesToUpsample.Value, sortByPixelPercentage: true); + locations = faceRecognition.FaceLocations(_Model, unknownImage, _Configuration.NumberOfTimesToUpsample, sortByNormalizedPixelPercentage: true); if (!locations.Any()) results.Add(new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, i: null, location: null)); else @@ -305,7 +299,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace padding = (int)((source.Width + source.Height) / 2 * .01); for (int i = 0; i < locations.Count; i++) { - for (int p = 0; p <= _Configuration.PaddingLoops.Value; p++) + for (int p = 0; p <= _Configuration.PaddingLoops; p++) { location = new(locations[i].Confidence, locations[i].Bottom + (padding * p), @@ -332,9 +326,9 @@ public class D_Face : Shared.Models.Properties.IFace, IFace { if (knownImage is null || knownImage.IsDisposed) throw new NullReferenceException(nameof(knownImage)); - facesLandmarks = faceRecognition.GetFaceLandmarkCollection(knownImage, _Configuration.NumberOfTimesToUpsample.Value, faceLocations: null, _PredictorModel, _Model); + facesLandmarks = faceRecognition.GetFaceLandmarkCollection(knownImage, _Configuration.NumberOfTimesToUpsample, faceLocations: null, _PredictorModel, _Model); } - if (facesLandmarks.Count == 0 && p < _Configuration.PaddingLoops.Value) + if (facesLandmarks.Count == 0 && p < _Configuration.PaddingLoops) continue; else if (facesLandmarks.Count != 1) continue; @@ -364,9 +358,9 @@ public class D_Face : Shared.Models.Properties.IFace, IFace { if (rotatedImage is null || rotatedImage.IsDisposed) throw new NullReferenceException(nameof(rotatedImage)); - faceEncodings = faceRecognition.FaceEncodings(rotatedImage, _Configuration.NumberOfTimesToUpsample.Value, knownFaceLocation: null, _Configuration.NumberOfJitters.Value, _PredictorModel, _Model); + faceEncodings = faceRecognition.FaceEncodings(rotatedImage, _Configuration.NumberOfTimesToUpsample, knownFaceLocation: null, _Configuration.NumberOfJitters, _PredictorModel, _Model); } - if (faceEncodings.Count == 0 && p < _Configuration.PaddingLoops.Value) + if (faceEncodings.Count == 0 && p < _Configuration.PaddingLoops) continue; else if (faceEncodings.Count != 1) continue; @@ -417,15 +411,11 @@ public class D_Face : Shared.Models.Properties.IFace, IFace List? results; if (item.Property?.Id is null) throw new NullReferenceException(nameof(item.Property.Id)); - if (_Configuration.PropertiesChangedForFaces is null) - throw new NullReferenceException(nameof(_Configuration.PropertiesChangedForFaces)); if (item.ImageFileHolder is null) throw new NullReferenceException(nameof(item.ImageFileHolder)); if (string.IsNullOrEmpty(dResultsFullGroupDirectory)) throw new NullReferenceException(nameof(dResultsFullGroupDirectory)); string json; - D_Face face; - bool checkForOutputResolutionChange = false; string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); @@ -453,7 +443,17 @@ public class D_Face : Shared.Models.Properties.IFace, IFace } if (!Directory.Exists(facesDirectory)) _ = Directory.CreateDirectory(facesDirectory); - if (_Configuration.PropertiesChangedForFaces.Value) + if (_Configuration.ForceFaceLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) + { + File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); + fileInfo.Refresh(); + } + if (_Configuration.ForceFaceLastWriteTimeToCreationTime && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime) + { + File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); + fileInfo.Refresh(); + } + if (_Configuration.PropertiesChangedForFaces) results = null; else if (!fileInfo.Exists) results = null; @@ -467,15 +467,6 @@ public class D_Face : Shared.Models.Properties.IFace, IFace results = JsonSerializer.Deserialize>(json); if (results is null) throw new NullReferenceException(nameof(results)); - for (int i = 0; i < results.Count; i++) - { - face = results[i]; - if (face.OutputResolution is not null) - continue; - if (!checkForOutputResolutionChange) - checkForOutputResolutionChange = true; - results[i] = new(outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, face); - } subFileTuples.Add(new Tuple(nameof(D_Face), fileInfo.LastWriteTime)); } catch (Exception) @@ -484,15 +475,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace parseExceptions.Add(nameof(D_Face)); } } - if (results is not null && checkForOutputResolutionChange) - { - json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); - bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; - DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); - if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) - File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); - } - else if (results is null) + if (results is null) { results = GetFaces(resizedFileHolder, item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, facesDirectory); json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); @@ -501,13 +484,23 @@ public class D_Face : Shared.Models.Properties.IFace, IFace if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) subFileTuples.Add(new Tuple(nameof(D_Face), DateTime.Now)); } + if (_Configuration.ForceFaceLastWriteTimeToCreationTime) + { + json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); + bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; + DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); + if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) + { + File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); + fileInfo.Refresh(); + subFileTuples.Add(new Tuple(nameof(D_Face), fileInfo.CreationTime)); + } + } return results; } internal void SaveFaces(string dResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, Item item, List faceCollection) { - if (_Configuration.OverrideForFaceImages is null) - throw new NullReferenceException(nameof(_Configuration.OverrideForFaceImages)); if (item.ImageFileHolder is null) throw new NullReferenceException(nameof(item.ImageFileHolder)); if (item.ResizedFileHolder is null) @@ -539,7 +532,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace File.Delete(parentCheck); } imageFiles.Add(fileInfo.FullName); - if (_Configuration.OverrideForFaceImages.Value) + if (_Configuration.OverrideForFaceImages) check = true; else if (!fileInfo.Exists) check = true; @@ -550,7 +543,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace SaveFaces(faceCollection, item.ResizedFileHolder, imageFiles); } - internal static void SaveShortcuts(string[] juliePhares, string dResultsFullGroupDirectory, long ticks, Dictionary> peopleCollection, PropertyLogic propertyLogic, Item[] filteredItems) + internal static void SaveShortcuts(string[] juliePhares, string dResultsFullGroupDirectory, long ticks, Dictionary> peopleCollection, PropertyLogic propertyLogic, List items) { Person person; string fileName; @@ -559,7 +552,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace WindowsShortcut windowsShortcut; const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]"; string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, $"({ticks})"); - List<(Item, (string, Shared.Models.Properties.IFace?, (string, string, string, string))[])> collections = Item.GetCollection(propertyLogic, filteredItems, dFacesContentDirectory); + List<(Item, (string, Shared.Models.Properties.IFace?, (string, string, string, string))[])> collections = Item.GetCollection(propertyLogic, items, dFacesContentDirectory); foreach ((Item item, (string personKey, Shared.Models.Properties.IFace? _, (string, string, string, string))[] collection) in collections) { if (collection.Length != 1) diff --git a/Instance/Models/_E_Distance.cs b/Instance/Models/_E_Distance.cs index 57e9b58..09a9718 100644 --- a/Instance/Models/_E_Distance.cs +++ b/Instance/Models/_E_Distance.cs @@ -1,19 +1,15 @@ -using System.Text; using System.Text.Json; using System.Text.RegularExpressions; using View_by_Distance.FaceRecognitionDotNet; using View_by_Distance.Metadata.Models; using View_by_Distance.Property.Models; using View_by_Distance.Resize.Models; +using View_by_Distance.Shared.Models.Properties; using View_by_Distance.Shared.Models.Stateless; using WindowsShortcutFactory; namespace View_by_Distance.Instance.Models; -/// -// List -/// - internal class E_Distance { @@ -34,183 +30,177 @@ internal class E_Distance return result; } - private static void LoadFaceEncodingCollections(Item[] filteredItems, List> faceCollections, List locationIndicesCollection, List faceEncodingCollection, List> faceEncodingCollections) + private static List GetDistanceHolder(Item[] items, List<(string JSONDirectory, string TSVDirectory)> directories) { - List faceCollection; - FaceEncoding faceEncoding; - for (int i = 0; i < filteredItems.Length; i++) + List results = new(); + Item item; + const int zero = 0; + string tsvDirectory; + string jsonDirectory; + FaceEncoding? faceEncoding; + if (items.Length != directories.Count) + throw new Exception(); + for (int i = 0; i < items.Length; i++) { - faceCollection = faceCollections[i]; - if (!faceCollection.Any()) - throw new Exception(); - faceEncodingCollections.Add(new List()); - for (int j = 0; j < faceCollection.Count; j++) + faceEncoding = null; + item = items[i]; + if (item.ImageFileHolder is null || item.Property?.Id is null || !item.Faces.Any()) + continue; + tsvDirectory = directories[i].TSVDirectory; + jsonDirectory = directories[i].JSONDirectory; + foreach (IFace face in item.Faces) { - if (!faceCollection[j].Populated) + if (!face.Populated) continue; - faceEncoding = FaceRecognition.LoadFaceEncoding(faceCollection[j].FaceEncoding.RawEncoding); - faceEncodingCollection.Add(faceEncoding); - faceEncodingCollections[i].Add(faceEncoding); - locationIndicesCollection.Add(new int[] { i, j }); + faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); + results.Add(new(face, faceEncoding, item.ImageFileHolder, item.Property.Id.Value, jsonDirectory, item.Faces[zero].Location, tsvDirectory)); } + if (faceEncoding is null) + results.Add(new(item.Faces[zero], null, item.ImageFileHolder, item.Property.Id.Value, jsonDirectory, item.Faces[zero].Location, tsvDirectory)); } + return results; } - private List> GetOrderedNoFaceCollection(List> faceCollections, int i, D_Face face) + private List> GetOrderedNoFaceCollection(List> faceCollections, int i, IFace face) { - List> results = new() { new(face, string.Empty) }; - if (_Configuration.MaxItemsInDistanceCollection is null) - throw new NullReferenceException(nameof(_Configuration.MaxItemsInDistanceCollection)); + List> results = new() { new(face, string.Empty) }; for (int n = 0; n < faceCollections.Count; n++) { if (i == n) continue; for (int j = 0; j < faceCollections[n].Count; j++) + { + if (!faceCollections[n][j].Populated) + continue; results.Add(new(faceCollections[n][j], string.Empty)); + } } - for (int r = results.Count - 1; r > _Configuration.MaxItemsInDistanceCollection.Value; r--) + for (int r = results.Count - 1; r > _Configuration.MaxItemsInDistanceCollection; r--) results.RemoveAt(r); return results; } - private List GetValues(List> faceCollections, List locationIndicesCollection, List faceDistances) + private void WriteNoFaceCollection(bool updateDateWhenMatches, DateTime? updateToWhenMatches, List> subFileTuples, List distanceHolders) { - List results = new(); - if (_Configuration.LocationConfidenceFactor is null) - throw new NullReferenceException(nameof(_Configuration.LocationConfidenceFactor)); - if (_Configuration.DistanceFactor is null) - throw new NullReferenceException(nameof(_Configuration.DistanceFactor)); - D_Face face; - int[] locationIndices; - for (int d = 0; d < faceDistances.Count; d++) - { - locationIndices = locationIndicesCollection[d]; - face = faceCollections[locationIndices[0]][locationIndices[1]]; - if (face.Populated && face.LocationIndex is not null && locationIndices[1] != face.LocationIndex) - throw new Exception(); - results.Add(new double[] { d, faceDistances[d], (faceDistances[d] * _Configuration.DistanceFactor.Value) + face.Location.Confidence * _Configuration.LocationConfidenceFactor.Value / 10 }); - } - results = (from l in results orderby l[2] select l).ToList(); - return results; - } - - private List> GetOrderedFaceCollection(List> faceCollections, List locationIndicesCollection, List indicesAndValues) - { - List> results = new(); - if (_Configuration.MaxItemsInDistanceCollection is null) - throw new NullReferenceException(nameof(_Configuration.MaxItemsInDistanceCollection)); - int[] locationIndices; - for (int t = 0; t < indicesAndValues.Count; t++) - { - locationIndices = locationIndicesCollection[(int)indicesAndValues[t][0]]; - results.Add(new(faceCollections[locationIndices[0]][locationIndices[1]], string.Join('|', (from l in indicesAndValues[t] select l.ToString("0.000")).ToArray(), 1, indicesAndValues[t].Length - 1))); - } - for (int r = results.Count - 1; r > _Configuration.MaxItemsInDistanceCollection.Value; r--) - results.RemoveAt(r); - return results; - } - - private static string GetText(string fileNameWithoutExtension, List> faceCollections, List locationIndicesCollection, List indicesAndValues) - { - string result; - D_Face face; - int[] locationIndices; - StringBuilder tvs = new(); - _ = tvs.Append("FileNameWithoutExtension").Append('\t').Append("LocationIndex").Append('\t').Append("FaceConfidence").Append('\t').Append("FaceDistance").Append('\t').Append("FactoredValue").AppendLine(); - for (int t = 0; t < indicesAndValues.Count; t++) - { - locationIndices = locationIndicesCollection[(int)indicesAndValues[t][0]]; - face = faceCollections[locationIndices[0]][locationIndices[1]]; - if (face.Populated && face.LocationIndex is not null && locationIndices[1] != face.LocationIndex) - throw new Exception(); - _ = tvs.Append(fileNameWithoutExtension).Append('\t').Append(face.LocationIndex).Append('\t').Append(face.Location.Confidence).Append('\t').Append(indicesAndValues[t][1]).Append('\t').Append(indicesAndValues[t][2]).AppendLine(); - } - result = tvs.ToString(); - return result; - } - - private void LoadOrCreateThenSaveDistanceResultsForOutputResolutionsLoop(List> faceCollections, int subFilesCount, int i, List faceCollection, List locationIndicesCollection, List> subFileTuples, List faceEncodingCollection, List faceEncodingCollections, string fileNameWithoutExtension, string jsonDirectory, string tvsDirectory, bool updateDateWhenMatches, DateTime? updateToWhenMatches) - { - string text; string json; + string check; string jsonFile; - List> orderedFaceCollection; - if (!Directory.Exists(jsonDirectory)) - _ = Directory.CreateDirectory(jsonDirectory); - if (!Directory.Exists(tvsDirectory)) - _ = Directory.CreateDirectory(tvsDirectory); - if (!faceEncodingCollections.Any()) + const int zero = 0; + DistanceHolder distanceHolder; + List> tupleCollection; + for (int i = 0; i < distanceHolders.Count; i++) { - int j = 0; - orderedFaceCollection = GetOrderedNoFaceCollection(faceCollections, i, faceCollection[j]); - json = JsonSerializer.Serialize(orderedFaceCollection, _WriteIndentedJsonSerializerOptions); - jsonFile = Path.Combine(jsonDirectory, $"{j} - {fileNameWithoutExtension}.json"); + distanceHolder = distanceHolders[i]; + if (distanceHolder.Face.Location.NormalizedPixelPercentage is null) + continue; + check = Path.Combine(distanceHolder.JSONDirectory, $"{zero} - {distanceHolder.FileHolder.NameWithoutExtension}.json"); + jsonFile = Path.Combine(distanceHolder.JSONDirectory, $"{distanceHolder.Id}.{zero}{distanceHolder.FileHolder.ExtensionLowered}.json"); + if (File.Exists(check)) + File.Move(check, jsonFile); + tupleCollection = new() { new(distanceHolders[i].Face, string.Empty) }; + for (int j = 0; j < distanceHolders.Count; j++) + { + if (j == i) + continue; + distanceHolder = distanceHolders[j]; + tupleCollection.Add(new(distanceHolder.Face, string.Empty)); + if (tupleCollection.Count > _Configuration.MaxItemsInDistanceCollection) + break; + } + json = JsonSerializer.Serialize(tupleCollection, _WriteIndentedJsonSerializerOptions); if (Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: updateToWhenMatches)) subFileTuples.Add(new Tuple(nameof(E_Distance), DateTime.Now)); } - else - { - string tvsFile; - List faceDistances; - List indicesAndValues; - for (int j = 0; j < faceEncodingCollections.Count; j++) - { - if (!faceCollection[j].Populated) - continue; - tvsFile = Path.Combine(tvsDirectory, $"{j} - {fileNameWithoutExtension}.tvs"); - jsonFile = Path.Combine(jsonDirectory, $"{j} - {fileNameWithoutExtension}.json"); - faceDistances = FaceRecognition.FaceDistances(faceEncodingCollection, faceEncodingCollections[j]); - indicesAndValues = GetValues(faceCollections, locationIndicesCollection, faceDistances); - orderedFaceCollection = GetOrderedFaceCollection(faceCollections, locationIndicesCollection, indicesAndValues); - text = GetText(fileNameWithoutExtension, faceCollections, locationIndicesCollection, indicesAndValues); - if (Property.Models.Stateless.IPath.WriteAllText(tvsFile, text, updateDateWhenMatches, compareBeforeWrite: true)) - subFileTuples.Add(new Tuple(nameof(E_Distance), DateTime.Now)); - json = JsonSerializer.Serialize(orderedFaceCollection, _WriteIndentedJsonSerializerOptions); - if (Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches, compareBeforeWrite: true)) - subFileTuples.Add(new Tuple(nameof(E_Distance), DateTime.Now)); - } - } } - private void LoadOrCreateThenSaveDistanceResultsForOutputResolutions(Item[] filteredItems, List> faceCollections, List directories, bool updateDateWhenMatches, DateTime? updateToWhenMatches) + private static List GetFaceEncodings(List distanceHolders) { - FileHolder? fileHolder; - List locationIndicesCollection = new(); - List> subFileTuples = new(); - List faceEncodingCollection = new(); - List> faceEncodingCollections = new(); - LoadFaceEncodingCollections(filteredItems, faceCollections, locationIndicesCollection, faceEncodingCollection, faceEncodingCollections); - if (faceEncodingCollections.Count != faceCollections.Count) - throw new Exception(); - if (locationIndicesCollection.Count != faceEncodingCollection.Count) - throw new Exception(); - for (int i = 0; i < filteredItems.Length; i++) + List results = new(); + foreach (DistanceHolder distanceHolder in distanceHolders) { - fileHolder = filteredItems[i].ImageFileHolder; - if (fileHolder is null) + if (!distanceHolder.Face.Populated || distanceHolder.FaceEncoding is null) continue; - LoadOrCreateThenSaveDistanceResultsForOutputResolutionsLoop(faceCollections, filteredItems.Length, i, faceCollections[i], locationIndicesCollection, subFileTuples, faceEncodingCollection, faceEncodingCollections[i], fileHolder.NameWithoutExtension, directories[i][0], directories[i][1], updateDateWhenMatches, updateToWhenMatches); + results.Add(distanceHolder.FaceEncoding); + } + return results; + } + + private void SaveDistanceResults(bool updateDateWhenMatches, DateTime? updateToWhenMatches, List> subFileTuples, List distanceHolders) + { + string json; + string check; + string jsonFile; + int locationIndex; + List faceDistances; + DistanceHolder distanceHolder; + int normalizedPixelPercentage; + DistanceHolder[] sortedDistanceHolders; + List> tupleCollection; + List<(int Index, double Distance)> collection; + distanceHolders = distanceHolders.OrderByDescending(l => l.Face.Populated).ToList(); + List faceEncodings = GetFaceEncodings(distanceHolders); + for (int i = 0; i < distanceHolders.Count; i++) + { + distanceHolder = distanceHolders[i]; + collection = new(); + tupleCollection = new(); + distanceHolder.Sort = 0d; + if (distanceHolder.Face.LocationIndex is null) + locationIndex = 0; + else + locationIndex = distanceHolder.Face.LocationIndex.Value; + if (!distanceHolder.Face.Populated || distanceHolder.Face.Location.NormalizedPixelPercentage is null) + normalizedPixelPercentage = 0; + else + normalizedPixelPercentage = distanceHolder.Face.Location.NormalizedPixelPercentage.Value; + check = Path.Combine(distanceHolder.JSONDirectory, $"{locationIndex} - {distanceHolder.FileHolder.NameWithoutExtension}.json"); + jsonFile = Path.Combine(distanceHolder.JSONDirectory, $"{distanceHolder.Id}.{normalizedPixelPercentage}{distanceHolder.FileHolder.ExtensionLowered}.json"); + if (!Directory.Exists(distanceHolder.JSONDirectory)) + _ = Directory.CreateDirectory(distanceHolder.JSONDirectory); + if (File.Exists(check)) + File.Move(check, jsonFile); + if (faceEncodings.Count == 1) + faceDistances = new() { 0d }; + else if (distanceHolder.FaceEncoding is null) + faceDistances = Enumerable.Repeat(9d, faceEncodings.Count).ToList(); + else + faceDistances = FaceRecognition.FaceDistances(faceEncodings, distanceHolder.FaceEncoding); + if (distanceHolder.Face.Populated && distanceHolder.FaceEncoding is not null && faceDistances[i] != 0d) + faceDistances[i] = 0d; + for (int d = 0; d < faceDistances.Count; d++) + collection.Add(new(d, faceDistances[d])); + collection = collection.OrderBy(l => l.Distance).ToList(); + foreach ((int index, double distance) in collection) + distanceHolders[index].Sort = ((distance * _Configuration.DistanceFactor) + (distanceHolders[index].Location.Confidence * _Configuration.LocationConfidenceFactor)) / 10; + sortedDistanceHolders = distanceHolders.OrderBy(l => l.Sort).ToArray(); + for (int j = 0; j < sortedDistanceHolders.Length; j++) + { + distanceHolder = sortedDistanceHolders[j]; + tupleCollection.Add(new(distanceHolders[j].Face, string.Empty)); + if (tupleCollection.Count > _Configuration.MaxItemsInDistanceCollection) + break; + } + json = JsonSerializer.Serialize(tupleCollection, _WriteIndentedJsonSerializerOptions); + if (Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: updateToWhenMatches)) + subFileTuples.Add(new Tuple(nameof(E_Distance), DateTime.Now)); } } - internal void LoadOrCreateThenSaveDistanceResultsForOutputResolutions(Property.Models.Configuration configuration, string eResultsFullGroupDirectory, string sourceDirectory, string outputResolution, List> sourceDirectoryChanges, Item[] filteredItems, List> faceCollections) + internal void LoadOrCreateThenSaveDistanceResults(Property.Models.Configuration configuration, string eResultsFullGroupDirectory, string sourceDirectory, string outputResolution, List> sourceDirectoryChanges, Item[] filteredItems) { - if (_Configuration.CheckJsonForDistanceResults is null) - throw new NullReferenceException(nameof(_Configuration.CheckJsonForDistanceResults)); - if (_Configuration.PropertiesChangedForDistance is null) - throw new NullReferenceException(nameof(_Configuration.PropertiesChangedForDistance)); Item item; string json; bool check = false; string parentCheck; + bool hasPopulatedFace; string usingRelativePath; DateTime? dateTime = null; string dCollectionDirectory; - FileInfo[] fileInfoCollection; bool updateDateWhenMatches = false; - List directories = new(); System.IO.DirectoryInfo directoryInfo; System.IO.DirectoryInfo tvsDirectoryInfo; + IEnumerator fileInfoCollection; + List<(string, string)> directories = new(); string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; List dateTimes = (from l in sourceDirectoryChanges where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection( @@ -226,6 +216,7 @@ internal class E_Distance item = filteredItems[i]; if (item.ImageFileHolder is null || item.Property?.Id is null) continue; + hasPopulatedFace = (from l in item.Faces where l.Populated select true).Any(); usingRelativePath = Path.Combine(directoryInfoCollection[0].Replace("<>", "[]"), item.ImageFileHolder.NameWithoutExtension); dCollectionDirectory = Path.Combine(eResultsFullGroupDirectory, "[]", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}"); directoryInfo = new System.IO.DirectoryInfo(dCollectionDirectory); @@ -250,24 +241,32 @@ internal class E_Distance } } tvsDirectoryInfo = new System.IO.DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension)); - directories.Add(new string[] { directoryInfo.FullName, tvsDirectoryInfo.FullName }); - if (_Configuration.CheckJsonForDistanceResults.Value && directoryInfo.Exists) + directories.Add(new(directoryInfo.FullName, tvsDirectoryInfo.FullName)); + if (_Configuration.CheckJsonForDistanceResults && directoryInfo.Exists) { - fileInfoCollection = directoryInfo.GetFiles("*.json", SearchOption.AllDirectories); - for (int j = 0; j < fileInfoCollection.Length; j++) + json = string.Empty; + fileInfoCollection = directoryInfo.EnumerateFiles("*.json", SearchOption.AllDirectories).GetEnumerator(); + for (int j = 0; j < int.MaxValue; j++) { - json = Shared.Models.Stateless.Methods.IIndex.GetJson(fileInfoCollection[j].FullName, fileInfoCollection[j]); - if (!_Configuration.PropertiesChangedForDistance.Value && Shared.Models.Stateless.Methods.IFace.GetFace(fileInfoCollection[j].FullName) is null) + if (!fileInfoCollection.MoveNext()) + break; + json = Shared.Models.Stateless.Methods.IIndex.GetJson(fileInfoCollection.Current.FullName, fileInfoCollection.Current); + if (!_Configuration.PropertiesChangedForDistance && Shared.Models.Stateless.Methods.IFace.GetFace(fileInfoCollection.Current.FullName) is null) + { check = true; + break; + } } + if (!check && string.IsNullOrEmpty(json)) + check = true; } if (check) continue; - if (_Configuration.PropertiesChangedForDistance.Value) + if (_Configuration.PropertiesChangedForDistance) check = true; - else if (!directoryInfo.Exists) + else if (hasPopulatedFace && !directoryInfo.Exists) check = true; - else if (!tvsDirectoryInfo.Exists) + else if (hasPopulatedFace && !tvsDirectoryInfo.Exists) check = true; else if (dateTimes.Any() && dateTimes.Max() > directoryInfo.LastWriteTime) check = true; @@ -278,7 +277,12 @@ internal class E_Distance } } if (check) - LoadOrCreateThenSaveDistanceResultsForOutputResolutions(filteredItems, faceCollections, directories, updateDateWhenMatches, updateToWhenMatches: dateTime); + { + DateTime? updateToWhenMatches = dateTime; + List> subFileTuples = new(); + List distanceHolders = GetDistanceHolder(filteredItems, directories); + SaveDistanceResults(updateDateWhenMatches, updateToWhenMatches, subFileTuples, distanceHolders); + } _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(directoryInfoCollection[0].Replace("<>", "()")); } @@ -377,8 +381,6 @@ internal class E_Distance int filesCount = files.Count; for (int i = 0; i < filesCount; i++) { - if (_Configuration.CrossDirectoryMaxItemsInDistanceCollection is null) - continue; _Log.Debug(string.Concat("LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions - ", nameof(outputResolution), ' ', outputResolution, " - ", i, " of ", filesCount)); for (int j = 0; j < files[i].Item2.Count; j++) { @@ -405,7 +407,7 @@ internal class E_Distance }); if (faceAndFaceDistanceCollection.Any()) { - faceAndFaceDistanceCollection = (from l in faceAndFaceDistanceCollection orderby l.Item2 select l).Take(_Configuration.CrossDirectoryMaxItemsInDistanceCollection.Value).ToList(); + faceAndFaceDistanceCollection = (from l in faceAndFaceDistanceCollection orderby l.Item2 select l).Take(_Configuration.CrossDirectoryMaxItemsInDistanceCollection).ToList(); Save(configuration, model, predictorModel, outputResolution, eDistanceCollectionDirectory, k, relativePath, face, faceAndFaceDistanceCollection); } } @@ -423,7 +425,7 @@ internal class E_Distance return result; } - private static FaceEncoding? GetFaceEncoding(Shared.Models.Properties.IFace face) + private static FaceEncoding? GetFaceEncoding(IFace face) { FaceEncoding? result; if (!face.Populated) @@ -439,14 +441,14 @@ internal class E_Distance return new(i, faceDistances.Sum()); } - private static List GetFaceEncodings(int maxDegreeOfParallelism, List<(DateTime MinimumDateTime, bool? IsWrongYear, Shared.Models.PersonBirthday PersonBirthday, Shared.Models.Properties.IFace Face)> collection) + private static List GetFaceEncodings(int maxDegreeOfParallelism, List<(DateTime MinimumDateTime, bool? IsWrongYear, Shared.Models.PersonBirthday PersonBirthday, IFace Face)> collection) { List results; if (maxDegreeOfParallelism == 1) { results = new(); FaceEncoding faceEncoding; - foreach ((DateTime _, bool? _, Shared.Models.PersonBirthday _, Shared.Models.Properties.IFace face) in collection) + foreach ((DateTime _, bool? _, Shared.Models.PersonBirthday _, IFace face) in collection) { if (!face.Populated) continue; @@ -518,12 +520,12 @@ internal class E_Distance return results; } - private static List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> GetThreeSigmaFaceEncodings(int maxDegreeOfParallelism, Dictionary> keyValuePairs) + private static List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> GetThreeSigmaFaceEncodings(int maxDegreeOfParallelism, Dictionary> keyValuePairs) { List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> results = new(); const int zero = 0; List faceEncodings; - foreach (KeyValuePair> keyValuePair in keyValuePairs) + foreach (KeyValuePair> keyValuePair in keyValuePairs) { faceEncodings = GetFaceEncodings(maxDegreeOfParallelism, keyValuePair.Value); results.Add(new(keyValuePair.Value[zero].MinimumDateTime, keyValuePair.Value[zero].IsWrongYear, keyValuePair.Value[zero].PersonBirthday, faceEncodings.ToArray())); @@ -531,7 +533,7 @@ internal class E_Distance return results; } - private static Closest? GetClosestParallelFor(DateTime minimumDateTime, bool? isWrongYear, Shared.Models.Properties.IFace face, FaceEncoding faceEncoding, (DateTime MinimumDateTime, bool? IsWrongYear, Shared.Models.PersonBirthday PersonBirthday, FaceEncoding[] FaceEncodings) tuple) + private static Closest? GetClosestParallelFor(DateTime minimumDateTime, bool? isWrongYear, IFace face, FaceEncoding faceEncoding, (DateTime MinimumDateTime, bool? IsWrongYear, Shared.Models.PersonBirthday PersonBirthday, FaceEncoding[] FaceEncodings) tuple) { Closest? result; if (isWrongYear.HasValue && !isWrongYear.Value && minimumDateTime < tuple.PersonBirthday.Value) @@ -546,7 +548,7 @@ internal class E_Distance return result; } - private static Closest[] GetClosestCollection(int maxDegreeOfParallelism, List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> collection, DateTime itemMinimumDateTime, bool? itemIsWrongYear, Shared.Models.Properties.IFace face) + private static Closest[] GetClosestCollection(int maxDegreeOfParallelism, List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> collection, DateTime itemMinimumDateTime, bool? itemIsWrongYear, IFace face) { Closest[] results; List closestCollection; @@ -585,14 +587,16 @@ internal class E_Distance return results; } - private static void AddClosest(int maxDegreeOfParallelism, string argZero, List containers, List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> collection) + private static void AddClosest(int maxDegreeOfParallelism, string argZero, PropertyLogic propertyLogic, List containers, List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> collection) { string key; + IFace face; Closest closest; + string personKey; bool? itemIsWrongYear; Closest[] closestCollection; DateTime? itemMinimumDateTime; - Shared.Models.Properties.IFace face; + float deterministicHashCodeKey; Dictionary results = new(); foreach (Container container in containers) { @@ -618,12 +622,16 @@ internal class E_Distance item.Closest.Add(closest); if (!face.Populated) continue; + deterministicHashCodeKey = Named.GetDeterministicHashCodeKey(item, face); closestCollection = GetClosestCollection(maxDegreeOfParallelism, collection, itemMinimumDateTime.Value, itemIsWrongYear, face); for (int j = 0; j < closestCollection.Length; j++) { closest = closestCollection[j]; if (closest.PersonBirthday is null) continue; + personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(closest.PersonBirthday); + if (propertyLogic.IncorrectDeterministicHashCodeKeyValuePairs.ContainsKey(deterministicHashCodeKey) && propertyLogic.IncorrectDeterministicHashCodeKeyValuePairs[deterministicHashCodeKey].Contains(personKey)) + continue; key = Item.GetKey(closest.MinimumDateTime, closest.IsWrongYear, closest.PersonBirthday); if (!results.ContainsKey(key)) results.Add(key, 0); @@ -638,12 +646,12 @@ internal class E_Distance } } - internal static List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> ParallelWork(int maxDegreeOfParallelism, string argZero, List containers) + internal static List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> ParallelWork(int maxDegreeOfParallelism, string argZero, PropertyLogic propertyLogic, List containers) { List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> results; - Dictionary> keyValuePairs = Item.GetKeyValuePairs(argZero, containers); + Dictionary> keyValuePairs = Item.GetKeyValuePairs(argZero, containers); results = GetThreeSigmaFaceEncodings(maxDegreeOfParallelism, keyValuePairs); - AddClosest(maxDegreeOfParallelism, argZero, containers, results); + AddClosest(maxDegreeOfParallelism, argZero, propertyLogic, containers, results); return results; } @@ -707,7 +715,7 @@ internal class E_Distance } } - internal static List<(FileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile)> GetClosest(string argZero, List containers, Dictionary> peopleCollection, PropertyLogic propertyLogic, string eDistanceContentDirectory, string dFacesContentDirectory) + internal static List<(FileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile)> GetClosest(string argZero, List containers, Dictionary> peopleCollection, string eDistanceContentDirectory, string dFacesContentDirectory) { List<(FileHolder?, string, FileInfo?, string, string)> results = new(); string checkFile; @@ -720,8 +728,8 @@ internal class E_Distance string facesDirectory; string personDirectory; Shared.Models.Person person; + float deterministicHashCodeKey; const string facePopulatedKey = "Closest"; - string deterministicHashCodeIdAndFaceLocationIndex; const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]"; foreach (Container container in containers) { @@ -740,14 +748,10 @@ internal class E_Distance throw new Exception(); foreach (Closest closest in item.Closest) { - if (closest.Average is null || closest.FaceLocationIndex is null || closest.PersonBirthday is null) - continue; - deterministicHashCodeIdAndFaceLocationIndex = $"{closest.FaceLocationIndex.Value} - {item.Property.Id.Value}"; - if (propertyLogic.NamedDeterministicHashCodeIdAndFaceLocationIndex.Contains(deterministicHashCodeIdAndFaceLocationIndex)) + if (closest.Average is null || closest.NormalizedPixelPercentage is null || closest.PersonBirthday is null) continue; personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(closest.PersonBirthday); directory = Item.GetDirectory(eDistanceContentDirectory, facePopulatedKey, closest.MinimumDateTime, closest.IsWrongYear, closest.PersonBirthday, personKey); - // checkFile = Path.Combine(directory, item.ImageFileHolder.Name); if (!peopleCollection.ContainsKey(personKey)) personDirectory = string.Empty; else @@ -758,12 +762,13 @@ internal class E_Distance results.Add(new(null, personDirectory, null, string.Empty, string.Empty)); } facesDirectory = string.Concat(dFacesContentDirectory, Path.Combine(directoryName, item.ImageFileHolder.NameWithoutExtension)); - faceFileInfo = new(Path.Combine(facesDirectory, $"{closest.FaceLocationIndex.Value} - {item.ImageFileHolder.NameWithoutExtension}.png")); - checkFile = Path.Combine(directory, $"{deterministicHashCodeIdAndFaceLocationIndex}{item.ImageFileHolder.ExtensionLowered}"); + faceFileInfo = new(Path.Combine(facesDirectory, $"{closest.NormalizedPixelPercentage.Value} - {item.ImageFileHolder.NameWithoutExtension}.png")); + deterministicHashCodeKey = Named.GetDeterministicHashCodeKey(item, closest); + checkFile = Path.Combine(directory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}"); if (string.IsNullOrEmpty(personDirectory)) shortcutFile = string.Empty; else - shortcutFile = Path.Combine(personDirectory, $"{deterministicHashCodeIdAndFaceLocationIndex}{item.ImageFileHolder.ExtensionLowered}.lnk"); + shortcutFile = Path.Combine(personDirectory, $"{item.ImageFileHolder.ExtensionLowered}.lnk"); results.Add(new(item.ResizedFileHolder, directory, faceFileInfo, checkFile, shortcutFile)); } } @@ -771,10 +776,10 @@ internal class E_Distance return results; } - internal static void SaveClosest(string argZero, List containers, Dictionary> peopleCollection, PropertyLogic propertyLogic, string eDistanceContentDirectory, string dFacesContentDirectory) + internal static void SaveClosest(string argZero, List containers, Dictionary> peopleCollection, string eDistanceContentDirectory, string dFacesContentDirectory) { WindowsShortcut windowsShortcut; - List<(FileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile)> collection = GetClosest(argZero, containers, peopleCollection, propertyLogic, eDistanceContentDirectory, dFacesContentDirectory); + List<(FileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile)> collection = GetClosest(argZero, containers, peopleCollection, eDistanceContentDirectory, dFacesContentDirectory); string[] directories = (from l in collection select l.directory).Distinct().ToArray(); foreach (string directory in directories) { diff --git a/Instance/Models/_F_Random.cs b/Instance/Models/_F_Random.cs index 4156cd2..852bcd5 100644 --- a/Instance/Models/_F_Random.cs +++ b/Instance/Models/_F_Random.cs @@ -47,8 +47,6 @@ internal class F_Random internal void Random(Property.Models.Configuration configuration, string outputResolution, List> fileKeyValuePairs) { - if (_Configuration.SaveFullYearOfRandomFiles is null) - throw new Exception(); string json; string jsonFile; Random random = new(); @@ -74,7 +72,7 @@ internal class F_Random jsonFile = Path.Combine(fRandomCollectionDirectory, $"{dateTime.AddDays(i):MM-dd}.json"); json = JsonSerializer.Serialize(relativePaths, _WriteIndentedJsonSerializerOptions); _ = Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: false, compareBeforeWrite: false); - if (!_Configuration.SaveFullYearOfRandomFiles.Value) + if (!_Configuration.SaveFullYearOfRandomFiles) break; } } diff --git a/Instance/Models/_G_Index.cs b/Instance/Models/_G_Index.cs index 86a54cc..147afad 100644 --- a/Instance/Models/_G_Index.cs +++ b/Instance/Models/_G_Index.cs @@ -144,8 +144,6 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex internal void SetIndex(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, Dictionary>> filePropertiesKeyValuePairs) { - if (_Configuration.PropertiesChangedForIndex is null) - throw new Exception(); FileInfo fileInfo; G_Index indexInfo; string parentCheck; @@ -181,7 +179,7 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex if (File.Exists(parentCheck)) File.Delete(parentCheck); } - if (_Configuration.PropertiesChangedForIndex.Value) + if (_Configuration.PropertiesChangedForIndex) indexInfo = null; else if (!fileInfo.Exists) indexInfo = null; diff --git a/Instance/Program.cs b/Instance/Program.cs index 43be07c..b2edc0b 100644 --- a/Instance/Program.cs +++ b/Instance/Program.cs @@ -20,10 +20,8 @@ public class Program .AddEnvironmentVariables() .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); IConfigurationRoot configurationRoot = configurationBuilder.Build(); - AppSettings appSettings = Models.Stateless.AppSettings.Get(configurationRoot); - if (appSettings.MaxDegreeOfParallelism is null) - throw new Exception("MaxDegreeOfParallelism must be set!"); - if (appSettings.MaxDegreeOfParallelism.Value > Environment.ProcessorCount) + AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount) throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!"); if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) throw new Exception("Working directory name must have a value!"); diff --git a/Instance/appsettings.Staging.json b/Instance/appsettings.Staging.json index fdd4022..01d3c92 100644 --- a/Instance/appsettings.Staging.json +++ b/Instance/appsettings.Staging.json @@ -55,6 +55,7 @@ "DateGroup": "2022-08-14", "DistanceFactor": 8, "FileNameDirectorySeparator": ".Z.", + "ForceFaceLastWriteTimeToCreationTime": false, "ForceMetadataLastWriteTimeToCreationTime": false, "ForcePropertyLastWriteTimeToCreationTime": false, "ForceResizeLastWriteTimeToCreationTime": false, diff --git a/Instance/appsettings.json b/Instance/appsettings.json index e2f74f0..4ff8359 100644 --- a/Instance/appsettings.json +++ b/Instance/appsettings.json @@ -55,6 +55,7 @@ "DateGroup": "2022-08-14", "DistanceFactor": 8, "FileNameDirectorySeparator": ".Z.", + "ForceFaceLastWriteTimeToCreationTime": false, "ForceMetadataLastWriteTimeToCreationTime": false, "ForcePropertyLastWriteTimeToCreationTime": false, "ForceResizeLastWriteTimeToCreationTime": false, diff --git a/Not-Copy-Copy/Models/AppSettings.cs b/Not-Copy-Copy/Models/AppSettings.cs index 994a295..2c8fe49 100644 --- a/Not-Copy-Copy/Models/AppSettings.cs +++ b/Not-Copy-Copy/Models/AppSettings.cs @@ -6,24 +6,16 @@ namespace View_by_Distance.Not.Copy.Copy.Models; public class AppSettings { - protected string _Company; - protected string _WorkingDirectoryName; - protected int? _MaxDegreeOfParallelism; - public string Company => _Company; - public string WorkingDirectoryName => _WorkingDirectoryName; - public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism; - - // public AppSettings() - // { - - // } + public string Company { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string WorkingDirectoryName { init; get; } [JsonConstructor] - public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism) + public AppSettings(string company, int maxDegreeOfParallelism, string workingDirectoryName) { - _Company = company; - _WorkingDirectoryName = workingDirectoryName; - _MaxDegreeOfParallelism = maxDegreeOfParallelism; + Company = company; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + WorkingDirectoryName = workingDirectoryName; } public override string ToString() diff --git a/Not-Copy-Copy/Models/Binder/AppSettings.cs b/Not-Copy-Copy/Models/Binder/AppSettings.cs index bf7052f..07e2b02 100644 --- a/Not-Copy-Copy/Models/Binder/AppSettings.cs +++ b/Not-Copy-Copy/Models/Binder/AppSettings.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Configuration; using System.Text.Json; namespace View_by_Distance.Not.Copy.Copy.Models.Binder; @@ -6,16 +6,13 @@ namespace View_by_Distance.Not.Copy.Copy.Models.Binder; public class AppSettings { - [Display(Name = "Company"), Required] public string Company { get; set; } - [Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; } - [Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; } +#nullable disable - public AppSettings() - { - Company = string.Empty; - WorkingDirectoryName = string.Empty; - MaxDegreeOfParallelism = -1; - } + public string Company { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string WorkingDirectoryName { get; set; } + +#nullable restore public override string ToString() { @@ -23,4 +20,25 @@ public class AppSettings return result; } + private static Models.AppSettings Get(AppSettings appSettings) + { + Models.AppSettings result; + if (appSettings.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + result = new( + appSettings.Company, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + } \ No newline at end of file diff --git a/Not-Copy-Copy/Models/Stateless/AppSettings.cs b/Not-Copy-Copy/Models/Stateless/AppSettings.cs deleted file mode 100644 index 25e5179..0000000 --- a/Not-Copy-Copy/Models/Stateless/AppSettings.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.Extensions.Configuration; -using System.Text.Json; - -namespace View_by_Distance.Not.Copy.Copy.Models.Stateless; - -public abstract class AppSettings -{ - - public static Models.AppSettings Get(IConfigurationRoot configurationRoot) - { - Models.AppSettings? result; - Binder.AppSettings appSettings = configurationRoot.Get(); - string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true }); - result = JsonSerializer.Deserialize(json); - if (result is null) - throw new Exception(json); - if (string.IsNullOrEmpty(result.Company)) - throw new Exception(json); - string jsonThis = result.ToString(); - if (jsonThis != json) - { - int? check = null; - int min = new int[] { json.Length, jsonThis.Length }.Min(); - for (int i = 0; i < min; i++) - { - if (json[i] == jsonThis[i]) - continue; - check = i; - break; - } - if (check is null) - throw new Exception(); - string a = json[..check.Value].Split(',')[^1]; - string b = json[check.Value..].Split(',')[0]; - throw new Exception($"{a}{b}"); - } - return result; - } - -} \ No newline at end of file diff --git a/Not-Copy-Copy/Not-Copy-Copy.cs b/Not-Copy-Copy/Not-Copy-Copy.cs index 4d321e0..605ee6b 100644 --- a/Not-Copy-Copy/Not-Copy-Copy.cs +++ b/Not-Copy-Copy/Not-Copy-Copy.cs @@ -24,8 +24,6 @@ public class NotCopyCopy if (console is null) { } _AppSettings = appSettings; - if (appSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); _IsEnvironment = isEnvironment; _Log = Serilog.Log.ForContext(); Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory); @@ -108,11 +106,9 @@ public class NotCopyCopy private PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel) { PropertyLogic result; - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); if (_Configuration?.PropertyConfiguration is null) throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, reverse, model, predictorModel); + result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, reverse, model, predictorModel); return result; } diff --git a/Not-Copy-Copy/Program.cs b/Not-Copy-Copy/Program.cs index ab7f609..5df9a03 100644 --- a/Not-Copy-Copy/Program.cs +++ b/Not-Copy-Copy/Program.cs @@ -21,10 +21,8 @@ public class Program .AddEnvironmentVariables() .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); IConfigurationRoot configurationRoot = configurationBuilder.Build(); - AppSettings appSettings = Models.Stateless.AppSettings.Get(configurationRoot); - if (appSettings.MaxDegreeOfParallelism is null) - throw new Exception("MaxDegreeOfParallelism must be set!"); - if (appSettings.MaxDegreeOfParallelism.Value > Environment.ProcessorCount) + AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount) throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!"); if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) throw new Exception("Working directory name must have a value!"); diff --git a/PrepareForOld/Models/AppSettings.cs b/PrepareForOld/Models/AppSettings.cs index 138819c..ea6049a 100644 --- a/PrepareForOld/Models/AppSettings.cs +++ b/PrepareForOld/Models/AppSettings.cs @@ -6,24 +6,16 @@ namespace View_by_Distance.PrepareForOld.Models; public class AppSettings { - protected string _Company; - protected string _WorkingDirectoryName; - protected int? _MaxDegreeOfParallelism; - public string Company => _Company; - public string WorkingDirectoryName => _WorkingDirectoryName; - public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism; - - // public AppSettings() - // { - - // } + public string Company { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string WorkingDirectoryName { init; get; } [JsonConstructor] - public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism) + public AppSettings(string company, int maxDegreeOfParallelism, string workingDirectoryName) { - _Company = company; - _WorkingDirectoryName = workingDirectoryName; - _MaxDegreeOfParallelism = maxDegreeOfParallelism; + Company = company; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + WorkingDirectoryName = workingDirectoryName; } public override string ToString() diff --git a/PrepareForOld/Models/Binder/AppSettings.cs b/PrepareForOld/Models/Binder/AppSettings.cs index 5426197..8fbc37d 100644 --- a/PrepareForOld/Models/Binder/AppSettings.cs +++ b/PrepareForOld/Models/Binder/AppSettings.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Configuration; using System.Text.Json; namespace View_by_Distance.PrepareForOld.Models.Binder; @@ -6,16 +6,13 @@ namespace View_by_Distance.PrepareForOld.Models.Binder; public class AppSettings { - [Display(Name = "Company"), Required] public string Company { get; set; } - [Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; } - [Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; } +#nullable disable - public AppSettings() - { - Company = string.Empty; - WorkingDirectoryName = string.Empty; - MaxDegreeOfParallelism = -1; - } + public string Company { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string WorkingDirectoryName { get; set; } + +#nullable restore public override string ToString() { @@ -23,4 +20,25 @@ public class AppSettings return result; } + private static Models.AppSettings Get(AppSettings appSettings) + { + Models.AppSettings result; + if (appSettings.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + result = new( + appSettings.Company, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + } \ No newline at end of file diff --git a/PrepareForOld/Models/Stateless/AppSettings.cs b/PrepareForOld/Models/Stateless/AppSettings.cs deleted file mode 100644 index 667b5b7..0000000 --- a/PrepareForOld/Models/Stateless/AppSettings.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.Extensions.Configuration; -using System.Text.Json; - -namespace View_by_Distance.PrepareForOld.Models.Stateless; - -public abstract class AppSettings -{ - - public static Models.AppSettings Get(IConfigurationRoot configurationRoot) - { - Models.AppSettings? result; - Binder.AppSettings appSettings = configurationRoot.Get(); - string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true }); - result = JsonSerializer.Deserialize(json); - if (result is null) - throw new Exception(json); - if (string.IsNullOrEmpty(result.Company)) - throw new Exception(json); - string jsonThis = result.ToString(); - if (jsonThis != json) - { - int? check = null; - int min = new int[] { json.Length, jsonThis.Length }.Min(); - for (int i = 0; i < min; i++) - { - if (json[i] == jsonThis[i]) - continue; - check = i; - break; - } - if (check is null) - throw new Exception(); - string a = json[..check.Value].Split(',')[^1]; - string b = json[check.Value..].Split(',')[0]; - throw new Exception($"{a}{b}"); - } - return result; - } - -} \ No newline at end of file diff --git a/PrepareForOld/PrepareForOld.cs b/PrepareForOld/PrepareForOld.cs index 62bb60a..11b1cdb 100644 --- a/PrepareForOld/PrepareForOld.cs +++ b/PrepareForOld/PrepareForOld.cs @@ -29,8 +29,6 @@ public class PrepareForOld string spellingA; string spellingB; _AppSettings = appSettings; - if (appSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); _SpellingFindReplace = new(); _IsEnvironment = isEnvironment; _Exceptions = new List(); @@ -225,8 +223,6 @@ public class PrepareForOld { if (_Log is null) throw new NullReferenceException(nameof(_Log)); - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); if (_Configuration?.PropertyConfiguration is null) throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory); @@ -251,7 +247,7 @@ public class PrepareForOld string infoDirectoryExtra = Path.Combine(imageSharedDirectory, "Images - 4) Info - - - Extra", "2022-04-14"); List mappedIndices = GetUseTabSeparatedValueIndices(useDirectory); List<(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)> collection = new(); - PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory); + PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory); PropertyCompare.Models.PropertyCompare[] propertyCompareCollection = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan, duplicates, deleteExtension: false); { long ticks = DateTime.Now.Ticks; @@ -592,8 +588,6 @@ public class PrepareForOld { if (_Log is null) throw new NullReferenceException(nameof(_Log)); - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); if (_Configuration?.PropertyConfiguration is null) throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory); @@ -612,7 +606,7 @@ public class PrepareForOld string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json"); string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07"); List<(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)> collection = new(); - PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory); + PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory); PropertyCompare.Models.PropertyCompare[] propertyCompareCollection = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan); { long ticks = DateTime.Now.Ticks; diff --git a/PrepareForOld/Program.cs b/PrepareForOld/Program.cs index ed23c36..ca2d4f5 100644 --- a/PrepareForOld/Program.cs +++ b/PrepareForOld/Program.cs @@ -21,10 +21,8 @@ public class Program .AddEnvironmentVariables() .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); IConfigurationRoot configurationRoot = configurationBuilder.Build(); - AppSettings appSettings = Models.Stateless.AppSettings.Get(configurationRoot); - if (appSettings.MaxDegreeOfParallelism is null) - throw new Exception("MaxDegreeOfParallelism must be set!"); - if (appSettings.MaxDegreeOfParallelism.Value > Environment.ProcessorCount) + AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount) throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!"); if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) throw new Exception("Working directory name must have a value!"); diff --git a/Property/Models/Closest.cs b/Property/Models/Closest.cs index 7c8b31d..67dc3f1 100644 --- a/Property/Models/Closest.cs +++ b/Property/Models/Closest.cs @@ -11,36 +11,36 @@ public class Closest public const float MinimumMinimum = 0.05f; protected readonly double? _Average; - protected readonly int? _FaceLocationIndex; + protected readonly int? _NormalizedPixelPercentage; protected readonly bool? _IsWrongYear; protected readonly double? _Minimum; protected readonly DateTime _MinimumDateTime; protected readonly PersonBirthday? _PersonBirthday; public double? Average => _Average; - public int? FaceLocationIndex => _FaceLocationIndex; + public int? NormalizedPixelPercentage => _NormalizedPixelPercentage; public bool? IsWrongYear => _IsWrongYear; public double? Minimum => _Minimum; public DateTime MinimumDateTime => _MinimumDateTime; public PersonBirthday? PersonBirthday => _PersonBirthday; [JsonConstructor] - public Closest(double? average, int? faceLocationIndex, bool? isWrongYear, double? minimum, DateTime minimumDateTime, PersonBirthday? personBirthday) + public Closest(double? average, int? normalizedPixelPercentage, bool? isWrongYear, double? minimum, DateTime minimumDateTime, PersonBirthday? personBirthday) { _Average = average; - _FaceLocationIndex = faceLocationIndex; + _NormalizedPixelPercentage = normalizedPixelPercentage; _IsWrongYear = isWrongYear; _Minimum = minimum; _MinimumDateTime = minimumDateTime; _PersonBirthday = personBirthday; } - public Closest(int? faceLocationIndex, DateTime minimumDateTime, bool? isWrongYear) : - this(null, faceLocationIndex, isWrongYear, null, minimumDateTime, null) + public Closest(int? normalizedPixelPercentage, DateTime minimumDateTime, bool? isWrongYear) : + this(null, normalizedPixelPercentage, isWrongYear, null, minimumDateTime, null) { } - public Closest(int? faceLocationIndex, DateTime minimumDateTime, bool? isWrongYear, PersonBirthday? personBirthday, List faceDistances) : - this(faceDistances.Average(), faceLocationIndex, isWrongYear, faceDistances.Min(), minimumDateTime, personBirthday) + public Closest(int? normalizedPixelPercentage, DateTime minimumDateTime, bool? isWrongYear, PersonBirthday? personBirthday, List faceDistances) : + this(faceDistances.Average(), normalizedPixelPercentage, isWrongYear, faceDistances.Min(), minimumDateTime, personBirthday) { } diff --git a/Property/Models/Item.cs b/Property/Models/Item.cs index 28bb160..aae579b 100644 --- a/Property/Models/Item.cs +++ b/Property/Models/Item.cs @@ -58,6 +58,7 @@ public class Item _Named = new(); _Closest = new(); _Changed = changed; + _Property = property; _Abandoned = abandoned; _NoJson = abandoned is null; _RelativePath = relativePath; @@ -90,43 +91,57 @@ public class Item return result; } - public static void AddToNamed(PropertyLogic propertyLogic, Item[] filteredItems) + public static void AddToNamed(PropertyLogic propertyLogic, List items) { - Item item; bool? isWrongYear; - string[] segments; - string[] personKeys; - double? pixelPercentage; DateTime minimumDateTime; PersonBirthday? personBirthday; - for (int i = 0; i < filteredItems.Length; i++) + float deterministicHashCodeKey; + List personKeys = new(); + foreach (Item item in items) { - item = filteredItems[i]; if (item.ImageFileHolder is null) continue; if (item.Property?.Id is null || item.ResizedFileHolder is null) continue; - if (!propertyLogic.NamedFaceInfoDeterministicHashCodeIds.ContainsKey(item.Property.Id.Value)) - continue; - minimumDateTime = Stateless.A_Property.GetMinimumDateTime(item.Property); - personKeys = propertyLogic.NamedFaceInfoDeterministicHashCodeIds[item.Property.Id.Value]; - (isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime); - for (int j = 0; j < personKeys.Length; j++) + foreach (IFace face in item.Faces) { - segments = Shared.Models.Stateless.Methods.IPersonBirthday.GetSegments(personKeys[j]); - personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKeys[j]); - if (personBirthday is null) + personKeys.Clear(); + if (face.LocationIndex is null) continue; - if (segments.Length <= 1 || !double.TryParse(segments[1], out double value)) - pixelPercentage = null; - else - pixelPercentage = value; - item.Named.Add(new(isWrongYear, minimumDateTime, personBirthday, pixelPercentage)); + deterministicHashCodeKey = Models.Named.GetDeterministicHashCodeKey(item, face); + if (!propertyLogic.NamedDeterministicHashCodeKeyValuePairs.ContainsKey(deterministicHashCodeKey)) + continue; + minimumDateTime = Stateless.A_Property.GetMinimumDateTime(item.Property); + personKeys.AddRange(propertyLogic.NamedDeterministicHashCodeKeyValuePairs[deterministicHashCodeKey]); + (isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime); + for (int i = 0; i < personKeys.Count; i++) + { + personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKeys[i]); + if (personBirthday is null) + continue; + item.Named.Add(new(isWrongYear, minimumDateTime, face.Location.NormalizedPixelPercentage, personBirthday)); + } + } + if (!personKeys.Any()) + { + if (!propertyLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs.ContainsKey(item.Property.Id.Value)) + continue; + minimumDateTime = Stateless.A_Property.GetMinimumDateTime(item.Property); + personKeys.AddRange(propertyLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs[item.Property.Id.Value]); + (isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime); + for (int i = 0; i < personKeys.Count; i++) + { + personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKeys[i]); + if (personBirthday is null) + continue; + item.Named.Add(new(isWrongYear, minimumDateTime, personBirthday)); + } } } } - public static List<(Item, (string, IFace?, (string, string, string, string))[])> GetCollection(PropertyLogic propertyLogic, Item[] filteredItems, string dFacesContentDirectory) + public static List<(Item, (string, IFace?, (string, string, string, string))[])> GetCollection(PropertyLogic propertyLogic, List items, string dFacesContentDirectory) { List<(Item, (string, IFace?, (string, string, string, string))[])> results = new(); Item item; @@ -134,7 +149,6 @@ public class Item string directory; string personKey; bool? isWrongYear; - string[] segments; const int zero = 0; TimeSpan? timeSpan; string copyFileName; @@ -148,13 +162,12 @@ public class Item List faceCollection; PersonBirthday? personBirthday; List<(string, IFace?, (string, string, string, string))> collection; - for (int i = 0; i < filteredItems.Length; i++) + for (int i = 0; i < items.Count; i++) { indices.Clear(); - personKey = string.Empty; copyFileName = string.Empty; copyDirectory = string.Empty; - item = filteredItems[i]; + item = items[i]; if (item.ImageFileHolder is null) continue; relativePath = Path.GetDirectoryName($"C:{item.RelativePath}"); @@ -163,15 +176,16 @@ public class Item if (item.Property?.Id is null || item.ResizedFileHolder is null) continue; collection = new(); - if (!propertyLogic.NamedFaceInfoDeterministicHashCodeIds.ContainsKey(item.Property.Id.Value)) + if (!propertyLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs.ContainsKey(item.Property.Id.Value)) { faceCollection = new(); + personKey = string.Empty; directory = Path.Combine(dFacesContentDirectory, $"Unnamed{relativePath[2..]}"); } else { faceCollection = item.Faces; - keys = propertyLogic.NamedFaceInfoDeterministicHashCodeIds[item.Property.Id.Value]; + keys = propertyLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs[item.Property.Id.Value]; minimumDateTime = Stateless.A_Property.GetMinimumDateTime(item.Property); if (minimumDateTime is null) continue; @@ -179,16 +193,25 @@ public class Item isWrongYearFlag = GetWrongYearFlag(isWrongYear); subDirectoryName = $"{isWrongYearFlag}{minimumDateTime.Value:yyyy}"; if (!faceCollection.Any()) + { + personKey = string.Empty; directory = Path.Combine(dFacesContentDirectory, $"None{relativePath[2..]}", subDirectoryName); + } else if (keys.Length != 1) + { + personKey = string.Empty; directory = Path.Combine(dFacesContentDirectory, $"Not Supported{relativePath[2..]}", subDirectoryName); + } else if (faceCollection.Count != 1) + { + personKey = string.Empty; directory = Path.Combine(dFacesContentDirectory, $"Many{relativePath[2..]}", subDirectoryName); + } else { indices.Add(zero); - segments = Shared.Models.Stateless.Methods.IPersonBirthday.GetSegments(keys[zero]); - personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(keys[zero]); + personKey = keys[zero]; + personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKey); if (personBirthday is null) continue; timeSpan = Shared.Models.Stateless.Methods.IPersonBirthday.GetTimeSpan(minimumDateTime.Value, isWrongYear, personBirthday); @@ -199,7 +222,6 @@ public class Item else subDirectoryName = $"^{Math.Floor(timeSpan.Value.TotalDays / 365):000}"; } - personKey = segments[zero]; directory = Path.Combine(dFacesContentDirectory, "Shortcuts", personKey, subDirectoryName); if (faceCollection[zero].Populated) copyDirectory = Path.Combine(dFacesContentDirectory, "Images", personKey, subDirectoryName); @@ -270,7 +292,7 @@ public class Item continue; foreach (Named named in item.Named) { - if (named.PixelPercentage is null && (item.Named.Count != 1 || item.Faces.Count != 1)) + if (named.NormalizedPixelPercentage is null && (item.Named.Count != 1 || item.Faces.Count != 1)) continue; foreach (IFace face in item.Faces) { @@ -278,13 +300,13 @@ public class Item continue; if (named.PersonBirthday is null) continue; - if (named.PixelPercentage.HasValue && named.PixelPercentage.Value != face.Location.PixelPercentage) + if (named.NormalizedPixelPercentage.HasValue && named.NormalizedPixelPercentage.Value != face.Location.NormalizedPixelPercentage) continue; key = GetKey(named.MinimumDateTime, named.IsWrongYear, named.PersonBirthday); if (!results.ContainsKey(key)) results.Add(key, new()); results[key].Add(new(named.MinimumDateTime, named.IsWrongYear, named.PersonBirthday, face)); - if (named.PixelPercentage is null) + if (named.NormalizedPixelPercentage is null) break; } } diff --git a/Property/Models/Named.cs b/Property/Models/Named.cs index d7d73be..27ea279 100644 --- a/Property/Models/Named.cs +++ b/Property/Models/Named.cs @@ -1,5 +1,6 @@ using System.Text.Json.Serialization; using View_by_Distance.Shared.Models; +using View_by_Distance.Shared.Models.Properties; namespace View_by_Distance.Property.Models; @@ -8,20 +9,77 @@ public class Named protected readonly bool? _IsWrongYear; protected readonly DateTime _MinimumDateTime; + protected readonly int? _NormalizedPixelPercentage; protected readonly PersonBirthday? _PersonBirthday; - protected readonly double? _PixelPercentage; public bool? IsWrongYear => _IsWrongYear; public DateTime MinimumDateTime => _MinimumDateTime; + public int? NormalizedPixelPercentage => _NormalizedPixelPercentage; public PersonBirthday? PersonBirthday => _PersonBirthday; - public double? PixelPercentage => _PixelPercentage; [JsonConstructor] - public Named(bool? isWrongYear, DateTime minimumDateTime, PersonBirthday? personBirthday, double? pixelPercentage) + public Named(bool? isWrongYear, DateTime minimumDateTime, int? normalizedPixelPercentage, PersonBirthday? personBirthday) { _IsWrongYear = isWrongYear; _MinimumDateTime = minimumDateTime; + _NormalizedPixelPercentage = normalizedPixelPercentage; _PersonBirthday = personBirthday; - _PixelPercentage = pixelPercentage; + } + + public Named(bool? isWrongYear, DateTime minimumDateTime, PersonBirthday? personBirthday) : + this(isWrongYear, minimumDateTime, null, personBirthday) + { } + + private static float GetDeterministicHashCodeFileName(int id, int normalizedPixelPercentage) + => float.Parse($"{id}.{normalizedPixelPercentage}"); + + public static float GetDeterministicHashCodeKey(Item item, Closest closest) + { + float result; + if (item.Property?.Id is null || item.ImageFileHolder is null || closest.NormalizedPixelPercentage is null) + throw new NullReferenceException(); + result = GetDeterministicHashCodeFileName(item.Property.Id.Value, closest.NormalizedPixelPercentage.Value); + return result; + } + + public static float GetDeterministicHashCodeKey(Item item, IFace face) + { + float result; + if (item.Property?.Id is null || item.ImageFileHolder is null || face.Location?.NormalizedPixelPercentage is null) + throw new NullReferenceException(); + result = GetDeterministicHashCodeFileName(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value); + return result; + } + + public static float? GetReversedDeterministicHashCode(Dictionary> keyValuePairs, string fileName) + { + float? result; + string[] segments = fileName.Split('.'); + if (segments.Length < 2) + throw new Exception(); + string id = segments[0]; + string normalizedPixelPercentage; + if (!id.Contains('-')) + normalizedPixelPercentage = segments[1]; + else + { + segments = fileName.Split(' '); + if (segments.Length < 3) + throw new Exception(); + id = segments[2]; + string locationIdex = segments[0]; + if (int.TryParse(id, out int idValue) && int.TryParse(locationIdex, out int locationIndexValue) && keyValuePairs.ContainsKey(idValue) && keyValuePairs[idValue].Count > locationIndexValue) + normalizedPixelPercentage = string.Concat(keyValuePairs[idValue][locationIndexValue].Location.NormalizedPixelPercentage); + else + { + id = string.Empty; + normalizedPixelPercentage = string.Empty; + } + } + if (!float.TryParse(string.Concat(id, '.', normalizedPixelPercentage), out float resultValue)) + result = null; + else + result = resultValue; + return result; } } \ No newline at end of file diff --git a/Property/Models/PropertyLogic.cs b/Property/Models/PropertyLogic.cs index aac479f..633c119 100644 --- a/Property/Models/PropertyLogic.cs +++ b/Property/Models/PropertyLogic.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Text; using System.Text.Json; using View_by_Distance.Property.Models.Stateless; +using View_by_Distance.Shared.Models.Properties; using View_by_Distance.Shared.Models.Stateless; namespace View_by_Distance.Property.Models; @@ -18,17 +19,21 @@ public class PropertyLogic protected readonly List _ExceptionsDirectories; protected readonly Dictionary _KeyValuePairs; protected readonly Dictionary _IndicesFromNew; + protected readonly string _DeterministicHashCodeRootDirectory; protected readonly Dictionary _SixCharacterNamedFaceInfo; - protected readonly List _NamedDeterministicHashCodeIdAndFaceLocationIndex; - protected readonly Dictionary _NamedFaceInfoDeterministicHashCodeIds; + protected readonly Dictionary _NamedFaceInfoDeterministicHashCodeKeyValuePairs; + protected readonly Dictionary _NamedDeterministicHashCodeKeyValuePairs; + protected readonly Dictionary _IncorrectDeterministicHashCodeKeyValuePairs; public bool Reverse { get; } public List AngleBracketCollection { get; } public Dictionary KeyValuePairs => _KeyValuePairs; public Dictionary IndicesFromNew => _IndicesFromNew; public List ExceptionsDirectories => _ExceptionsDirectories; - public Dictionary NamedFaceInfoDeterministicHashCodeIds => _NamedFaceInfoDeterministicHashCodeIds; - public List NamedDeterministicHashCodeIdAndFaceLocationIndex => _NamedDeterministicHashCodeIdAndFaceLocationIndex; + public string DeterministicHashCodeRootDirectory => _DeterministicHashCodeRootDirectory; + public Dictionary NamedDeterministicHashCodeKeyValuePairs => _NamedDeterministicHashCodeKeyValuePairs; + public Dictionary IncorrectDeterministicHashCodeKeyValuePairs => _IncorrectDeterministicHashCodeKeyValuePairs; + public Dictionary NamedFaceInfoDeterministicHashCodeKeyValuePairs => _NamedFaceInfoDeterministicHashCodeKeyValuePairs; private readonly Model? _Model; private readonly Serilog.ILogger? _Log; @@ -51,7 +56,7 @@ public class PropertyLogic AngleBracketCollection = new List(); _Log = Serilog.Log.ForContext(); _MaxDegreeOfParallelism = maxDegreeOfParallelism; - Dictionary? namedFaceInfoDeterministicHashCodeIndices; + Dictionary? namedFaceInfoDeterministicHashCode; _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; if (configuration.VerifyToSeason is null || !configuration.VerifyToSeason.Any()) throw new Exception(); @@ -59,41 +64,29 @@ public class PropertyLogic string json; string[] files; string fullPath; - List namedDeterministicHashCodeIdAndFaceLocationIndex = new(); Dictionary? keyValuePairs; + string deterministicHashCodeRootDirectory; List>? collection; Dictionary indicesFromNew = new(); Dictionary? sixCharacterNamedFaceInfo; + Dictionary namedDeterministicHashCode = new(); + Dictionary incorrectDeterministicHashCode = new(); string? rootDirectoryParent = Path.GetDirectoryName(configuration.RootDirectory); if (string.IsNullOrEmpty(rootDirectoryParent)) throw new NullReferenceException(nameof(rootDirectoryParent)); files = Directory.GetFiles(rootDirectoryParent, "*DeterministicHashCode*.json", SearchOption.TopDirectoryOnly); if (files.Length != 1) - namedFaceInfoDeterministicHashCodeIndices = new(); + namedFaceInfoDeterministicHashCode = new(); else { json = File.ReadAllText(files[0]); - namedFaceInfoDeterministicHashCodeIndices = JsonSerializer.Deserialize>(json); - if (namedFaceInfoDeterministicHashCodeIndices is null) - throw new NullReferenceException(nameof(namedFaceInfoDeterministicHashCodeIndices)); + namedFaceInfoDeterministicHashCode = JsonSerializer.Deserialize>(json); + if (namedFaceInfoDeterministicHashCode is null) + throw new NullReferenceException(nameof(namedFaceInfoDeterministicHashCode)); } - if (namedFaceInfoDeterministicHashCodeIndices.Any()) - { - sixCharacterNamedFaceInfo = new(); - string[] directories = Directory.GetDirectories(rootDirectoryParent, "*DeterministicHashCode*", SearchOption.TopDirectoryOnly); - if (directories.Any()) - { - Dictionary ticksKeyValuePairs = GetKeyValuePairs(namedDeterministicHashCodeIdAndFaceLocationIndex, directories[0]); - foreach (KeyValuePair keyValuePair in ticksKeyValuePairs) - { - if (namedFaceInfoDeterministicHashCodeIndices.ContainsKey(keyValuePair.Key)) - continue; - namedFaceInfoDeterministicHashCodeIndices.Add(keyValuePair.Key, keyValuePair.Value); - } - } - } - else + if (namedFaceInfoDeterministicHashCode.Any()) { + deterministicHashCodeRootDirectory = string.Empty; files = Directory.GetFiles(rootDirectoryParent, "*SixCharacter*.json", SearchOption.TopDirectoryOnly); if (files.Length != 1) sixCharacterNamedFaceInfo = new(); @@ -105,6 +98,19 @@ public class PropertyLogic throw new NullReferenceException(nameof(sixCharacterNamedFaceInfo)); } } + else + { + sixCharacterNamedFaceInfo = new(); + string[] directories = Directory.GetDirectories(rootDirectoryParent, "*DeterministicHashCode*", SearchOption.TopDirectoryOnly); + if (!directories.Any()) + deterministicHashCodeRootDirectory = string.Empty; + else + { + Dictionary> faces = new(); + deterministicHashCodeRootDirectory = directories[0]; + SetKeyValuePairs(deterministicHashCodeRootDirectory, namedDeterministicHashCode, incorrectDeterministicHashCode, faces); + } + } files = Directory.GetFiles(rootDirectoryParent, "*keyValuePairs*.json", SearchOption.TopDirectoryOnly); if (files.Length != 1) keyValuePairs = new(); @@ -133,26 +139,25 @@ public class PropertyLogic indicesFromNew.Add(keyValuePair.Key, keyValuePair.Value); } } - _NamedDeterministicHashCodeIdAndFaceLocationIndex = namedDeterministicHashCodeIdAndFaceLocationIndex; _KeyValuePairs = keyValuePairs; _IndicesFromNew = indicesFromNew; _SixCharacterNamedFaceInfo = sixCharacterNamedFaceInfo; - _NamedFaceInfoDeterministicHashCodeIds = namedFaceInfoDeterministicHashCodeIndices; + _NamedDeterministicHashCodeKeyValuePairs = namedDeterministicHashCode; + _DeterministicHashCodeRootDirectory = deterministicHashCodeRootDirectory; + _IncorrectDeterministicHashCodeKeyValuePairs = incorrectDeterministicHashCode; + _NamedFaceInfoDeterministicHashCodeKeyValuePairs = namedFaceInfoDeterministicHashCode; } - private static Dictionary GetKeyValuePairs(List namedDeterministicHashCodeIdAndFaceLocationIndex, string rootDirectory) + private static void SetKeyValuePairs(string deterministicHashCodeRootDirectory, List<(string, float)> named, List<(string, float)> incorrect, Dictionary> keyValuePairs) { - Dictionary results = new(); - string id; string[] files; + string fileName; string personKey; - string[] segments; - string faceLocationIndex; string[] yearDirectories; string[] personKeyDirectories; string[] personNameDirectories; - string fileNameWithoutExtension; - string[] ticksDirectories = Directory.GetDirectories(rootDirectory, "*", SearchOption.TopDirectoryOnly); + float? idAndNormalizedPixelPercentage; + string[] ticksDirectories = Directory.GetDirectories(deterministicHashCodeRootDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string ticksDirectory in ticksDirectories) { if (!ticksDirectory.EndsWith(')')) @@ -164,7 +169,18 @@ public class PropertyLogic yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string yearDirectory in yearDirectories) { + files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly); personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string file in files) + { + if (file.EndsWith(".lnk")) + continue; + fileName = Path.GetFileName(file); + idAndNormalizedPixelPercentage = Named.GetReversedDeterministicHashCode(keyValuePairs, fileName); + if (idAndNormalizedPixelPercentage is null) + break; + incorrect.Add(new(personKey, idAndNormalizedPixelPercentage.Value)); + } foreach (string personNameDirectory in personNameDirectories) { files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly); @@ -172,24 +188,64 @@ public class PropertyLogic { if (file.EndsWith(".lnk")) continue; - fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); - segments = fileNameWithoutExtension.Split(' '); - if (segments.Length < 2) - continue; - id = segments[2]; - faceLocationIndex = segments[0]; - if (!int.TryParse(id, out int idValue)) - continue; - namedDeterministicHashCodeIdAndFaceLocationIndex.Add(fileNameWithoutExtension); - if (results.ContainsKey(idValue)) - continue; - results.Add(idValue, new string[] { personKey }); + fileName = Path.GetFileNameWithoutExtension(file); + idAndNormalizedPixelPercentage = Named.GetReversedDeterministicHashCode(keyValuePairs, fileName); + if (idAndNormalizedPixelPercentage is null) + break; + named.Add(new(personKey, idAndNormalizedPixelPercentage.Value)); } } } } } - return results; + } + + private static void SetKeyValuePairs(string deterministicHashCodeRootDirectory, Dictionary namedDeterministicHashCode, Dictionary incorrectDeterministicHashCode, Dictionary> keyValuePairs) + { + Dictionary> namedKeyValuePairs = new(); + Dictionary> incorrectKeyValuePairs = new(); + List<(string PersonKey, float IdAndNormalizedPixelPercentage)> named = new(); + List<(string PersonKey, float IdAndNormalizedPixelPercentage)> incorrect = new(); + SetKeyValuePairs(deterministicHashCodeRootDirectory, named, incorrect, keyValuePairs); + named = (from l in named orderby l.IdAndNormalizedPixelPercentage select l).ToList(); + incorrect = (from l in incorrect orderby l.IdAndNormalizedPixelPercentage select l).ToList(); + foreach ((string personKey, float idAndNormalizedPixelPercentage) in named) + { + if (!namedKeyValuePairs.ContainsKey(idAndNormalizedPixelPercentage)) + namedKeyValuePairs.Add(idAndNormalizedPixelPercentage, new()); + namedKeyValuePairs[idAndNormalizedPixelPercentage].Add(personKey); + } + foreach ((string personKey, float idAndNormalizedPixelPercentage) in incorrect) + { + if (!incorrectKeyValuePairs.ContainsKey(idAndNormalizedPixelPercentage)) + incorrectKeyValuePairs.Add(idAndNormalizedPixelPercentage, new()); + incorrectKeyValuePairs[idAndNormalizedPixelPercentage].Add(personKey); + } + foreach (KeyValuePair> keyValuePair in namedKeyValuePairs) + namedDeterministicHashCode.Add(keyValuePair.Key, keyValuePair.Value.Distinct().ToArray()); + foreach (KeyValuePair> keyValuePair in incorrectKeyValuePairs) + incorrectDeterministicHashCode.Add(keyValuePair.Key, keyValuePair.Value.Distinct().ToArray()); + } + + public void UpdateKeyValuePairs(List containers) + { + Dictionary> keyValuePairs = new(); + Dictionary namedDeterministicHashCode = new(); + Dictionary incorrectDeterministicHashCode = new(); + foreach (Container container in containers) + { + foreach (Item item in container.Items) + { + if (item.ImageFileHolder is null || item.Property?.Id is null || !item.Faces.Any()) + continue; + keyValuePairs.Add(item.Property.Id.Value, item.Faces); + } + } + SetKeyValuePairs(_DeterministicHashCodeRootDirectory, namedDeterministicHashCode, incorrectDeterministicHashCode, keyValuePairs); + foreach (KeyValuePair keyValuePair in namedDeterministicHashCode) + _NamedDeterministicHashCodeKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value); + foreach (KeyValuePair keyValuePair in incorrectDeterministicHashCode) + _IncorrectDeterministicHashCodeKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value); } public override string ToString() diff --git a/Property/Models/Stateless/Container.cs b/Property/Models/Stateless/Container.cs index 8cb82ea..881a1ad 100644 --- a/Property/Models/Stateless/Container.cs +++ b/Property/Models/Stateless/Container.cs @@ -13,7 +13,7 @@ public class Container string[] sourceDirectoryFiles; List fileCollections = new(); if (!topDirectories.Any()) - topDirectories.AddRange(from l in Directory.GetDirectories(rootDirectory, "*", SearchOption.TopDirectoryOnly) select Path.GetFullPath(l)); + topDirectories.AddRange(from l in Directory.GetDirectories(rootDirectory, "*", SearchOption.TopDirectoryOnly) orderby Path.GetFileName(l)[..1], l select Path.GetFullPath(l)); for (int g = 1; g < 5; g++) { if (g == 4) diff --git a/Resize/Models/_C_Resize.cs b/Resize/Models/_C_Resize.cs index f8c6a4d..e5337fa 100644 --- a/Resize/Models/_C_Resize.cs +++ b/Resize/Models/_C_Resize.cs @@ -300,8 +300,10 @@ public class C_Resize return results; } - public void SaveResizedSubfile(string outputResolution, string cResultsFullGroupDirectory, List> subFileTuples, Item item, string original, A_Property property, Dictionary imageResizes) + public void SaveResizedSubfile(string outputResolution, string cResultsFullGroupDirectory, List> subFileTuples, Item item, string original, Dictionary imageResizes) { + if (item.Property is null) + throw new NullReferenceException(nameof(item.Property)); if (item.ImageFileHolder is null) throw new NullReferenceException(nameof(item.ImageFileHolder)); if (item.ResizedFileHolder is null) @@ -347,7 +349,7 @@ public class C_Resize check = true; if (check) { - _ = SaveResizedSubfile(item.ImageFileHolder.FullName, property, resize, fileHolder); + _ = SaveResizedSubfile(item.ImageFileHolder.FullName, item.Property, resize, fileHolder); subFileTuples.Add(new Tuple(nameof(C_Resize), DateTime.Now)); } } @@ -422,7 +424,7 @@ public class C_Resize return results; } - public Dictionary GetResizeKeyValuePairs(string cResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, string original, List> metadataCollection, A_Property property, Item item) + public Dictionary GetResizeKeyValuePairs(string cResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, string original, List> metadataCollection, Item item) { Dictionary results; if (item.Property?.Id is null) @@ -484,7 +486,7 @@ public class C_Resize results = keyValuePairs; if ((from l in results where l.Value[0] == l.Value[1] select true).Any()) { - results = GetImageResizes(property, metadataCollection, original); + results = GetImageResizes(item.Property, metadataCollection, original); if (!(from l in results where l.Value[0] == l.Value[1] select true).Any()) throw new Exception("Was square!"); } @@ -498,7 +500,7 @@ public class C_Resize } if (results is null || !results.Any()) { - results = GetImageResizes(property, metadataCollection, original); + results = GetImageResizes(item.Property, metadataCollection, original); json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); diff --git a/Shared/Models/Location.cs b/Shared/Models/Location.cs index e52213c..5ea0b78 100644 --- a/Shared/Models/Location.cs +++ b/Shared/Models/Location.cs @@ -7,40 +7,40 @@ namespace View_by_Distance.Shared.Models; public class Location : Properties.ILocation, ILocation, IEquatable { - public double Confidence => _Confidence; - protected double _Confidence; protected int _Bottom; + protected double _Confidence; protected int _Left; - protected double? _PixelPercentage; + protected readonly int? _NormalizedPixelPercentage; protected int _Right; protected int _Top; public int Bottom => _Bottom; + public double Confidence => _Confidence; public int Left => _Left; - public double? PixelPercentage => _PixelPercentage; + public int? NormalizedPixelPercentage => _NormalizedPixelPercentage; public int Right => _Right; public int Top => _Top; [JsonConstructor] - public Location(double confidence, int bottom, int left, double? pixelPercentage, int right, int top) + public Location(int bottom, double confidence, int left, int? normalizedPixelPercentage, int right, int top) { _Confidence = confidence; _Bottom = bottom; _Left = left; - _PixelPercentage = pixelPercentage; + _NormalizedPixelPercentage = normalizedPixelPercentage; _Right = right; _Top = top; } public Location(double confidence, int bottom, int left, int right, int top, int width, int height) : - this(confidence, bottom, left, GetPixelPercentage(bottom, left, right, top, width, height), right, top) + this(bottom, confidence, left, GetNormalizedPixelPercentage(bottom, height, left, right, top, width), right, top) { } public Location(double confidence, Location location, int width, int height) : - this(confidence, location.Bottom, location.Left, location.Right, location.Top, width, height) + this(location.Bottom, confidence, location.Left, GetNormalizedPixelPercentage(location.Bottom, height, location.Left, location.Right, location.Top, width), location.Right, location.Top) { } public Location(int left, int top, int right, int bottom, int width, int height) : - this(-1.0d, bottom, left, right, top, width, height) + this(bottom, -1.0d, left, GetNormalizedPixelPercentage(bottom, height, left, right, top, width), right, top) { } public override bool Equals(object? obj) => Equals(obj as Location); @@ -61,13 +61,13 @@ public class Location : Properties.ILocation, ILocation, IEquatable return hashCode; } - public static double GetPixelPercentage(int left, int top, int right, int bottom, int width, int height) + public static int GetNormalizedPixelPercentage(int bottom, int height, int left, int right, int top, int width) { double result; double xCenter = left + ((right - left) / 2); double yCenter = top + ((bottom - top) / 2); result = ((yCenter * width) + xCenter) / (width * height); - return (double)Math.Round((decimal)result, 4); + return (int)(Math.Round((decimal)result, 4) * Stateless.Methods.ILocation.Factor); } public bool Equals(Location? location) diff --git a/Shared/Models/Properties/ILocation.cs b/Shared/Models/Properties/ILocation.cs index d404ace..2d8c9c9 100644 --- a/Shared/Models/Properties/ILocation.cs +++ b/Shared/Models/Properties/ILocation.cs @@ -3,9 +3,10 @@ namespace View_by_Distance.Shared.Models.Properties; public interface ILocation { - public double Confidence { get; } public int Bottom { get; } + public double Confidence { get; } public int Left { get; } + public int? NormalizedPixelPercentage { get; } public int Right { get; } public int Top { get; } diff --git a/Shared/Models/Stateless/Methods/ILocation.cs b/Shared/Models/Stateless/Methods/ILocation.cs new file mode 100644 index 0000000..f4dfec0 --- /dev/null +++ b/Shared/Models/Stateless/Methods/ILocation.cs @@ -0,0 +1,8 @@ +namespace View_by_Distance.Shared.Models.Stateless.Methods; + +public interface ILocation +{ // ... + + public const int Factor = 10000; + +} \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPersonBirthday.cs b/Shared/Models/Stateless/Methods/IPersonBirthday.cs index ef6f60f..a7b51bf 100644 --- a/Shared/Models/Stateless/Methods/IPersonBirthday.cs +++ b/Shared/Models/Stateless/Methods/IPersonBirthday.cs @@ -12,9 +12,6 @@ public interface IPersonBirthday string TestStatic_GetFormat() => PersonBirthday.GetFormat(); static string GetFormat() => PersonBirthday.GetFormat(); - string[] TestStatic_GetSegments(string personKey) => PersonBirthday.GetSegments(personKey); - static string[] GetSegments(string personKey) => PersonBirthday.GetSegments(personKey); - DateTime? TestStatic_GetDateTime(string personKey) => PersonBirthday.GetDateTime(personKey); static DateTime? GetDateTime(string personKey) => PersonBirthday.GetDateTime(personKey); diff --git a/Shared/Models/Stateless/Methods/PersonBirthday.cs b/Shared/Models/Stateless/Methods/PersonBirthday.cs index 985f7ca..077df35 100644 --- a/Shared/Models/Stateless/Methods/PersonBirthday.cs +++ b/Shared/Models/Stateless/Methods/PersonBirthday.cs @@ -10,7 +10,6 @@ internal abstract class PersonBirthday // ... internal static string GetFormat() => "yyyy-MM-dd_HH"; - internal static string[] GetSegments(string personKey) => personKey.Split('\t'); internal static string GetFormatted(Models.PersonBirthday personBirthday) => personBirthday.Value.ToString(GetFormat()); internal static string GetFileName(Models.PersonBirthday personBirthday) => $"{personBirthday.Value.ToString(GetFormat())}.json"; internal static bool DoesBirthDateExits(Properties.IStorage storage, Models.PersonBirthday personBirthday) => File.Exists(GetFileFullName(storage, personBirthday)); @@ -21,8 +20,7 @@ internal abstract class PersonBirthday internal static Models.PersonBirthday? GetPersonBirthday(string personKey) { Models.PersonBirthday? result; - string[] segments = GetSegments(personKey); - DateTime? dateTime = GetDateTime(segments[0]); + DateTime? dateTime = GetDateTime(personKey); if (dateTime is null) result = null; else diff --git a/Tests/Models/AppSettings.cs b/Tests/Models/AppSettings.cs index 86d6f6a..ff0c37b 100644 --- a/Tests/Models/AppSettings.cs +++ b/Tests/Models/AppSettings.cs @@ -6,24 +6,16 @@ namespace View_by_Distance.Tests.Models; public class AppSettings { - protected string _Company; - protected string _WorkingDirectoryName; - protected int? _MaxDegreeOfParallelism; - public string Company => _Company; - public string WorkingDirectoryName => _WorkingDirectoryName; - public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism; - - // public AppSettings() - // { - - // } + public string Company { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string WorkingDirectoryName { init; get; } [JsonConstructor] - public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism) + public AppSettings(string company, int maxDegreeOfParallelism, string workingDirectoryName) { - _Company = company; - _WorkingDirectoryName = workingDirectoryName; - _MaxDegreeOfParallelism = maxDegreeOfParallelism; + Company = company; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + WorkingDirectoryName = workingDirectoryName; } public override string ToString() diff --git a/Tests/Models/Binder/AppSettings.cs b/Tests/Models/Binder/AppSettings.cs index 94e3cc6..2167e26 100644 --- a/Tests/Models/Binder/AppSettings.cs +++ b/Tests/Models/Binder/AppSettings.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Configuration; using System.Text.Json; namespace View_by_Distance.Tests.Models.Binder; @@ -6,16 +6,13 @@ namespace View_by_Distance.Tests.Models.Binder; public class AppSettings { - [Display(Name = "Company"), Required] public string Company { get; set; } - [Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; } - [Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; } +#nullable disable - public AppSettings() - { - Company = string.Empty; - WorkingDirectoryName = string.Empty; - MaxDegreeOfParallelism = -1; - } + public string Company { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string WorkingDirectoryName { get; set; } + +#nullable restore public override string ToString() { @@ -23,4 +20,25 @@ public class AppSettings return result; } + private static Models.AppSettings Get(AppSettings appSettings) + { + Models.AppSettings result; + if (appSettings.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + result = new( + appSettings.Company, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + } \ No newline at end of file diff --git a/Tests/Models/Stateless/AppSettings.cs b/Tests/Models/Stateless/AppSettings.cs deleted file mode 100644 index 8ae31f1..0000000 --- a/Tests/Models/Stateless/AppSettings.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.Extensions.Configuration; -using System.Text.Json; - -namespace View_by_Distance.Tests.Models.Stateless; - -public abstract class AppSettings -{ - - public static Models.AppSettings Get(IConfigurationRoot configurationRoot) - { - Models.AppSettings? result; - Binder.AppSettings appSettings = configurationRoot.Get(); - string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true }); - result = JsonSerializer.Deserialize(json); - if (result is null) - throw new Exception(json); - if (string.IsNullOrEmpty(result.Company)) - throw new Exception(json); - string jsonThis = result.ToString(); - if (jsonThis != json) - { - int? check = null; - int min = new int[] { json.Length, jsonThis.Length }.Min(); - for (int i = 0; i < min; i++) - { - if (json[i] == jsonThis[i]) - continue; - check = i; - break; - } - if (check is null) - throw new Exception(); - string a = json[..check.Value].Split(',')[^1]; - string b = json[check.Value..].Split(',')[0]; - throw new Exception($"{a}{b}"); - } - return result; - } - -} \ No newline at end of file diff --git a/Tests/UnitTestExample.cs b/Tests/UnitTestExample.cs index ccc67b2..e9deb2e 100644 --- a/Tests/UnitTestExample.cs +++ b/Tests/UnitTestExample.cs @@ -38,7 +38,7 @@ public class UnitTestExample .AddEnvironmentVariables() .AddJsonFile(isEnvironment.AppSettingsFileName); configurationRoot = configurationBuilder.Build(); - appSettings = Models.Stateless.AppSettings.Get(configurationRoot); + appSettings = Models.Binder.AppSettings.Get(configurationRoot); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); diff --git a/Tests/UnitTestResize.cs b/Tests/UnitTestResize.cs index 8709879..7f59417 100644 --- a/Tests/UnitTestResize.cs +++ b/Tests/UnitTestResize.cs @@ -42,7 +42,7 @@ public class UnitTestResize .AddEnvironmentVariables() .AddJsonFile(isEnvironment.AppSettingsFileName); configurationRoot = configurationBuilder.Build(); - appSettings = Models.Stateless.AppSettings.Get(configurationRoot); + appSettings = Models.Binder.AppSettings.Get(configurationRoot); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); @@ -75,11 +75,9 @@ public class UnitTestResize private Property.Models.PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel) { Property.Models.PropertyLogic result; - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); if (_Configuration?.PropertyConfiguration is null) throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, reverse, model, predictorModel); + result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, reverse, model, predictorModel); return result; } @@ -161,12 +159,16 @@ public class UnitTestResize sourceDirectory = Path.Combine(aPropertySingletonDirectory, sourceDirectoryName); item = new(sourceDirectoryFile, relativePath, fileHolder, isValidImageFormatExtension, property, false, false); Assert.IsNotNull(item.ImageFileHolder); - property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions); + if (item.Property is null) + { + property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions); + item.Update(property); + } (int _, metadataCollection) = metadata.GetMetadataCollection(bResultsFullGroupDirectory, subFileTuples, parseExceptions, item); - imageResizeKeyValuePairs = resize.GetResizeKeyValuePairs(cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, property, item); + imageResizeKeyValuePairs = resize.GetResizeKeyValuePairs(cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, item); Property.Models.FileHolder resizedFileHolder = new(Path.Combine(resize.AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(item.ImageFileHolder.FullName))); item.SetResizedFileHolder(resizedFileHolder); - resize.SaveResizedSubfile(outputResolution, cResultsFullGroupDirectory, subFileTuples, item, original, property, imageResizeKeyValuePairs); + resize.SaveResizedSubfile(outputResolution, cResultsFullGroupDirectory, subFileTuples, item, original, imageResizeKeyValuePairs); item.SetResizedFileHolder(Property.Models.FileHolder.Refresh(resizedFileHolder)); } diff --git a/TestsWithFaceRecognitionDotNet/Models/AppSettings.cs b/TestsWithFaceRecognitionDotNet/Models/AppSettings.cs index 7399204..246901f 100644 --- a/TestsWithFaceRecognitionDotNet/Models/AppSettings.cs +++ b/TestsWithFaceRecognitionDotNet/Models/AppSettings.cs @@ -6,24 +6,16 @@ namespace View_by_Distance.TestsWithFaceRecognitionDotNet.Models; public class AppSettings { - protected string _Company; - protected string _WorkingDirectoryName; - protected int? _MaxDegreeOfParallelism; - public string Company => _Company; - public string WorkingDirectoryName => _WorkingDirectoryName; - public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism; - - // public AppSettings() - // { - - // } + public string Company { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string WorkingDirectoryName { init; get; } [JsonConstructor] - public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism) + public AppSettings(string company, int maxDegreeOfParallelism, string workingDirectoryName) { - _Company = company; - _WorkingDirectoryName = workingDirectoryName; - _MaxDegreeOfParallelism = maxDegreeOfParallelism; + Company = company; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + WorkingDirectoryName = workingDirectoryName; } public override string ToString() diff --git a/TestsWithFaceRecognitionDotNet/Models/Binder/AppSettings.cs b/TestsWithFaceRecognitionDotNet/Models/Binder/AppSettings.cs index 7019998..534037d 100644 --- a/TestsWithFaceRecognitionDotNet/Models/Binder/AppSettings.cs +++ b/TestsWithFaceRecognitionDotNet/Models/Binder/AppSettings.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Configuration; using System.Text.Json; namespace View_by_Distance.TestsWithFaceRecognitionDotNet.Models.Binder; @@ -6,16 +6,13 @@ namespace View_by_Distance.TestsWithFaceRecognitionDotNet.Models.Binder; public class AppSettings { - [Display(Name = "Company"), Required] public string Company { get; set; } - [Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; } - [Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; } +#nullable disable - public AppSettings() - { - Company = string.Empty; - WorkingDirectoryName = string.Empty; - MaxDegreeOfParallelism = -1; - } + public string Company { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string WorkingDirectoryName { get; set; } + +#nullable restore public override string ToString() { @@ -23,4 +20,25 @@ public class AppSettings return result; } + private static Models.AppSettings Get(AppSettings appSettings) + { + Models.AppSettings result; + if (appSettings.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + result = new( + appSettings.Company, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + } \ No newline at end of file diff --git a/TestsWithFaceRecognitionDotNet/Models/Stateless/AppSettings.cs b/TestsWithFaceRecognitionDotNet/Models/Stateless/AppSettings.cs deleted file mode 100644 index b32222d..0000000 --- a/TestsWithFaceRecognitionDotNet/Models/Stateless/AppSettings.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.Extensions.Configuration; -using System.Text.Json; - -namespace View_by_Distance.TestsWithFaceRecognitionDotNet.Models.Stateless; - -public abstract class AppSettings -{ - - public static Models.AppSettings Get(IConfigurationRoot configurationRoot) - { - Models.AppSettings? result; - Binder.AppSettings appSettings = configurationRoot.Get(); - string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true }); - result = JsonSerializer.Deserialize(json); - if (result is null) - throw new Exception(json); - if (string.IsNullOrEmpty(result.Company)) - throw new Exception(json); - string jsonThis = result.ToString(); - if (jsonThis != json) - { - int? check = null; - int min = new int[] { json.Length, jsonThis.Length }.Min(); - for (int i = 0; i < min; i++) - { - if (json[i] == jsonThis[i]) - continue; - check = i; - break; - } - if (check is null) - throw new Exception(); - string a = json[..check.Value].Split(',')[^1]; - string b = json[check.Value..].Split(',')[0]; - throw new Exception($"{a}{b}"); - } - return result; - } - -} \ No newline at end of file diff --git a/TestsWithFaceRecognitionDotNet/TestsWithFaceRecognitionDotNet.csproj b/TestsWithFaceRecognitionDotNet/TestsWithFaceRecognitionDotNet.csproj index acb603a..dde47fe 100644 --- a/TestsWithFaceRecognitionDotNet/TestsWithFaceRecognitionDotNet.csproj +++ b/TestsWithFaceRecognitionDotNet/TestsWithFaceRecognitionDotNet.csproj @@ -7,6 +7,11 @@ win-x64 net6.0 + + trx + XPlat Code Coverage + ../.vscode/TestResults + true true diff --git a/TestsWithFaceRecognitionDotNet/UnitTestExample.cs b/TestsWithFaceRecognitionDotNet/UnitTestExample.cs index 6ae182f..7533929 100644 --- a/TestsWithFaceRecognitionDotNet/UnitTestExample.cs +++ b/TestsWithFaceRecognitionDotNet/UnitTestExample.cs @@ -38,7 +38,7 @@ public class UnitTestExample .AddEnvironmentVariables() .AddJsonFile(isEnvironment.AppSettingsFileName); configurationRoot = configurationBuilder.Build(); - appSettings = Models.Stateless.AppSettings.Get(configurationRoot); + appSettings = Models.Binder.AppSettings.Get(configurationRoot); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); diff --git a/TestsWithFaceRecognitionDotNet/UnitTestFace.cs b/TestsWithFaceRecognitionDotNet/UnitTestFace.cs index ab2d4d1..060ba98 100644 --- a/TestsWithFaceRecognitionDotNet/UnitTestFace.cs +++ b/TestsWithFaceRecognitionDotNet/UnitTestFace.cs @@ -44,7 +44,7 @@ public class UnitTestFace .AddEnvironmentVariables() .AddJsonFile(isEnvironment.AppSettingsFileName); configurationRoot = configurationBuilder.Build(); - appSettings = Models.Stateless.AppSettings.Get(configurationRoot); + appSettings = Models.Binder.AppSettings.Get(configurationRoot); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); @@ -77,11 +77,9 @@ public class UnitTestFace private Property.Models.PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel) { Property.Models.PropertyLogic result; - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism)); if (_Configuration?.PropertyConfiguration is null) throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, reverse, model, predictorModel); + result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, reverse, model, predictorModel); return result; } @@ -129,11 +127,32 @@ public class UnitTestFace [TestMethod] public void TestGetPixelPercentage() { - double pixelPercentage; - pixelPercentage = Location.GetPixelPercentage(1, 1, 10, 10, 100, 100); - Assert.IsTrue(pixelPercentage == 0.0505d); - pixelPercentage = Location.GetPixelPercentage(50, 50, 60, 60, 100, 100); - Assert.IsTrue(pixelPercentage == 0.5555d); + int normalizedPixelPercentage; + int left, top, right, bottom, width, height; + left = 1; + top = 1; + right = 10; + bottom = 10; + width = 100; + height = 100; + normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width); + Assert.IsTrue(normalizedPixelPercentage == 0505); + left = 50; + top = 50; + right = 60; + bottom = 60; + width = 100; + height = 100; + normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width); + Assert.IsTrue(normalizedPixelPercentage == 5555); + left = 20; + top = 40; + right = 60; + bottom = 80; + width = 100; + height = 100; + normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width); + Assert.IsTrue(normalizedPixelPercentage == 6040); } [TestMethod] @@ -223,18 +242,22 @@ public class UnitTestFace sourceDirectory = Path.Combine(aPropertySingletonDirectory, sourceDirectoryName); item = new(sourceDirectoryFile, relativePath, fileHolder, isValidImageFormatExtension, property, false, false); Assert.IsNotNull(item.ImageFileHolder); - property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions); + if (item.Property is null) + { + property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions); + item.Update(property); + } (int _, metadataCollection) = metadata.GetMetadataCollection(bResultsFullGroupDirectory, subFileTuples, parseExceptions, item); - imageResizeKeyValuePairs = resize.GetResizeKeyValuePairs(cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, property, item); + imageResizeKeyValuePairs = resize.GetResizeKeyValuePairs(cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, item); Property.Models.FileHolder resizedFileHolder = new(Path.Combine(resize.AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(item.ImageFileHolder.FullName))); item.SetResizedFileHolder(resizedFileHolder); - resize.SaveResizedSubfile(outputResolution, cResultsFullGroupDirectory, subFileTuples, item, original, property, imageResizeKeyValuePairs); + resize.SaveResizedSubfile(outputResolution, cResultsFullGroupDirectory, subFileTuples, item, original, imageResizeKeyValuePairs); item.SetResizedFileHolder(Property.Models.FileHolder.Refresh(resizedFileHolder)); Assert.IsNotNull(item.ResizedFileHolder); Image? image = FaceRecognition.LoadImageFile(item.ResizedFileHolder.FullName); Assert.IsNotNull(image); FaceRecognition faceRecognition = FaceRecognition.Create(modelParameter); - List locations = faceRecognition.FaceLocations(model, image, _Configuration.NumberOfTimesToUpsample.Value, sortByPixelPercentage: true); + List locations = faceRecognition.FaceLocations(model, image, _Configuration.NumberOfTimesToUpsample.Value, sortByNormalizedPixelPercentage: true); Assert.IsTrue(locations.Count == 2); List<(FacePart, FacePoint[])[]> faceLandmarks = faceRecognition.GetFaceLandmarkCollection(image, _Configuration.NumberOfTimesToUpsample.Value, locations, predictorModel, model); Assert.IsTrue(faceLandmarks.Count == 2);