diff --git a/.vscode/launch.json b/.vscode/launch.json index c25c58c..72ffcea 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,8 +11,8 @@ "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. "programC": "${workspaceFolder}/Compare/bin/Debug/net6.0/win-x64/Compare.dll", - "program": "${workspaceFolder}/Date-Group/bin/Debug/net6.0/win-x64/Date-Group.dll", - "programI": "${workspaceFolder}/Instance/bin/Debug/net6.0/win-x64/Instance.dll", + "programD": "${workspaceFolder}/Date-Group/bin/Debug/net6.0/win-x64/Date-Group.dll", + "program": "${workspaceFolder}/Instance/bin/Debug/net6.0/win-x64/Instance.dll", "programN": "${workspaceFolder}/Not-Copy-Copy/bin/Debug/net6.0/win-x64/Not-Copy-Copy.dll", "programP": "${workspaceFolder}/PrepareForOld/bin/Debug/net6.0/win-x64/PrepareForOld.dll", "args": [], diff --git a/.vscode/settings.json b/.vscode/settings.json index 09ac856..5c22591 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,22 @@ { "cSpell.words": [ + "ASPNETCORE", "Barrick", + "bcdfghjklmnpqrstvwxyz", "Beichler", "Bohdi", + "CUDA", "Dlib", + "Exif", + "Getα", + "mmod", + "nosj", "Phares", + "resnet", "Serilog", + "Subfile", + "Subfiles", "Vericruz" - ] + ], + "cSpell.enabled": true } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index f9df1ea..25f4871 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -7,7 +7,7 @@ "type": "process", "args": [ "build", - "${workspaceFolder}/Console.sln", + "${workspaceFolder}/View-by-Distance-MKLink-Console.sln", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], diff --git a/Compare/Compare.cs b/Compare/Compare.cs index 1065438..34197b1 100644 --- a/Compare/Compare.cs +++ b/Compare/Compare.cs @@ -14,8 +14,6 @@ public class Compare private readonly Serilog.ILogger? _Log; private readonly AppSettings _AppSettings; - private readonly List _Exceptions; - private readonly string[] _VerifyToSeason; private readonly IsEnvironment _IsEnvironment; private readonly Models.Configuration _Configuration; private readonly List> _FileKeyValuePairs; @@ -42,20 +40,20 @@ public class Compare _RenameCFindReplace = new(); _SpellingFindReplace = new(); _IsEnvironment = isEnvironment; - _Exceptions = new List(); _Log = Serilog.Log.ForContext(); _FileKeyValuePairs = new List>(); _FilePropertiesKeyValuePairs = new Dictionary>>(); - string message; string searchPattern = "*"; long ticks = DateTime.Now.Ticks; List topDirectories = new(); + List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection; Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory); Property.Models.Configuration.Verify(propertyConfiguration); - Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); + Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Verify(configuration); - if (propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null) - throw new Exception($"{nameof(propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!"); + bool reverse = false; + string modelName = nameof(modelName); + string predictorModelName = nameof(predictorModelName); if (propertyConfiguration.PopulatePropertyId is null) throw new Exception($"{nameof(propertyConfiguration.PopulatePropertyId)} is null!"); foreach (string spelling in configuration.Spelling) @@ -105,11 +103,11 @@ public class Compare throw new Exception("Change configuration!"); _RenameCFindReplace.Add(new(renameFrom, renameTo)); } - List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); + groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, reverse: false); if (appSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); _Log.Information($"{nameof(Property.Models.Stateless.A_Property.GetGroupCollection)} has finished"); - _VerifyToSeason = propertyConfiguration.VerifyToSeason.Select(l => Path.Combine(propertyConfiguration.RootDirectory, l)).ToArray(); + _Configuration = configuration; List missingVerifyToSeasonCollection = GetMissingVerifyToSeasonCollection(topDirectories, groupCollection); if (missingVerifyToSeasonCollection.Any()) throw new Exception($"Update configuration with the following {Environment.NewLine} {string.Join(Environment.NewLine, missingVerifyToSeasonCollection)}"); @@ -117,7 +115,7 @@ public class Compare { topDirectories.Clear(); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); - groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); + groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, reverse: false); if (appSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); } @@ -126,7 +124,7 @@ public class Compare { topDirectories.Clear(); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); - groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); + groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, reverse: false); if (appSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); } @@ -135,7 +133,7 @@ public class Compare { topDirectories.Clear(); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); - groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); + groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, reverse: false); if (appSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); } @@ -144,7 +142,7 @@ public class Compare { topDirectories.Clear(); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); - groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); + groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, reverse: false); if (appSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); } @@ -157,20 +155,14 @@ public class Compare { topDirectories.Clear(); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); - groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); + groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, reverse: false); if (appSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); } PropertyLogic propertyLogic = GetPropertyLogic(); if (_IsEnvironment.Development && propertyConfiguration.PopulatePropertyId.Value && !propertyLogic.IndicesFromOld.Any()) throw new Exception("Copy keyValuePairs-####.json file"); - _Exceptions.AddRange(propertyLogic.DoWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true)); - message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}"; - _Log.Information(message); - if (_Exceptions.Count != 0) - throw new Exception(message); - if (appSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(PropertyLogic.DoWork)); + List propertyHolderCollections = Property.Models.Stateless.A_Property.Get(propertyConfiguration, reverse, modelName, predictorModelName, propertyLogic); if (!isSilent) { _Log.Information("First pass completed"); @@ -182,10 +174,9 @@ public class Compare } _Log.Information(". . ."); } - string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A_Property), "{}"); - string aPropertyContentCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A_Property), "[()]"); if (!isSilent) { + string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A_Property), "{}"); if (Directory.Exists(aPropertySingletonDirectory)) { ConsoleKey? consoleKey = null; @@ -199,37 +190,8 @@ public class Compare _Log.Information(". . ."); if (consoleKey == ConsoleKey.Y) ChangeExtensionFromDeleteToJson(aPropertySingletonDirectory); - for (int y = 0; y < int.MaxValue; y++) - { - _Log.Information($"Execute {nameof(Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull)} \"Y(es)\" or \"N(o)\"?"); - consoleKey = Console.ReadKey().Key; - if (consoleKey is ConsoleKey.Y or ConsoleKey.N) - break; - } - _Log.Information(". . ."); - if (consoleKey == ConsoleKey.Y) - { - Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull(propertyConfiguration.RootDirectory, aPropertySingletonDirectory, onlyJson: false); - for (int y = 0; y < int.MaxValue; y++) - { - _Log.Information($"Execute {nameof(Property.Models.Stateless.IPath.DeleteEmptyDirectories)} \"Y(es)\" or \"N(o)\"?"); - consoleKey = Console.ReadKey().Key; - if (consoleKey is ConsoleKey.Y or ConsoleKey.N) - break; - } - _Log.Information(". . ."); - _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); - _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(aPropertySingletonDirectory); - } } } - topDirectories.Clear(); - groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); - _Exceptions.AddRange(propertyLogic.DoWork(propertyConfiguration, topDirectories, groupCollection, firstPass: false)); - message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}"; - _Log.Information(message); - if (_Exceptions.Count != 0) - throw new Exception(message); if (!isSilent) { _Log.Information("Second pass completed"); @@ -241,7 +203,8 @@ public class Compare } _Log.Information(". . ."); } - ThirdPassToMove(propertyLogic, propertyConfiguration, aPropertyContentCollectionDirectory, topDirectories, groupCollection); + string aPropertyContentCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A_Property), "[()]"); + ThirdPassToMove(propertyConfiguration, modelName, predictorModelName, propertyLogic, propertyHolderCollections, aPropertyContentCollectionDirectory); if (!isSilent) { _Log.Information("Third pass completed"); @@ -253,7 +216,7 @@ public class Compare } _Log.Information(". . ."); } - FourthPassCreateWindowsShortcuts(propertyLogic, propertyConfiguration, topDirectories, groupCollection, saveToCollection: false, keepAll: false); + FourthPassCreateWindowsShortcuts(propertyConfiguration, modelName, predictorModelName, propertyLogic, propertyHolderCollections, saveToCollection: false, keepAll: false); if (!isSilent) { _Log.Information("Fourth pass completed"); @@ -269,7 +232,6 @@ public class Compare string currentYearDirectory = Path.Combine(propertyConfiguration.RootDirectory, $". {DateTime.Now:yyyy}"); if (!Directory.Exists(currentYearDirectory)) _ = Directory.CreateDirectory(currentYearDirectory); - _Configuration = configuration; } private string GetRename(string renameA) @@ -430,16 +392,16 @@ public class Compare throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!"); if (_Configuration?.PropertyConfiguration is null) throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); - result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, _VerifyToSeason); - string fromPerpareForOld = "34720-637858334555170379.tsv"; - string fromPerpareForOldFile = Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, fromPerpareForOld); - if (File.Exists(fromPerpareForOldFile)) + result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration); + string fromPrepareForOld = "34720-637858334555170379.tsv"; + string fromPrepareForOldFile = Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, fromPrepareForOld); + if (File.Exists(fromPrepareForOldFile)) { string[] lines; string[] columns; List debug = new(); long ticks = DateTime.Now.Ticks; - lines = File.ReadAllLines(fromPerpareForOldFile); + lines = File.ReadAllLines(fromPrepareForOldFile); string resultsDirectory = $"{_Configuration.PropertyConfiguration.RootDirectory} - Results"; int[]? zeros = (from l in result.IndicesFromNew where l.Value.Any() select l.Value[0]).ToArray(); lines = (from l in result.IndicesFromNew select string.Concat(l.Key, '\t', string.Join('\t', l.Value))).ToArray(); @@ -461,7 +423,7 @@ public class Compare else debug.Add(propertyId.ToString()); } - File.WriteAllLines(Path.Combine(resultsDirectory, $"{ticks}-{fromPerpareForOld}"), debug); + File.WriteAllLines(Path.Combine(resultsDirectory, $"{ticks}-{fromPrepareForOld}"), debug); } return result; } @@ -551,7 +513,8 @@ public class Compare string searchPattern = "*.delete"; long ticks = DateTime.Now.Ticks; List topDirectories = new(); - List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(aPropertySingletonDirectory, searchPattern, topDirectories); + List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection; + groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(aPropertySingletonDirectory, searchPattern, topDirectories); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection) @@ -786,7 +749,7 @@ public class Compare } } - private void ThirdPassToMove(PropertyLogic propertyLogic, Property.Models.Configuration configuration, string aPropertyContentCollectionDirectory, List topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection) + private void ThirdPassToMove(Property.Models.Configuration configuration, string modelName, string predictorModelName, PropertyLogic propertyLogic, List propertyHolderCollections, string aPropertyContentCollectionDirectory) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -798,14 +761,17 @@ public class Compare A_Property? property; string? directoryName; ConsoleKey? consoleKey = null; - DateTime dateTime = DateTime.Now; + long ticks = DateTime.Now.Ticks; string filteredSourceDirectoryFile; List fileStayCollection = new(); List fileMoveCollection = new(); List distinctDirectories = new(); List> valueCollection = new(); - List groupResultsCollection = propertyLogic.GetParallelWork(configuration, topDirectories, groupCollection, firstPass: false, filterOnFirstPass: false); - foreach (Group group in groupResultsCollection) + List directoryInfoCollection = new(); + propertyLogic.ParallelWork(configuration, modelName, predictorModelName, ticks, propertyHolderCollections, firstPass: false); + if (propertyLogic.ExceptionsDirectories.Any()) + throw new Exception(); + foreach (Property.Models.DirectoryInfo group in directoryInfoCollection) { for (int i = 0; i < group.PropertyCollection.Length; i++) { @@ -823,9 +789,9 @@ public class Compare string[] lines = (from l in valueCollection select string.Concat(l.Key, '\t', string.Join('\t', l.Value))).ToArray(); if (!Directory.Exists(aPropertyContentCollectionDirectory)) _ = Directory.CreateDirectory(aPropertyContentCollectionDirectory); - File.WriteAllLines(Path.Combine(aPropertyContentCollectionDirectory, $"{dateTime.Ticks}.tsv"), lines); + File.WriteAllLines(Path.Combine(aPropertyContentCollectionDirectory, $"{ticks}.tsv"), lines); string json = JsonSerializer.Serialize(valueCollection, new JsonSerializerOptions { WriteIndented = true }); - File.WriteAllText(Path.Combine(aPropertyContentCollectionDirectory, $"{dateTime.Ticks}.json"), json); + File.WriteAllText(Path.Combine(aPropertyContentCollectionDirectory, $"{ticks}.json"), json); foreach (string fileMove in fileMoveCollection) { directoryName = Path.GetDirectoryName(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, id, fileMove[_Configuration.PropertyConfiguration.RootDirectory.Length..])); @@ -861,19 +827,23 @@ public class Compare } } - private void FourthPassCreateWindowsShortcuts(PropertyLogic propertyLogic, Property.Models.Configuration configuration, List topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection, bool saveToCollection, bool keepAll) + private void FourthPassCreateWindowsShortcuts(Property.Models.Configuration configuration, string modelName, string predictorModelName, PropertyLogic propertyLogic, List propertyHolderCollections, bool saveToCollection, bool keepAll) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); int stay = 0; A_Property? property; ConsoleKey? consoleKey = null; + long ticks = DateTime.Now.Ticks; string filteredSourceDirectoryFile; List fileMoveCollection = new(); List> valueCollection = new(); (long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] collection; - List groupResultsCollection = propertyLogic.GetParallelWork(configuration, topDirectories, groupCollection, firstPass: false, filterOnFirstPass: false); - foreach (Group group in groupResultsCollection) + List directoryInfoCollection = new(); + propertyLogic.ParallelWork(configuration, modelName, predictorModelName, ticks, propertyHolderCollections, firstPass: false); + if (propertyLogic.ExceptionsDirectories.Any()) + throw new Exception(); + foreach (Property.Models.DirectoryInfo group in directoryInfoCollection) { for (int i = 0; i < group.PropertyCollection.Length; i++) { @@ -888,7 +858,7 @@ public class Compare fileMoveCollection.Add(filteredSourceDirectoryFile); } } - collection = propertyLogic.GetPropertyIds(configuration, groupResultsCollection, saveToCollection); + collection = propertyLogic.GetPropertyIds(configuration, modelName, predictorModelName, directoryInfoCollection, saveToCollection); _Log.Information($"{stay} file(s) are staying and {fileMoveCollection.Count} file(s) will be moved"); for (int x = 0; x < int.MaxValue; x++) { diff --git a/Compare/Models/Configuration.cs b/Compare/Models/Configuration.cs index 4f02890..e54f251 100644 --- a/Compare/Models/Configuration.cs +++ b/Compare/Models/Configuration.cs @@ -36,7 +36,7 @@ public class Configuration return result; } - public void Set(Property.Models.Configuration propertyConfiguration) => _PropertyConfiguration = propertyConfiguration; + public void Set(Property.Models.Configuration configuration) => _PropertyConfiguration = configuration; public void Update() => _PropertyConfiguration?.Update(); diff --git a/Compare/appsettings.Development.json b/Compare/appsettings.Development.json index 7a0b764..a3f26d5 100644 --- a/Compare/appsettings.Development.json +++ b/Compare/appsettings.Development.json @@ -79,7 +79,7 @@ "/zzz Phares Slides/Slides 2015-06-10/Magazine 01" ], "Configuration": { - "DateGroup": "2022-04-07", + "DateGroup": "2022-07-24", "DiffPropertyDirectory": "", "FileNameDirectorySeparator": ".Z.", "ForcePropertyLastWriteTimeToCreationTime": false, @@ -87,20 +87,20 @@ "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", "PopulatePropertyId": true, "PropertiesChangedForProperty": false, - "RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-04-17 - fa60aa45ebb55fe3ee0ce4da8a64e40611e7d5ce - III", + "RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-07-24 - 1539b2f974f07b6b5cbda8450faf0eec85d02eda - III", "WriteBitmapDataBytes": false, "IgnoreExtensions": [ ".gif", ".GIF" ], "PropertyContentCollectionFiles": [ - "/Images 2022-04-17 - fa60aa45ebb55fe3ee0ce4da8a64e40611e7d5ce - III - Results/A) Property/2022-04-07/[()]/637869381676042455.json", - "/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-04-07/[()]/637869733124119330.json", - "/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-04-07/[()]/637869734240700328.json", - "/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-04-07/[()]/637869734970730630.json", - "/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-04-07/[()]/637869743752078399.json", - "/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-04-07/[()]/637869744751177715.json", - "/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-04-07/[()]/637869745134124462.json" + "/Images 2022-07-24 - 1539b2f974f07b6b5cbda8450faf0eec85d02eda - III - Results/A) Property/2022-07-24/[()]/637869381676042455.json", + "/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-07-24/[()]/637869733124119330.json", + "/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-07-24/[()]/637869734240700328.json", + "/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-07-24/[()]/637869734970730630.json", + "/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-07-24/[()]/637869743752078399.json", + "/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-07-24/[()]/637869744751177715.json", + "/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-07-24/[()]/637869745134124462.json" ], "ValidImageFormatExtensions": [ ".bmp", diff --git a/Compare/appsettings.json b/Compare/appsettings.json index 65beeea..b357d22 100644 --- a/Compare/appsettings.json +++ b/Compare/appsettings.json @@ -50,7 +50,7 @@ "WorkingDirectoryName": "PharesApps", "Windows": { "Configuration": { - "DateGroup": "2022-04-07", + "DateGroup": "2022-07-24", "DiffPropertyDirectory": "", "FileNameDirectorySeparator": ".Z.", "ForcePropertyLastWriteTimeToCreationTime": false, @@ -94,13 +94,13 @@ ".GIF" ], "PropertyContentCollectionFiles": [ - "/Images 2022-04-17 - fa60aa45ebb55fe3ee0ce4da8a64e40611e7d5ce - III - Results/A) Property/2022-04-07/[()]/637869381676042455.json", - "/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-04-07/[()]/637869733124119330.json", - "/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-04-07/[()]/637869734240700328.json", - "/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-04-07/[()]/637869734970730630.json", - "/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-04-07/[()]/637869743752078399.json", - "/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-04-07/[()]/637869744751177715.json", - "/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-04-07/[()]/637869745134124462.json" + "/Images 2022-07-24 - 1539b2f974f07b6b5cbda8450faf0eec85d02eda - III - Results/A) Property/2022-07-24/[()]/637869381676042455.json", + "/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-07-24/[()]/637869733124119330.json", + "/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-07-24/[()]/637869734240700328.json", + "/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-07-24/[()]/637869734970730630.json", + "/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-07-24/[()]/637869743752078399.json", + "/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-07-24/[()]/637869744751177715.json", + "/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-07-24/[()]/637869745134124462.json" ], "ValidImageFormatExtensions": [ ".bmp", diff --git a/Date-Group/Date-Group.csproj b/Date-Group/Date-Group.csproj index 2b69460..c8bef69 100644 --- a/Date-Group/Date-Group.csproj +++ b/Date-Group/Date-Group.csproj @@ -46,6 +46,7 @@ + diff --git a/Date-Group/DateGroup.cs b/Date-Group/DateGroup.cs index 3ce0df8..d00c531 100644 --- a/Date-Group/DateGroup.cs +++ b/Date-Group/DateGroup.cs @@ -5,6 +5,7 @@ using System.Text; using View_by_Distance.Date.Group.Models; using View_by_Distance.Property.Models; using View_by_Distance.Shared.Models.Methods; +using WindowsShortcutFactory; namespace View_by_Distance.Date.Group; @@ -39,50 +40,60 @@ public class DateGroup Property.Models.Configuration.Verify(propertyConfiguration); Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Verify(configuration); + bool reverse = false; + string modelName = nameof(modelName); + string predictorModelName = nameof(predictorModelName); _Configuration = configuration; if (configuration.ByHash is null) throw new Exception($"{nameof(configuration.ByHash)} is null!"); - if (propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null) - throw new Exception($"{nameof(propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!"); + if (configuration.ByCreateDateShortcut is null) + throw new Exception($"{nameof(configuration.ByCreateDateShortcut)} is null!"); if (propertyConfiguration.PopulatePropertyId is null) throw new Exception($"{nameof(propertyConfiguration.PopulatePropertyId)} is null!"); if (!_IsEnvironment.Development) throw new Exception("This program only allows development environments!"); - string searchPattern = "*"; long ticks = DateTime.Now.Ticks; - List topDirectories = new(); PropertyLogic propertyLogic = GetPropertyLogic(); string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories); foreach (string dbFile in dbFiles) File.Delete(dbFile); + if (true || appSettings.MaxDegreeOfParallelism.Value < 2) + ticks = LogDelta(ticks, nameof(File.Delete)); for (int i = 1; i < 10; i++) _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); - List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); - if (appSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); - List groupResultsCollection = new(); - if (!propertyConfiguration.PopulatePropertyId.Value || !configuration.ByHash.Value) - groupResultsCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true, filterOnFirstPass: true); + if (true || appSettings.MaxDegreeOfParallelism.Value < 2) + ticks = LogDelta(ticks, nameof(Property.Models.Stateless.IPath.DeleteEmptyDirectories)); + List propertyHolderCollections = Property.Models.Stateless.A_Property.Get(propertyConfiguration, reverse, modelName, predictorModelName, propertyLogic); + if (configuration.ByCreateDateShortcut.HasValue && configuration.ByCreateDateShortcut.Value) + CreateDateShortcut(propertyConfiguration, propertyHolderCollections); else { - _Exceptions.AddRange(propertyLogic.DoWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true)); - string message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}"; - _Log.Information(message); - if (_Exceptions.Count != 0) - throw new Exception(message); + List topDirectories = new(); + List directoryInfoCollection = new(); + propertyLogic.ParallelWork(propertyConfiguration, modelName, predictorModelName, ticks, propertyHolderCollections, firstPass: true); if (appSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(PropertyLogic.DoWork)); - topDirectories.Clear(); - groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); - if (appSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); - groupResultsCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: false, filterOnFirstPass: true); + ticks = LogDelta(ticks, nameof(PropertyLogic.ParallelWork)); + if (propertyLogic.ExceptionsDirectories.Any()) + throw new Exception(); + if (propertyConfiguration.PopulatePropertyId.Value && (configuration.ByCreateDateShortcut.Value || configuration.ByHash.Value)) + { + if (Property.Models.Stateless.A_Property.Any(propertyHolderCollections)) + propertyLogic.ParallelWork(propertyConfiguration, modelName, predictorModelName, ticks, propertyHolderCollections, firstPass: false); + if (appSettings.MaxDegreeOfParallelism.Value < 2) + ticks = LogDelta(ticks, nameof(PropertyLogic.ParallelWork)); + if (propertyLogic.ExceptionsDirectories.Any()) + throw new Exception(); + } + if ((from l in directoryInfoCollection where l.Moved.Any(a => a) select true).Any()) + throw new Exception(); + MoveFiles(topDirectories, directoryInfoCollection); } - MoveFiles(topDirectories, groupResultsCollection); } private static void Verify(Models.Configuration configuration) { + if (configuration.ByCreateDateShortcut is null) + throw new Exception($"{nameof(configuration.ByCreateDateShortcut)} is null!"); if (configuration.ByDay is null) throw new Exception($"{nameof(configuration.ByDay)} is null!"); if (configuration.ByHash is null) @@ -91,17 +102,17 @@ public class DateGroup throw new Exception($"{nameof(configuration.BySeason)} is null!"); if (configuration.ByWeek is null) throw new Exception($"{nameof(configuration.ByWeek)} is null!"); - if (!configuration.ByDay.Value && !configuration.ByWeek.Value && !configuration.BySeason.Value && !configuration.ByHash.Value) + if (!configuration.ByCreateDateShortcut.Value && !configuration.ByDay.Value && !configuration.ByWeek.Value && !configuration.BySeason.Value && !configuration.ByHash.Value) throw new Exception("Change configuration!"); if (configuration.KeepFullPath is null) throw new Exception($"{nameof(configuration.KeepFullPath)} is null!"); if (configuration?.PropertyConfiguration?.PopulatePropertyId is null) throw new Exception($"{nameof(configuration.PropertyConfiguration.PopulatePropertyId)} must be set!"); - if (configuration.PropertyConfiguration.PopulatePropertyId.Value && !configuration.ByHash.Value) + if (configuration.PropertyConfiguration.PopulatePropertyId.Value && !configuration.ByCreateDateShortcut.Value && !configuration.ByHash.Value) throw new Exception("Change configuration!"); if (!configuration.PropertyConfiguration.PopulatePropertyId.Value && configuration.ByHash.Value) throw new Exception("Change configuration!"); - if (configuration.ByDay.Value && configuration.ByWeek.Value && configuration.BySeason.Value && configuration.ByHash.Value) + if (configuration.ByCreateDateShortcut.Value && configuration.ByDay.Value && configuration.ByWeek.Value && configuration.BySeason.Value && configuration.ByHash.Value) throw new Exception("Change configuration!"); } @@ -148,9 +159,11 @@ public class DateGroup return result; } - private List<(string Source, string[] Destination)> GetMoveFileCollection(string destinationDirectory, string topDirectory, Property.Models.Group group) + private List<(string Source, string[] Destination)> GetMoveFileCollection(string destinationDirectory, string topDirectory, Property.Models.DirectoryInfo group) { List<(string Source, string[] Destination)> results = new(); + if (_Configuration.ByCreateDateShortcut is null) + throw new Exception($"{nameof(_Configuration.ByCreateDateShortcut)} is null!"); if (_Configuration.ByDay is null) throw new Exception($"{nameof(_Configuration.ByDay)} is null!"); if (_Configuration.ByHash is null) @@ -181,8 +194,8 @@ public class DateGroup string[] directorySegments; DateTime? minimumDateTime = null; List destinationCollection; - string filteredSourceDirectoryFile; List directoryNames = new(); + FileInfo filteredSourceDirectoryFileInfo; List topDirectorySegments = new(); StringBuilder destinationDirectoryName = new(); Calendar calendar = new CultureInfo("en-US").Calendar; @@ -219,7 +232,7 @@ public class DateGroup } if (matches is null) matches = Array.Empty(); - for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++) + for (int i = 0; i < group.SourceDirectoryFileInfoCollection.Length; i++) { destinationCollection = new(); directoryNames.Clear(); @@ -227,14 +240,14 @@ public class DateGroup property = group.PropertyCollection[i]; if (property is null) continue; - filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i]; + filteredSourceDirectoryFileInfo = group.SourceDirectoryFileInfoCollection[i]; minimumDateTime = Property.Models.Stateless.A_Property.GetMinimumDateTime(property); - directory = Path.GetDirectoryName(filteredSourceDirectoryFile); + directory = filteredSourceDirectoryFileInfo.DirectoryName; if (string.IsNullOrEmpty(directory)) continue; day = minimumDateTime.Value.ToString("MM-dd"); month = minimumDateTime.Value.ToString("MMMM"); - (propertyWrongYear, _) = property.IsWrongYear(filteredSourceDirectoryFile, minimumDateTime); + (propertyWrongYear, _) = property.IsWrongYear(filteredSourceDirectoryFileInfo.FullName, minimumDateTime); if (propertyWrongYear is null) flag = '#'; else @@ -303,13 +316,13 @@ public class DateGroup } } if (!_Configuration.ByHash.Value || property.Id is null) - fileName = Path.GetFileName(filteredSourceDirectoryFile); + fileName = filteredSourceDirectoryFileInfo.Name; else - fileName = $"{property.Id.Value}{Path.GetExtension(filteredSourceDirectoryFile).ToLower()}"; + fileName = $"{property.Id.Value}{filteredSourceDirectoryFileInfo.Extension.ToLower()}"; destinationCollection.Add(destinationDirectory); destinationCollection.AddRange(directoryNames); destinationCollection.Add(fileName); - results.Add(new(filteredSourceDirectoryFile, destinationCollection.ToArray())); + results.Add(new(filteredSourceDirectoryFileInfo.FullName, destinationCollection.ToArray())); } return results; } @@ -317,18 +330,15 @@ public class DateGroup private PropertyLogic GetPropertyLogic() { PropertyLogic result; - - string[] verifyToSeason = Array.Empty(); - if (_AppSettings.MaxDegreeOfParallelism is null) throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!"); if (_Configuration?.PropertyConfiguration is null) throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); - result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, verifyToSeason); + result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration); return result; } - private List<(string Source, string[] Destination)> GetFileMoveCollectionAll(List topDirectories, List groupCollection) + private List<(string Source, string[] Destination)> GetFileMoveCollectionAll(List topDirectories, List groupCollection) { List<(string Source, string[] Destination)> results = new(); if (_Configuration.KeepFullPath is null) @@ -341,7 +351,7 @@ public class DateGroup string destinationDirectory; string destinationRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, "Z) Moved"); List<(string Source, string[] Destination)> fileMoveCollectionDirectory; - foreach (Property.Models.Group group in groupCollection) + foreach (Property.Models.DirectoryInfo group in groupCollection) { sourceDirectory = group.SourceDirectory; if (!_Configuration.KeepFullPath.Value) @@ -366,7 +376,7 @@ public class DateGroup return results; } - private void MoveFiles(List topDirectories, List groupCollection) + private void MoveFiles(List topDirectories, List groupCollection) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -423,4 +433,57 @@ public class DateGroup _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory); } + private static void CreateDateShortcut(Property.Models.Configuration configuration, List propertyHolderCollections) + { + string path; + string fileName; + string directory; + int selectedTotal; + const int minimum = 3; + List dateTimes; + const int maximumHours = 24; + string? relativePathDirectory; + WindowsShortcut windowsShortcut; + TimeSpan threeStandardDeviationHigh; + List selectedPropertyHolderCollection; + string aPropertyContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "()"); + foreach (PropertyHolder[] propertyHolderCollection in propertyHolderCollections) + { + if (!propertyHolderCollection.Any()) + continue; + selectedTotal = 0; + threeStandardDeviationHigh = Property.Models.Stateless.A_Property.GetThreeStandardDeviationHigh(minimum, propertyHolderCollection); + if (threeStandardDeviationHigh.TotalHours > maximumHours) + threeStandardDeviationHigh = new(maximumHours, 0, 0); + for (int i = 0; i < propertyHolderCollection.Length; i++) + { + (i, dateTimes, selectedPropertyHolderCollection) = Property.Models.Stateless.A_Property.Get(propertyHolderCollection, threeStandardDeviationHigh, i); + selectedTotal += selectedPropertyHolderCollection.Count; + foreach (PropertyHolder propertyHolder in selectedPropertyHolderCollection) + { + if (propertyHolder.Property is null || propertyHolder.MinimumDateTime is null) + continue; + relativePathDirectory = Path.GetDirectoryName(propertyHolder.RelativePath); + if (string.IsNullOrEmpty(relativePathDirectory)) + continue; + path = Path.GetFullPath($"{configuration.RootDirectory}{propertyHolder.RelativePath[..^5]}"); + directory = Path.Combine($"{aPropertyContentDirectory}{relativePathDirectory}", $"{dateTimes.Min():yyyy-MM-dd_HH-mm-ss}---{dateTimes.Max():yyyy-MM-dd_HH-mm-ss}"); + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); + fileName = Path.Combine(directory, $"{Path.GetFileName(propertyHolder.RelativePath[..^5])}.lnk"); + if (File.Exists(fileName)) + continue; + windowsShortcut = new() { Path = path }; + windowsShortcut.Save(fileName); + windowsShortcut.Dispose(); + if (!File.Exists(fileName)) + continue; + File.SetLastWriteTime(fileName, propertyHolder.MinimumDateTime.Value); + } + } + if (selectedTotal < propertyHolderCollection.Length && selectedTotal < (from l in propertyHolderCollection where l.Property is not null && l.MinimumDateTime.HasValue select true).Count()) + continue; + } + } + } \ No newline at end of file diff --git a/Date-Group/Models/Binder/Configuration.cs b/Date-Group/Models/Binder/Configuration.cs index 0f759e0..97f6c56 100644 --- a/Date-Group/Models/Binder/Configuration.cs +++ b/Date-Group/Models/Binder/Configuration.cs @@ -5,6 +5,7 @@ namespace View_by_Distance.Date.Group.Models.Binder; public class Configuration { + [Display(Name = "By Create Date Shortcut"), Required] public bool? ByCreateDateShortcut { get; set; } [Display(Name = "By Date"), Required] public bool? ByDay { get; set; } [Display(Name = "By Hash"), Required] public bool? ByHash { get; set; } [Display(Name = "By Season"), Required] public bool? BySeason { get; set; } @@ -15,6 +16,7 @@ public class Configuration public Configuration() { ByDay = null; + ByCreateDateShortcut = null; ByHash = null; BySeason = null; ByWeek = null; diff --git a/Date-Group/Models/Configuration.cs b/Date-Group/Models/Configuration.cs index 9623679..c93de8b 100644 --- a/Date-Group/Models/Configuration.cs +++ b/Date-Group/Models/Configuration.cs @@ -6,12 +6,14 @@ namespace View_by_Distance.Date.Group.Models; public class Configuration { + protected readonly bool? _ByCreateDateShortcut; protected readonly bool? _ByDay; protected readonly bool? _ByHash; protected readonly bool? _BySeason; protected readonly bool? _ByWeek; protected readonly bool? _KeepFullPath; protected Property.Models.Configuration? _PropertyConfiguration; + public bool? ByCreateDateShortcut => _ByCreateDateShortcut; public bool? ByDay => _ByDay; public bool? ByHash => _ByHash; public bool? BySeason => _BySeason; @@ -20,8 +22,9 @@ public class Configuration public Property.Models.Configuration? PropertyConfiguration => _PropertyConfiguration; [JsonConstructor] - public Configuration(bool? byDay, bool? byHash, bool? bySeason, bool? byWeek, bool? keepFullPath, Property.Models.Configuration? propertyConfiguration) + public Configuration(bool? byCreateDateShortcut, bool? byDay, bool? byHash, bool? bySeason, bool? byWeek, bool? keepFullPath, Property.Models.Configuration? propertyConfiguration) { + _ByCreateDateShortcut = byCreateDateShortcut; _ByDay = byDay; _ByHash = byHash; _BySeason = bySeason; @@ -36,7 +39,7 @@ public class Configuration return result; } - public void Set(Property.Models.Configuration propertyConfiguration) => _PropertyConfiguration = propertyConfiguration; + public void Set(Property.Models.Configuration configuration) => _PropertyConfiguration = configuration; public void Update() => _PropertyConfiguration?.Update(); diff --git a/Date-Group/appsettings.Development.json b/Date-Group/appsettings.Development.json index 9069b83..e332095 100644 --- a/Date-Group/appsettings.Development.json +++ b/Date-Group/appsettings.Development.json @@ -9,7 +9,7 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "MaxDegreeOfParallelism": 1, + "MaxDegreeOfParallelism": 6, "Serilog": { "Using": [ "Serilog.Sinks.Console", @@ -50,19 +50,20 @@ "WorkingDirectoryName": "PharesApps", "Windows": { "Configuration": { + "ByCreateDateShortcut": true, "ByDay": false, "ByHash": false, - "BySeason": true, + "BySeason": false, "ByWeek": false, - "DateGroup": "2022-04-07", + "DateGroup": "2022-07-24", "FileNameDirectorySeparator": ".Z.", "ForcePropertyLastWriteTimeToCreationTime": false, "KeepFullPath": false, "MaxImagesInDirectoryForTopLevelFirstPass": 50, "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", - "PopulatePropertyId": false, + "PopulatePropertyId": true, "PropertiesChangedForProperty": false, - "RootDirectory": "C:/Tmp/Phares/- Device Videos 2_0_0_3 - Current/_", + "RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-07-24 - 1539b2f974f07b6b5cbda8450faf0eec85d02eda - III", "WriteBitmapDataBytes": false, "IgnoreExtensions": [ ".gif", diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 8078f71..77d622f 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -8,6 +8,7 @@ using View_by_Distance.Instance.Models; using View_by_Distance.Metadata.Models; using View_by_Distance.Property.Models; using View_by_Distance.Resize.Models; +using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Instance; @@ -36,6 +37,7 @@ public class DlibDotNet public DlibDotNet(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) { string argZero; + Person[] people; _AppSettings = appSettings; if (appSettings.MaxDegreeOfParallelism is null) throw new Exception($"{nameof(appSettings.MaxDegreeOfParallelism)} is null!"); @@ -49,8 +51,6 @@ public class DlibDotNet Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Verify(configuration); (Model model, PredictorModel predictorModel) = GetTuple(args, propertyConfiguration, configuration); - if (configuration.SearchForAbandonedFilesFull is null) - throw new Exception($"{nameof(configuration.SearchForAbandonedFilesFull)} is null!"); _Configuration = configuration; _Index = new G_Index(configuration); _Random = new F_Random(configuration); @@ -72,6 +72,8 @@ public class DlibDotNet throw new Exception($"{nameof(configuration.PropertiesChangedForMetadata)} is null!"); if (configuration.PropertiesChangedForResize is null) throw new Exception($"{nameof(configuration.PropertiesChangedForResize)} is null!"); + if (configuration.Reverse is null) + throw new Exception($"{nameof(configuration.Reverse)} is null!"); _Metadata = new(configuration.ForceMetadataLastWriteTimeToCreationTime.Value, configuration.PropertiesChangedForMetadata.Value); if (args.Count > 0) argZero = Path.GetFullPath(args[0]); @@ -90,44 +92,21 @@ public class DlibDotNet _Faces = new D_Face(configuration, argZero, model, modelParameter, predictorModel); if (configuration.SkipSearch is null) throw new Exception($"{nameof(configuration.SkipSearch)} is null!"); - if (_ArgZeroIsConfigurationRootDirectory) - _ = _People.GetPeople(propertyConfiguration); + if (!_ArgZeroIsConfigurationRootDirectory) + people = Array.Empty(); + else + people = _People.GetPeople(propertyConfiguration); if (!isSilent && configuration.TestDistanceResults.HasValue && configuration.TestDistanceResults.Value) { E2_Navigate e2Navigate = new(console, configuration, argZero); - e2Navigate.Navigate(propertyConfiguration, configuration.OutputResolutions[0]); - } - if (_ArgZeroIsConfigurationRootDirectory) - { - long ticks = DateTime.Now.Ticks; - string[] directories = Property.Models.Stateless.A_Property.GetDirectoryRenameCollection(propertyConfiguration, configuration.OutputResolutions[0], nameof(B_Metadata), nameof(C_Resize)); - foreach (string directory in directories) - { - if (!Directory.Exists(directory)) - continue; - Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull(argZero, directory, onlyJson: false); - } - if (appSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull)); + e2Navigate.Navigate(propertyConfiguration, model, predictorModel, configuration.OutputResolutions[0]); } if (!configuration.SkipSearch.Value) - Search(argZero); + Search(propertyConfiguration, configuration.JuliePhares, configuration.Reverse.Value, model, predictorModel, argZero, people); if (_Exceptions.Count == 0 && _ArgZeroIsConfigurationRootDirectory) { long ticks = DateTime.Now.Ticks; - if (configuration.SearchForAbandonedFilesFull.Value) - { - string[] directories = _Rename.GetDirectoryRenameCollection(propertyConfiguration, relativePath: string.Empty, newDirectoryName: string.Empty, jsonFiles4InfoAny: false); - foreach (string directory in directories) - { - if (!Directory.Exists(directory)) - continue; - Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull(argZero, directory, onlyJson: true); - } - if (appSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull)); - } - List directoryCollections = _Rename.GetDirectoryRenameCollections(propertyConfiguration, relativePath: string.Empty, newDirectoryName: string.Empty, jsonFiles4InfoAny: false); + List directoryCollections = _Rename.GetDirectoryRenameCollections(propertyConfiguration, model, predictorModel, relativePath: string.Empty, newDirectoryName: string.Empty, jsonFiles4InfoAny: false); foreach (string[] directoryCollection in directoryCollections) { _Log.Information(string.Concat("Cleaning <", directoryCollection[0], ">")); @@ -149,7 +128,7 @@ public class DlibDotNet { long ticks = DateTime.Now.Ticks; foreach (string outputResolution in configuration.OutputResolutions) - _Distance.LoadOrCreateThenSaveDirectoryDistanceResults(propertyConfiguration, outputResolution); + _Distance.LoadOrCreateThenSaveDirectoryDistanceResults(propertyConfiguration, model, predictorModel, outputResolution); if (appSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(E_Distance.LoadOrCreateThenSaveDirectoryDistanceResults)); } @@ -300,8 +279,6 @@ public class DlibDotNet throw new Exception($"{nameof(configuration.SaveFullYearOfRandomFiles)} must be set!"); if (configuration.SaveResizedSubfiles is null) throw new Exception($"{nameof(configuration.SaveResizedSubfiles)} must be set!"); - if (configuration.SearchForAbandonedFilesFull is null) - throw new Exception($"{nameof(configuration.SearchForAbandonedFilesFull)} must be set!"); if (configuration.SkipSearch is null) throw new Exception($"{nameof(configuration.SkipSearch)} must be set!"); if (configuration.TestDistanceResults is null) @@ -320,51 +297,10 @@ public class DlibDotNet throw new Exception($"{nameof(configuration.DistanceFactor)} and {nameof(configuration.LocationConfidenceFactor)} must add up to 10!"); } - private int FullParallelWork(object @lock, long ticks, PropertyLogic propertyLogic, string outputResolution, List> sourceDirectoryChanges, List propertyFileInfoCollection, List propertyCollection, List>> metadataCollection, List> resizeKeyValuePairs, List> faceCollections, int g, string sourceDirectory, int r, string[] filteredSourceDirectoryFiles, int count) - { - int result = 0; - if (_Log is null) - throw new Exception($"{nameof(_Log)} is null!"); - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new Exception($"{nameof(AppSettings.MaxDegreeOfParallelism)} is null!"); - ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism.Value }; - ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; - if (faceCollections.Count != filteredSourceDirectoryFiles.Length || metadataCollection.Count != filteredSourceDirectoryFiles.Length || resizeKeyValuePairs.Count != filteredSourceDirectoryFiles.Length || propertyCollection.Count != filteredSourceDirectoryFiles.Length) - { - for (int i = 0; i < filteredSourceDirectoryFiles.Length; i++) - { - faceCollections.Add(new()); - metadataCollection.Add(new()); - resizeKeyValuePairs.Add(new()); - propertyCollection.Add(new()); - propertyFileInfoCollection.Add(null); - } - } - int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); - using (ProgressBar progressBar = new(filteredSourceDirectoryFiles.Length, $"{g}) {r + 1:000} / {count:000} - {outputResolution} - {sourceDirectory} - {filteredSourceDirectoryFiles.Length} file(s) - {totalSeconds} total second(s)", options)) - { - _ = Parallel.For(0, filteredSourceDirectoryFiles.Length, parallelOptions, i => - { - try - { - FullParallelForWork(propertyLogic, @lock, outputResolution, sourceDirectoryChanges, propertyFileInfoCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, faceCollections, sourceDirectory, index: i, filteredSourceDirectoryFiles[i]); - if (sourceDirectoryChanges.Any()) - progressBar.Tick(); - } - catch (Exception ex) - { - result += 1; - _Log.Error(string.Concat(sourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex); - if (result == filteredSourceDirectoryFiles.Length) - throw new Exception(string.Concat("All in [", sourceDirectory, "]failed!")); - } - }); - } - return result; - } - - private void FullParallelForWork(PropertyLogic propertyLogic, object @lock, string outputResolution, List> sourceDirectoryChanges, List propertyFileInfoCollection, List propertyCollection, List>> metadataCollections, List> resizeKeyValuePairs, List> imageFaceCollections, string sourceDirectory, int index, string filteredSourceDirectoryFile) + private void FullParallelForWork(PropertyLogic propertyLogic, object @lock, string outputResolution, List> sourceDirectoryChanges, List propertyFileInfoCollection, List propertyCollection, List>> metadataCollections, List> resizeKeyValuePairs, List> imageFaceCollections, string sourceDirectory, int index, PropertyHolder propertyHolder) { + if (propertyHolder.FileInfo is null) + throw new Exception($"{nameof(propertyHolder.FileInfo)} is null!"); if (_AppSettings.MaxDegreeOfParallelism is null) throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!"); if (_Configuration.SaveResizedSubfiles is null) @@ -373,6 +309,7 @@ public class DlibDotNet throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); if (_Configuration.PropertyConfiguration.WriteBitmapDataBytes is null) throw new Exception($"{nameof(_Configuration.PropertyConfiguration.WriteBitmapDataBytes)} is null!"); + A_Property property; List faceCollection; string original = "Original"; long ticks = DateTime.Now.Ticks; @@ -381,29 +318,36 @@ public class DlibDotNet Dictionary imageResizeKeyValuePairs; List> subFileTuples = new(); List> metadataCollection; - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filteredSourceDirectoryFile); - string relativePath = Property.Models.Stateless.IPath.GetRelativePath(filteredSourceDirectoryFile, _Configuration.PropertyConfiguration.RootDirectory.Length); - FileInfo propertyFileInfo = new(Path.Combine(propertyLogic.AngleBracketCollection[0].Replace("<>", "{}"), string.Concat(fileNameWithoutExtension, ".json"))); - A_Property property = propertyLogic.GetProperty(propertyLogic.AngleBracketCollection[0], sourceDirectory, filteredSourceDirectoryFile, subFileTuples, parseExceptions, propertyFileInfo); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(PropertyLogic.GetProperty)); - (int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(subFileTuples, parseExceptions, filteredSourceDirectoryFile, relativePath, fileNameWithoutExtension); + if (propertyHolder.Property is null) + { + sourceDirectoryChanges.Add(new Tuple(nameof(A_Property), propertyHolder.FileInfo.LastWriteTime)); + property = propertyLogic.GetProperty(propertyLogic.AngleBracketCollection[0], sourceDirectory, propertyHolder.FileInfo.FullName, subFileTuples, parseExceptions, propertyHolder.FileInfo); + } + else + { + property = propertyHolder.Property; + if (propertyHolder.Changed.HasValue && propertyHolder.Changed.Value) + sourceDirectoryChanges.Add(new Tuple(nameof(A_Property), propertyHolder.FileInfo.LastWriteTime)); + } + string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(propertyHolder.FileInfo.FullName); + (int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(subFileTuples, parseExceptions, propertyHolder.FileInfo.FullName, propertyHolder.RelativePath, fileNameWithoutExtension); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection)); - FileInfo resizedFileInfo = new(Path.Combine(_Resize.AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(filteredSourceDirectoryFile))); - imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(subFileTuples, parseExceptions, original, metadataCollection, property, filteredSourceDirectoryFile, relativePath, fileNameWithoutExtension); + FileInfo resizedFileInfo = new(Path.Combine(_Resize.AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(propertyHolder.FileInfo.FullName))); + propertyHolder.SetResizedFileInfo(resizedFileInfo); + imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(subFileTuples, parseExceptions, original, metadataCollection, property, propertyHolder.FileInfo.FullName, propertyHolder.RelativePath, fileNameWithoutExtension); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(C_Resize.GetResizeKeyValuePairs)); if (_Configuration.SaveResizedSubfiles.Value) { - _Resize.SaveResizedSubfile(outputResolution, subFileTuples, filteredSourceDirectoryFile, original, property, imageResizeKeyValuePairs, resizedFileInfo); + _Resize.SaveResizedSubfile(outputResolution, subFileTuples, propertyHolder.FileInfo.FullName, original, property, imageResizeKeyValuePairs, resizedFileInfo); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(C_Resize.SaveResizedSubfile)); resizedFileInfo.Refresh(); } else if (outputResolution == _Configuration.OutputResolutions[0] && false) { - byte[] bytes = _Resize.GetResizedBytes(outputResolution, subFileTuples, filteredSourceDirectoryFile, property, imageResizeKeyValuePairs); + byte[] bytes = _Resize.GetResizedBytes(outputResolution, subFileTuples, propertyHolder.FileInfo.FullName, property, imageResizeKeyValuePairs); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(C_Resize.GetResizedBytes)); string path = Path.Combine(resizedFileInfo.DirectoryName, Path.GetFileNameWithoutExtension(resizedFileInfo.Name)); @@ -417,15 +361,15 @@ public class DlibDotNet int outputResolutionWidth = outputResolutionCollection[0]; int outputResolutionHeight = outputResolutionCollection[1]; int outputResolutionOrientation = outputResolutionCollection[2]; - faceCollection = _Faces.GetFaces(_Configuration.PropertyConfiguration, outputResolution, subFileTuples, parseExceptions, relativePath, fileNameWithoutExtension, property, resizedFileInfo, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); + faceCollection = _Faces.GetFaces(_Configuration.PropertyConfiguration, outputResolution, subFileTuples, parseExceptions, propertyHolder.RelativePath, fileNameWithoutExtension, property, resizedFileInfo, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(D_Face.GetFaces)); - _Faces.SaveFaces(_Configuration.PropertyConfiguration, subFileTuples, parseExceptions, relativePath, fileNameWithoutExtension, resizedFileInfo, faceCollection); + _Faces.SaveFaces(_Configuration.PropertyConfiguration, subFileTuples, parseExceptions, propertyHolder.RelativePath, fileNameWithoutExtension, resizedFileInfo, faceCollection); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(D_Face.SaveFaces)); if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) { - _FaceLandmarks.SaveFaceLandmarkImages(subFileTuples, parseExceptions, relativePath, fileNameWithoutExtension, resizedFileInfo, faceCollection); + _FaceLandmarks.SaveFaceLandmarkImages(subFileTuples, parseExceptions, propertyHolder.RelativePath, fileNameWithoutExtension, resizedFileInfo, faceCollection); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(D2_FaceLandmarks.SaveFaceLandmarkImages)); } @@ -435,12 +379,55 @@ public class DlibDotNet propertyCollection[index] = property; imageFaceCollections[index] = faceCollection; metadataCollections[index] = metadataCollection; - propertyFileInfoCollection[index] = propertyFileInfo; resizeKeyValuePairs[index] = imageResizeKeyValuePairs; + propertyFileInfoCollection[index] = propertyHolder.FileInfo; sourceDirectoryChanges.AddRange(from l in subFileTuples where l.Item2 > dateTime select l); } } + private int FullParallelWork(object @lock, long ticks, PropertyLogic propertyLogic, string outputResolution, List> sourceDirectoryChanges, List propertyFileInfoCollection, List propertyCollection, List>> metadataCollection, List> resizeKeyValuePairs, List> faceCollections, int propertyHolderCollectionsCount, int g, string sourceDirectory, int r, PropertyHolder[] filteredPropertyHolderCollection) + { + int result = 0; + if (_Log is null) + throw new Exception($"{nameof(_Log)} is null!"); + if (_AppSettings.MaxDegreeOfParallelism is null) + throw new Exception($"{nameof(AppSettings.MaxDegreeOfParallelism)} is null!"); + ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism.Value }; + ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; + if (faceCollections.Count != filteredPropertyHolderCollection.Length || metadataCollection.Count != filteredPropertyHolderCollection.Length || resizeKeyValuePairs.Count != filteredPropertyHolderCollection.Length || propertyCollection.Count != filteredPropertyHolderCollection.Length) + { + for (int i = 0; i < filteredPropertyHolderCollection.Length; i++) + { + faceCollections.Add(new()); + metadataCollection.Add(new()); + resizeKeyValuePairs.Add(new()); + propertyCollection.Add(new()); + propertyFileInfoCollection.Add(null); + } + } + int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); + using (ProgressBar progressBar = new(filteredPropertyHolderCollection.Length, $"{r + 1:000}.{g} / {propertyHolderCollectionsCount:000}) {filteredPropertyHolderCollection.Length:000} file(s) - {totalSeconds} total second(s) - {outputResolution} - {sourceDirectory}", options)) + { + _ = Parallel.For(0, filteredPropertyHolderCollection.Length, parallelOptions, i => + { + try + { + FullParallelForWork(propertyLogic, @lock, outputResolution, sourceDirectoryChanges, propertyFileInfoCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, faceCollections, sourceDirectory, index: i, filteredPropertyHolderCollection[i]); + if (sourceDirectoryChanges.Any()) + progressBar.Tick(); + } + catch (Exception ex) + { + result += 1; + _Log.Error(string.Concat(sourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex); + if (result == filteredPropertyHolderCollection.Length) + throw new Exception(string.Concat("All in [", sourceDirectory, "] failed!")); + } + }); + } + return result; + } + private static void WriteTab(string checkDirectory, List<(string Id, string Line)> metadataIdLines, string fileName) { string text; @@ -476,14 +463,12 @@ public class DlibDotNet } } - private void WriteGroup(PropertyLogic propertyLogic, List propertyCollection, List>> metadataCollection, List> faceCollections, List> resizeKeyValuePairs, string sourceDirectory, string[] filteredSourceDirectoryFiles) + private void WriteGroup(Property.Models.Configuration configuration, PropertyLogic propertyLogic, List propertyCollection, List>> metadataCollection, List> faceCollections, List> resizeKeyValuePairs, string sourceDirectory, PropertyHolder[] filteredPropertyHolderCollection) { if (_Configuration.PropertiesChangedForMetadata is null) throw new Exception($"{nameof(_Configuration.PropertiesChangedForMetadata)} is null!"); - if (_Configuration?.PropertyConfiguration is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); - if (_Configuration.PropertyConfiguration.PropertiesChangedForProperty is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.PropertiesChangedForProperty)} is null!"); + if (configuration.PropertiesChangedForProperty is null) + throw new Exception($"{nameof(configuration.PropertiesChangedForProperty)} is null!"); if (_Configuration.PropertiesChangedForResize is null) throw new Exception($"{nameof(_Configuration.PropertiesChangedForResize)} is null!"); if (_Configuration.PropertiesChangedForFaces is null) @@ -491,8 +476,10 @@ public class DlibDotNet string key; string json; string checkFile; + PropertyHolder propertyHolder; int sourceDirectoryLength = sourceDirectory.Length; - int rootDirectoryLength = _Configuration.PropertyConfiguration.RootDirectory.Length; + int rootDirectoryLength = configuration.RootDirectory.Length; + _FilePropertiesKeyValuePairs.Add(sourceDirectory, new List>()); JsonSerializerOptions writeIndentedJsonSerializerOptions = new() { WriteIndented = false }; if (!(from l in propertyCollection where l?.Width is null select true).Any()) { @@ -501,11 +488,18 @@ public class DlibDotNet List> propertyCollectionKeyValuePairs = new(); List>> resizeKeyValuePairsCollections = new(); List>>> metadataCollectionKeyValuePairs = new(); - (int level, List directories) = Property.Models.Stateless.IPath.Get(_Configuration.PropertyConfiguration.RootDirectory, sourceDirectory); - string fileName = string.Concat(string.Join(_Configuration.PropertyConfiguration.FileNameDirectorySeparator, directories), ".json"); - for (int i = 0; i < filteredSourceDirectoryFiles.Length; i++) + (int level, List directories) = Property.Models.Stateless.IPath.Get(configuration.RootDirectory, sourceDirectory); + string fileName = string.Concat(string.Join(configuration.FileNameDirectorySeparator, directories), ".json"); + for (int i = 0; i < filteredPropertyHolderCollection.Length; i++) { - key = Property.Models.Stateless.IPath.GetRelativePath(filteredSourceDirectoryFiles[i], sourceDirectoryLength); + propertyHolder = filteredPropertyHolderCollection[i]; + if (propertyHolder.Property is null) + continue; + if (propertyHolder.FileInfo is null) + continue; + key = Property.Models.Stateless.IPath.GetRelativePath(propertyHolder.FileInfo.FullName, sourceDirectoryLength); + _FileKeyValuePairs.Add(new KeyValuePair(sourceDirectory, key)); + _FilePropertiesKeyValuePairs[sourceDirectory].Add(new Tuple(key, propertyCollection[i])); faceCollectionsKeyValuePairs.Add(new KeyValuePair>(key, faceCollections[i])); propertyCollectionKeyValuePairs.Add(new KeyValuePair(key, propertyCollection[i])); resizeKeyValuePairsCollections.Add(new KeyValuePair>(key, resizeKeyValuePairs[i])); @@ -554,131 +548,135 @@ public class DlibDotNet } } - private void FullDoWork(List topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection) + private void FullDoWork(Property.Models.Configuration configuration, string[] juliePhares, Model model, PredictorModel predictorModel, string argZero, Person[] people, PropertyLogic propertyLogic, List propertyHolderCollections) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); if (_AppSettings.MaxDegreeOfParallelism is null) throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!"); - if (_Configuration?.PropertyConfiguration is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); - if (_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime)} is null!"); if (_Configuration.LoadOrCreateThenSaveImageFacesResults is null) throw new Exception($"{nameof(_Configuration.LoadOrCreateThenSaveImageFacesResults)} is null!"); if (_Configuration.LoadOrCreateThenSaveDirectoryDistanceResults is null) throw new Exception($"{nameof(_Configuration.LoadOrCreateThenSaveDirectoryDistanceResults)} is null!"); if (_Configuration.LoadOrCreateThenSaveDistanceResults is null) throw new Exception($"{nameof(_Configuration.LoadOrCreateThenSaveDistanceResults)} is null!"); - if (_Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!"); - if (_Configuration.PropertyConfiguration.PopulatePropertyId is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.PopulatePropertyId)} is null!"); - if (_Configuration.PropertyConfiguration.PropertiesChangedForProperty is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.PropertiesChangedForProperty)} is null!"); - if (_Configuration.PropertyConfiguration.WriteBitmapDataBytes is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.WriteBitmapDataBytes)} is null!"); + int g; + int r; int exceptionCount; object @lock = new(); + string sourceDirectory; long ticks = DateTime.Now.Ticks; - string[] filteredSourceDirectoryFiles; + string modelName = model.ToString(); List> faceCollections = new(); List propertyCollection = new(); - PropertyLogic propertyLogic = GetPropertyLogic(); + PropertyHolder[] filteredPropertyHolderCollection; List propertyFileInfoCollection = new(); + string predictorModelName = predictorModel.ToString(); List> resizeKeyValuePairs = new(); List> sourceDirectoryChanges = new(); - string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property)); List>> metadataCollection = new(); + string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); + string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, nameof(A_Property)); foreach (string outputResolution in _Configuration.OutputResolutions) { _FileKeyValuePairs.Clear(); _FilePropertiesKeyValuePairs.Clear(); - foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection) + foreach (PropertyHolder[] propertyHolderCollection in propertyHolderCollections) { - if (!topDirectories.Any()) + if (!propertyHolderCollection.Any()) continue; + if (!_ArgZeroIsConfigurationRootDirectory && !propertyHolderCollection[0].SourceDirectory.StartsWith(argZero)) + continue; + filteredPropertyHolderCollection = (from l in propertyHolderCollection where l.FileInfo is not null && l.Property is not null && l.ValidImageFormatExtension.HasValue && l.ValidImageFormatExtension.Value && !_Configuration.IgnoreExtensions.Contains(l.FileInfo.Extension) select l).ToArray(); + if (!filteredPropertyHolderCollection.Any()) + continue; + faceCollections.Clear(); + metadataCollection.Clear(); + propertyCollection.Clear(); + resizeKeyValuePairs.Clear(); + sourceDirectoryChanges.Clear(); + propertyFileInfoCollection.Clear(); _Faces.AngleBracketCollection.Clear(); _Resize.AngleBracketCollection.Clear(); _Metadata.AngleBracketCollection.Clear(); + g = filteredPropertyHolderCollection[0].G; + r = filteredPropertyHolderCollection[0].R; propertyLogic.AngleBracketCollection.Clear(); _FaceLandmarks.AngleBracketCollection.Clear(); - filteredSourceDirectoryFiles = (from l in sourceDirectoryFiles where !_Configuration.IgnoreExtensions.Contains(Path.GetExtension(l)) select l).ToArray(); - if (!filteredSourceDirectoryFiles.Any()) - continue; - propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, - sourceDirectory, - nameof(A_Property), - outputResolution, - includeResizeGroup: false, - includeModel: false, - includePredictorModel: false, - contentDescription: string.Empty, - singletonDescription: "Properties for each image", - collectionDescription: string.Empty)); - _Metadata.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, - sourceDirectory, - nameof(B_Metadata), - outputResolution, - includeResizeGroup: false, - includeModel: false, - includePredictorModel: false, - contentDescription: string.Empty, - singletonDescription: "Metadata as key value pairs", - collectionDescription: string.Empty)); - _Resize.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, - sourceDirectory, - nameof(C_Resize), - outputResolution, - includeResizeGroup: true, - includeModel: false, - includePredictorModel: false, - contentDescription: "Resized image", - singletonDescription: "Resize deminsions for each resolution", - collectionDescription: string.Empty)); - if (_Configuration.LoadOrCreateThenSaveImageFacesResults.HasValue && _Configuration.LoadOrCreateThenSaveImageFacesResults.Value) - _Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, - sourceDirectory, - nameof(D_Face), - outputResolution, - includeResizeGroup: true, - includeModel: true, - includePredictorModel: true, - contentDescription: "n png file(s) for each face found", - singletonDescription: string.Empty, - collectionDescription: "For each image a json file with all faces found")); - if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) - _FaceLandmarks.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, + sourceDirectory = filteredPropertyHolderCollection[0].SourceDirectory; + propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, + modelName, + predictorModelName, sourceDirectory, - nameof(D2_FaceLandmarks), + nameof(A_Property), outputResolution, - includeResizeGroup: true, - includeModel: true, - includePredictorModel: true, - contentDescription: "n x 2 png file(s) for each face found", - singletonDescription: string.Empty, + includeResizeGroup: false, + includeModel: false, + includePredictorModel: false, + contentDescription: string.Empty, + singletonDescription: "Properties for each image", collectionDescription: string.Empty)); - exceptionCount = FullParallelWork(@lock, ticks, propertyLogic, outputResolution, sourceDirectoryChanges, propertyFileInfoCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, faceCollections, g, sourceDirectory, r, filteredSourceDirectoryFiles, groupCollection.Count); - if (metadataCollection.Count != filteredSourceDirectoryFiles.Length || propertyCollection.Count != filteredSourceDirectoryFiles.Length || resizeKeyValuePairs.Count != filteredSourceDirectoryFiles.Length || faceCollections.Count != filteredSourceDirectoryFiles.Length) + _Metadata.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, + modelName, + predictorModelName, + sourceDirectory, + nameof(B_Metadata), + outputResolution, + includeResizeGroup: false, + includeModel: false, + includePredictorModel: false, + contentDescription: string.Empty, + singletonDescription: "Metadata as key value pairs", + collectionDescription: string.Empty)); + _Resize.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, + modelName, + predictorModelName, + sourceDirectory, + nameof(C_Resize), + outputResolution, + includeResizeGroup: true, + includeModel: false, + includePredictorModel: false, + contentDescription: "Resized image", + singletonDescription: "Resize dimensions for each resolution", + collectionDescription: string.Empty)); + if (_Configuration.LoadOrCreateThenSaveImageFacesResults.HasValue && _Configuration.LoadOrCreateThenSaveImageFacesResults.Value) + _Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, + modelName, + predictorModelName, + sourceDirectory, + nameof(D_Face), + outputResolution, + includeResizeGroup: true, + includeModel: true, + includePredictorModel: true, + contentDescription: "n png file(s) for each face found", + singletonDescription: string.Empty, + collectionDescription: "For each image a json file with all faces found")); + if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) + _FaceLandmarks.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, + modelName, + predictorModelName, + sourceDirectory, + nameof(D2_FaceLandmarks), + outputResolution, + includeResizeGroup: true, + includeModel: true, + includePredictorModel: true, + contentDescription: "n x 2 png file(s) for each face found", + singletonDescription: string.Empty, + collectionDescription: string.Empty)); + exceptionCount = FullParallelWork(@lock, ticks, propertyLogic, outputResolution, sourceDirectoryChanges, propertyFileInfoCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, faceCollections, propertyHolderCollections.Count, g, sourceDirectory, r, filteredPropertyHolderCollection); + if (metadataCollection.Count != filteredPropertyHolderCollection.Length || propertyCollection.Count != filteredPropertyHolderCollection.Length || resizeKeyValuePairs.Count != filteredPropertyHolderCollection.Length || faceCollections.Count != filteredPropertyHolderCollection.Length) throw new Exception("Counts don't match!"); if (exceptionCount != 0) _Exceptions.Add(sourceDirectory); - else - { - string key; - int rootDirectoryLength = _Configuration.PropertyConfiguration.RootDirectory.Length; - _FilePropertiesKeyValuePairs.Add(sourceDirectory, new List>()); - for (int i = 0; i < filteredSourceDirectoryFiles.Length; i++) - { - key = Property.Models.Stateless.IPath.GetRelativePath(filteredSourceDirectoryFiles[i], rootDirectoryLength); - _FileKeyValuePairs.Add(new KeyValuePair(sourceDirectory, key)); - _FilePropertiesKeyValuePairs[sourceDirectory].Add(new Tuple(key, propertyCollection[i])); - } - } if (exceptionCount == 0 && _ArgZeroIsConfigurationRootDirectory) - WriteGroup(propertyLogic, propertyCollection, metadataCollection, faceCollections, resizeKeyValuePairs, sourceDirectory, filteredSourceDirectoryFiles); + WriteGroup(configuration, propertyLogic, propertyCollection, metadataCollection, faceCollections, resizeKeyValuePairs, sourceDirectory, filteredPropertyHolderCollection); + if (exceptionCount == 0 && _Configuration.LoadOrCreateThenSaveImageFacesResults.Value && _Configuration.SaveShortcuts.HasValue && _Configuration.SaveShortcuts.Value) + _Faces.SaveShortcuts(configuration, juliePhares, model, predictorModel, people, propertyLogic, outputResolution, filteredPropertyHolderCollection, propertyCollection, faceCollections); if (exceptionCount == 0 && _Configuration.LoadOrCreateThenSaveDistanceResults.HasValue && _Configuration.LoadOrCreateThenSaveDistanceResults.Value) - _Distance.LoadOrCreateThenSaveDistanceResults(_Configuration.PropertyConfiguration, sourceDirectory, outputResolution, sourceDirectoryChanges, filteredSourceDirectoryFiles, faceCollections); + _Distance.LoadOrCreateThenSaveDistanceResults(configuration, model, predictorModel, sourceDirectory, outputResolution, sourceDirectoryChanges, filteredPropertyHolderCollection, faceCollections); if (_Resize.AngleBracketCollection.Any()) _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(_Resize.AngleBracketCollection[0].Replace("<>", "()")); if (_Faces.AngleBracketCollection.Any()) @@ -690,7 +688,7 @@ public class DlibDotNet for (int y = 0; y < int.MaxValue; y++) { _Log.Information("Press \"Y\" key when ready to continue or close console"); - if (Console.ReadKey().Key == ConsoleKey.Y) + if (System.Console.ReadKey().Key == ConsoleKey.Y) break; } _Log.Information(". . ."); @@ -698,31 +696,20 @@ public class DlibDotNet } if (_ArgZeroIsConfigurationRootDirectory && outputResolution == _Configuration.OutputResolutions[0]) { - int loadLessThan = 7; - string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "{}"); - PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration); - PropertyCompare.Models.PropertyCompare[] propertyCompares = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan); - { - string[] lines = (from l in propertyCompares select l.GetSelect()).ToArray(); - string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "[{}]"); - File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines); - string json = JsonSerializer.Serialize(propertyCompares, new JsonSerializerOptions { WriteIndented = true }); - File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json); - } if (!_Configuration.LoadOrCreateThenSaveImageFacesResults.Value && !_Configuration.LoadOrCreateThenSaveDirectoryDistanceResults.Value && !_Configuration.LoadOrCreateThenSaveDistanceResults.Value) break; if (_Exceptions.Count == 0) { if (_FileKeyValuePairs.Any()) - _Random.Random(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], _FileKeyValuePairs); + _Random.Random(configuration, _Configuration.OutputResolutions[0], _FileKeyValuePairs); if (_IsEnvironment.Development) continue; G2_Identify identify = new(_Configuration); - List identifiedCollection = identify.GetIdentifiedCollection(_Configuration.PropertyConfiguration, _IsEnvironment, _People); - _People.WriteAllText(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], identifiedCollection); - identify.WriteAllText(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], identifiedCollection); + 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.PropertyConfiguration, _Configuration.OutputResolutions[0], _FilePropertiesKeyValuePairs); + _Index.SetIndex(configuration, model, predictorModel, _Configuration.OutputResolutions[0], _FilePropertiesKeyValuePairs); } } } @@ -731,66 +718,21 @@ public class DlibDotNet private PropertyLogic GetPropertyLogic() { PropertyLogic result; - - - string[] verifyToSeason = Array.Empty(); - - if (_AppSettings.MaxDegreeOfParallelism is null) throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!"); if (_Configuration?.PropertyConfiguration is null) throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); - result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, verifyToSeason); + result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration); return result; } - private void Search(string argZero) + private void Search(Property.Models.Configuration configuration, string[] juliePhares, bool reverse, Model model, PredictorModel predictorModel, string argZero, Person[] people) { - if (_Log is null) - throw new Exception($"{nameof(_Log)} is null!"); - if (_AppSettings.MaxDegreeOfParallelism is null) - throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!"); - if (_Configuration?.PropertyConfiguration is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); - if (_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime)} is null!"); - if (_Configuration.PropertyConfiguration.IgnoreExtensions is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.IgnoreExtensions)} is null!"); - if (_Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!"); - if (_Configuration.PropertyConfiguration.PopulatePropertyId is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.PopulatePropertyId)} is null!"); - if (_Configuration.PropertyConfiguration.PropertiesChangedForProperty is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.PropertiesChangedForProperty)} is null!"); - if (_Configuration.Reverse is null) - throw new Exception($"{nameof(_Configuration.Reverse)} is null!"); - if (_Configuration.PropertyConfiguration.WriteBitmapDataBytes is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration.WriteBitmapDataBytes)} is null!"); - string searchPattern = "*"; - long ticks = DateTime.Now.Ticks; - List topDirectories = new(); PropertyLogic propertyLogic = GetPropertyLogic(); - List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(argZero, searchPattern, topDirectories, _Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, _Configuration.Reverse.Value); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); - _Exceptions.AddRange(propertyLogic.DoWork(_Configuration.PropertyConfiguration, topDirectories, groupCollection, firstPass: true)); - string message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}"; - _Log.Information(message); - if (_Exceptions.Count != 0) - throw new Exception(message); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); - groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(argZero, searchPattern, topDirectories, _Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, _Configuration.Reverse.Value); - if (_AppSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); - FullDoWork(topDirectories, groupCollection); + List propertyHolderCollections = Property.Models.Stateless.A_Property.Get(configuration, reverse, model.ToString(), predictorModel.ToString(), propertyLogic); + FullDoWork(configuration, juliePhares, model, predictorModel, argZero, people, propertyLogic, propertyHolderCollections); } - internal void RenameQueue() - { - if (_Configuration?.PropertyConfiguration is null) - throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); - _Rename.RenameQueue(_Configuration.PropertyConfiguration); - } + 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/Instance.csproj b/Instance/Instance.csproj index a8703a8..7376eee 100644 --- a/Instance/Instance.csproj +++ b/Instance/Instance.csproj @@ -50,6 +50,7 @@ + diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index e69ab67..f2f6f9b 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -13,7 +13,8 @@ public class Configuration [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; } [Display(Name = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; } - [Display(Name = "Load Or Create Then Save Directroy Distance Results"), Required] public bool? LoadOrCreateThenSaveDirectoryDistanceResults { get; set; } + [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; } + [Display(Name = "Load Or Create Then Save Directory Distance Results"), Required] public bool? LoadOrCreateThenSaveDirectoryDistanceResults { get; set; } [Display(Name = "Load Or Create Then Save Distance Results"), Required] public bool? LoadOrCreateThenSaveDistanceResults { get; set; } [Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public bool? LoadOrCreateThenSaveImageFacesResults { get; set; } [Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; } @@ -42,7 +43,7 @@ public class Configuration [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; } [Display(Name = "Save Resized Subfiles"), Required] public bool? SaveResizedSubfiles { get; set; } - [Display(Name = "Search for Abandoned Files"), Required] public bool? SearchForAbandonedFilesFull { get; set; } + [Display(Name = "Save Shortcuts"), Required] public bool? SaveShortcuts { get; set; } [Display(Name = "Skip Search"), Required] public bool? SkipSearch { get; set; } [Display(Name = "Test Distance Results"), Required] public bool? TestDistanceResults { get; set; } [Display(Name = "Valid Resolutions"), Required] public string[] ValidResolutions { get; set; } @@ -56,6 +57,7 @@ public class Configuration ForceResizeLastWriteTimeToCreationTime = null; IgnoreExtensions = Array.Empty(); IgnoreRelativePaths = Array.Empty(); + JuliePhares = Array.Empty(); LoadOrCreateThenSaveDirectoryDistanceResults = null; LoadOrCreateThenSaveDistanceResults = null; LoadOrCreateThenSaveImageFacesResults = null; @@ -84,7 +86,7 @@ public class Configuration SaveFaceLandmarkForOutputResolutions = Array.Empty(); SaveFullYearOfRandomFiles = null; SaveResizedSubfiles = null; - SearchForAbandonedFilesFull = null; + SaveShortcuts = null; SkipSearch = null; TestDistanceResults = null; ValidResolutions = Array.Empty(); diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index facb9e1..4337c1e 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -13,6 +13,7 @@ public class Configuration protected readonly bool? _ForceResizeLastWriteTimeToCreationTime; protected readonly string[] _IgnoreExtensions; protected readonly string[] _IgnoreRelativePaths; + protected readonly string[] _JuliePhares; protected readonly bool? _LoadOrCreateThenSaveDirectoryDistanceResults; protected readonly bool? _LoadOrCreateThenSaveDistanceResults; protected readonly bool? _LoadOrCreateThenSaveImageFacesResults; @@ -42,7 +43,7 @@ public class Configuration protected readonly string[] _SaveFaceLandmarkForOutputResolutions; protected readonly bool? _SaveFullYearOfRandomFiles; protected readonly bool? _SaveResizedSubfiles; - protected readonly bool? _SearchForAbandonedFiles; + protected readonly bool? _SaveShortcuts; protected readonly bool? _SkipSearch; protected readonly bool? _TestDistanceResults; protected readonly string[] _ValidResolutions; @@ -53,6 +54,7 @@ public class Configuration public bool? ForceResizeLastWriteTimeToCreationTime => _ForceResizeLastWriteTimeToCreationTime; public string[] IgnoreExtensions => _IgnoreExtensions; public string[] IgnoreRelativePaths => _IgnoreRelativePaths; + public string[] JuliePhares => _JuliePhares; public bool? LoadOrCreateThenSaveDirectoryDistanceResults => _LoadOrCreateThenSaveDirectoryDistanceResults; public bool? LoadOrCreateThenSaveDistanceResults => _LoadOrCreateThenSaveDistanceResults; public bool? LoadOrCreateThenSaveImageFacesResults => _LoadOrCreateThenSaveImageFacesResults; @@ -82,13 +84,13 @@ public class Configuration public string[] SaveFaceLandmarkForOutputResolutions => _SaveFaceLandmarkForOutputResolutions; public bool? SaveFullYearOfRandomFiles => _SaveFullYearOfRandomFiles; public bool? SaveResizedSubfiles => _SaveResizedSubfiles; - public bool? SearchForAbandonedFilesFull => _SearchForAbandonedFiles; + public bool? SaveShortcuts => _SaveShortcuts; public bool? SkipSearch => _SkipSearch; public bool? TestDistanceResults => _TestDistanceResults; public string[] ValidResolutions => _ValidResolutions; [JsonConstructor] - public Configuration(bool? checkJsonForDistanceResults, int? crossDirectoryMaxItemsInDistanceCollection, int? distanceFactor, bool? forceMetadataLastWriteTimeToCreationTime, bool? forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, bool? loadOrCreateThenSaveDirectoryDistanceResults, bool? loadOrCreateThenSaveDistanceResults, bool? loadOrCreateThenSaveImageFacesResults, bool? loadOrCreateThenSaveIndex, int? locationConfidenceFactor, int? mappedMaxIndex, int? maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int? numJitters, 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, bool? searchForAbandonedFilesFull, bool? skipSearch, bool? testDistanceResults, string[] validResolutions) + public Configuration(bool? checkJsonForDistanceResults, int? crossDirectoryMaxItemsInDistanceCollection, int? distanceFactor, bool? forceMetadataLastWriteTimeToCreationTime, bool? forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, bool? loadOrCreateThenSaveDirectoryDistanceResults, bool? loadOrCreateThenSaveDistanceResults, bool? loadOrCreateThenSaveImageFacesResults, bool? loadOrCreateThenSaveIndex, int? locationConfidenceFactor, int? mappedMaxIndex, int? maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int? numJitters, 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, bool? saveShortcuts, bool? skipSearch, bool? testDistanceResults, string[] validResolutions) { _CheckJsonForDistanceResults = checkJsonForDistanceResults; _CrossDirectoryMaxItemsInDistanceCollection = crossDirectoryMaxItemsInDistanceCollection; @@ -97,6 +99,7 @@ public class Configuration _ForceResizeLastWriteTimeToCreationTime = forceResizeLastWriteTimeToCreationTime; _IgnoreExtensions = ignoreExtensions; _IgnoreRelativePaths = ignoreRelativePaths; + _JuliePhares = juliePhares; _LoadOrCreateThenSaveDirectoryDistanceResults = loadOrCreateThenSaveDirectoryDistanceResults; _LoadOrCreateThenSaveDistanceResults = loadOrCreateThenSaveDistanceResults; _LoadOrCreateThenSaveImageFacesResults = loadOrCreateThenSaveImageFacesResults; @@ -126,7 +129,7 @@ public class Configuration _SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions; _SaveFullYearOfRandomFiles = saveFullYearOfRandomFiles; _SaveResizedSubfiles = saveResizedSubfiles; - _SearchForAbandonedFiles = searchForAbandonedFilesFull; + _SaveShortcuts = saveShortcuts; _SkipSearch = skipSearch; _TestDistanceResults = testDistanceResults; _ValidResolutions = validResolutions; @@ -138,7 +141,7 @@ public class Configuration return result; } - public void Set(Property.Models.Configuration propertyConfiguration) => _PropertyConfiguration = propertyConfiguration; + public void Set(Property.Models.Configuration configuration) => _PropertyConfiguration = configuration; public void Update() => _PropertyConfiguration?.Update(); diff --git a/Instance/Models/_D_Face.cs b/Instance/Models/_D_Face.cs index fa46b6c..7ac7d02 100644 --- a/Instance/Models/_D_Face.cs +++ b/Instance/Models/_D_Face.cs @@ -3,11 +3,13 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Text.Json; using System.Text.Json.Serialization; +using System.Text.RegularExpressions; using View_by_Distance.Metadata.Models; using View_by_Distance.Property.Models; using View_by_Distance.Resize.Models; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Methods; +using WindowsShortcutFactory; namespace View_by_Distance.Instance.Models; @@ -47,6 +49,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace public string RelativePath => _RelativePath; #nullable disable + [JsonConstructor] public D_Face(double? α, DateTime dateTime, Shared.Models.FaceEncoding faceEncoding, Dictionary faceLandmarks, Shared.Models.Location location, int? locationIndex, OutputResolution outputResolution, bool populated, string relativePath) { @@ -125,22 +128,24 @@ public class D_Face : Shared.Models.Properties.IFace, IFace _RelativePath = face.RelativePath; } - private static void GetPointBounds(PointF[] points, out float xmin, out float xmax, out float ymin, out float ymax) +#nullable restore + + private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum) { - xmin = points[0].X; - xmax = xmin; - ymin = points[0].Y; - ymax = ymin; + xMinimum = points[0].X; + xMaximum = xMinimum; + yMinimum = points[0].Y; + yMaximum = yMinimum; foreach (PointF point in points) { - if (xmin > point.X) - xmin = point.X; - if (xmax < point.X) - xmax = point.X; - if (ymin > point.Y) - ymin = point.Y; - if (ymax < point.Y) - ymax = point.Y; + if (xMinimum > point.X) + xMinimum = point.X; + if (xMaximum < point.X) + xMaximum = point.X; + if (yMinimum > point.Y) + yMinimum = point.Y; + if (yMaximum < point.Y) + yMaximum = point.Y; } } @@ -175,12 +180,12 @@ public class D_Face : Shared.Models.Properties.IFace, IFace new PointF(0, bitmap.Height), }; rotate_at_origin.TransformPoints(points); - float xmin, xmax, ymin, ymax; - GetPointBounds(points, out xmin, out xmax, out ymin, out ymax); + float xMinimum, xMaximum, yMinimum, yMaximum; + GetPointBounds(points, out xMinimum, out xMaximum, out yMinimum, out yMaximum); // Make a bitmap to hold the rotated result. - int wid = (int)Math.Round(xmax - xmin); - int hgt = (int)Math.Round(ymax - ymin); + int wid = (int)Math.Round(xMaximum - xMinimum); + int hgt = (int)Math.Round(yMaximum - yMinimum); result = new Bitmap(wid, hgt); // Create the real rotation transformation. @@ -251,7 +256,8 @@ public class D_Face : Shared.Models.Properties.IFace, IFace if (_Configuration.NumJitters is null) throw new Exception(); FaceRecognitionDotNet.Location[] locations; - FaceRecognitionDotNet.Image unknownImage = null; + const int numberOfTimesToUpSample = 1; + FaceRecognitionDotNet.Image? unknownImage = null; if (resizedFileInfo.Exists) { try @@ -263,7 +269,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace else { FaceRecognition faceRecognition = FaceRecognition.Create(_ModelParameter); - locations = faceRecognition.FaceLocations(unknownImage, numberOfTimesToUpsample: 1, _Model).ToArray(); + locations = faceRecognition.FaceLocations(unknownImage, numberOfTimesToUpSample, _Model).ToArray(); if (!locations.Any()) results.Add(new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, relativePath, i: null, location: null)); else @@ -276,19 +282,19 @@ public class D_Face : Shared.Models.Properties.IFace, IFace int leftEyeY; int rightEyeX; int rightEyeY; + Bitmap rotated; string faceFile; + Bitmap preRotated; Graphics graphics; - D_Face face = null; + D_Face? face = null; Rectangle rectangle; double[] rawEncoding; - Bitmap rotated; - Bitmap preRotated; - FaceRecognitionDotNet.Image knownImage; - FaceRecognitionDotNet.Image rotatedImage; Shared.Models.Location location; + FaceRecognitionDotNet.Image knownImage; + Shared.Models.FaceEncoding faceEncoding; + FaceRecognitionDotNet.Image rotatedImage; FaceRecognitionDotNet.FaceEncoding[] faceEncodings; IEnumerable facePoints; - Shared.Models.FaceEncoding faceEncoding; IDictionary>[] faceLandmarks; using Bitmap source = unknownImage.ToBitmap(); padding = (int)((source.Width + source.Height) / 2 * .01); @@ -380,7 +386,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace internal List GetFaces(Property.Models.Configuration configuration, string outputResolution, List> subFileTuples, List parseExceptions, string relativePath, string fileNameWithoutExtension, A_Property property, FileInfo resizedFileInfo, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation) { - List results; + List? results; if (_Configuration.PropertiesChangedForFaces is null) throw new Exception(); string json; @@ -412,6 +418,8 @@ public class D_Face : Shared.Models.Properties.IFace, IFace try { results = JsonSerializer.Deserialize>(json); + if (results is null) + throw new Exception($"{nameof(results)} is null"); for (int i = 0; i < results.Count; i++) { face = results[i]; @@ -487,6 +495,106 @@ public class D_Face : Shared.Models.Properties.IFace, IFace SaveFaces(faceCollection, resizedFileInfo, imageFiles); } + internal void SaveShortcuts(Property.Models.Configuration configuration, string[] juliePhares, Model model, PredictorModel predictorModel, Person[] people, PropertyLogic propertyLogic, string outputResolution, PropertyHolder[] filteredPropertyHolderCollection, List propertyCollection, List> faceCollections) + { + int oldIndex; + string[] keys; + string fileName; + string fullName; + string personKey; + string directory; + FileInfo fileInfo; + string copyDirectory; + string? relativePath; + List faceCollection; + PropertyHolder propertyHolder; + WindowsShortcut windowsShortcut; + const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]"; + Dictionary> peopleCollection = new(); + foreach (Person person in people) + { + personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(person.Birthday); + if (!peopleCollection.ContainsKey(personKey)) + peopleCollection.Add(personKey, new List()); + peopleCollection[personKey].Add(person); + } + string dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model.ToString(), predictorModel.ToString(), nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "(_)"); + for (int i = 0; i < filteredPropertyHolderCollection.Length; i++) + { + personKey = string.Empty; + copyDirectory = string.Empty; + propertyHolder = filteredPropertyHolderCollection[i]; + if (propertyHolder.FileInfo is null) + continue; + fileInfo = propertyHolder.FileInfo; + relativePath = Path.GetDirectoryName($"C:{propertyHolder.RelativePath}"); + if (string.IsNullOrEmpty(relativePath) || relativePath.Length < 3) + continue; + if (propertyHolder.Property?.Id is null || propertyHolder.MinimumDateTime is null || propertyHolder.ResizedFileInfo is null) + continue; + if (propertyHolder.Property.Indices.Length < 2) + directory = Path.Combine(dFacesContentDirectory, $"New{relativePath[2..]}"); + else + { + oldIndex = propertyHolder.Property.Indices[1]; + if (!propertyLogic.NamedFaceInfo.ContainsKey(oldIndex)) + directory = Path.Combine(dFacesContentDirectory, $"Unnamed{relativePath[2..]}"); + else + { + faceCollection = faceCollections[i]; + keys = propertyLogic.NamedFaceInfo[oldIndex]; + if (!faceCollection.Any()) + directory = Path.Combine(dFacesContentDirectory, $"None{relativePath[2..]}"); + else if (keys.Length != 1) + directory = Path.Combine(dFacesContentDirectory, $"Not Supported{relativePath[2..]}"); + else if (faceCollection.Count == 1) + { + personKey = keys[0]; + if (juliePhares.Contains(personKey)) + copyDirectory = Path.Combine(dFacesContentDirectory, "Named Images"); + directory = Path.Combine(dFacesContentDirectory, "Named Shortcuts", personKey); + } + else if ((from l in faceCollection where HasLeftAndRight(l.FaceLandmarks) select true).Count() == 1) + { + personKey = keys[0]; + if (juliePhares.Contains(personKey)) + copyDirectory = Path.Combine(dFacesContentDirectory, "Named Images^"); + directory = Path.Combine(dFacesContentDirectory, "Named Shortcuts", $"{personKey}^"); + } + else + directory = Path.Combine(dFacesContentDirectory, $"Many{relativePath[2..]}"); + } + } + if (!Directory.Exists(directory)) + { + _ = Directory.CreateDirectory(directory); + if (!string.IsNullOrEmpty(personKey) && peopleCollection.ContainsKey(personKey)) + { + Person person = peopleCollection[personKey][0]; + fullName = Regex.Replace($"{Shared.Models.Stateless.Methods.IPersonName.GetFullName(person.Name)}.txt", pattern, string.Empty); + File.WriteAllText(Path.Combine(directory, fullName), string.Empty); + } + } + if (!string.IsNullOrEmpty(copyDirectory)) + { + if (!Directory.Exists(copyDirectory)) + _ = Directory.CreateDirectory(copyDirectory); + fileName = Path.Combine(copyDirectory, $"{propertyHolder.Property.Id.Value}{propertyHolder.ResizedFileInfo.Extension}"); + if (!File.Exists(fileName)) + File.Copy(propertyHolder.ResizedFileInfo.FullName, fileName); + } + fileName = Path.Combine(directory, $"{propertyHolder.Property.Id.Value}.lnk"); + if (File.Exists(fileName)) + continue; + windowsShortcut = new() { Path = fileInfo.FullName }; + windowsShortcut.Save(fileName); + windowsShortcut.Dispose(); + if (!File.Exists(fileName)) + continue; + File.SetLastWriteTime(fileName, propertyHolder.MinimumDateTime.Value); + } + } + double Shared.Models.Stateless.Methods.IFace.TestStatic_Getα(int x1, int x2, int y1, int y2) => throw new NotImplementedException(); string Shared.Models.Stateless.Methods.IFace.TestStatic_GetJson(string jsonFileFullName) => throw new NotImplementedException(); @@ -495,4 +603,18 @@ public class D_Face : Shared.Models.Properties.IFace, IFace Face[] Shared.Models.Stateless.Methods.IFace.TestStatic_GetFaces(string jsonFileFullName) => throw new NotImplementedException(); + private static bool HasLeftAndRight(Dictionary faceLandmarks) + { + bool result = true; + if (!faceLandmarks.ContainsKey(FacePart.LeftEye.ToString())) + result = false; + else if (!faceLandmarks.ContainsKey(FacePart.RightEye.ToString())) + result = false; + else if (!faceLandmarks.ContainsKey(FacePart.LeftEyebrow.ToString())) + result = false; + else if (!faceLandmarks.ContainsKey(FacePart.RightEyebrow.ToString())) + result = false; + return result; + } + } \ No newline at end of file diff --git a/Instance/Models/_E2_Navigate.cs b/Instance/Models/_E2_Navigate.cs index a6296b4..16b7a8a 100644 --- a/Instance/Models/_E2_Navigate.cs +++ b/Instance/Models/_E2_Navigate.cs @@ -1,3 +1,4 @@ +using FaceRecognitionDotNet; using System.Text.Json; using View_by_Distance.Instance.Models.Stateless; using View_by_Distance.Metadata.Models; @@ -34,7 +35,7 @@ internal class E2_Navigate return result; } - private void DisplayTags(Property.Models.Configuration configuration, string outputResolution, string[] directories, Dictionary directoryKeyValuePairs, string[] files, Dictionary fileKeyValuePairs) + private void DisplayTags(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, string[] directories, Dictionary directoryKeyValuePairs, string[] files, Dictionary fileKeyValuePairs) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -44,10 +45,12 @@ internal class E2_Navigate string? rootResultsDirectory = Path.GetDirectoryName(Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, nameof(B_Metadata))); if (string.IsNullOrEmpty(rootResultsDirectory)) throw new Exception(); + string modelName = model.ToString(); + string predictorModelName = predictorModel.ToString(); string rootResultsDirectoryAbsoluteUri = new Uri(rootResultsDirectory).AbsoluteUri; - string dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); - string cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"); - string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); + string dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); + string cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"); + string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple = new(rootResultsDirectoryAbsoluteUri, cResizeContentDirectory, dFacesContentDirectory, eDistanceCollectionDirectory); List fileSystemCollection = Shared.Models.Stateless.Methods.IFileSystem.GetFileSystemCollection(requestPath, tuple, directories, files, all); Queue queue = new(fileSystemCollection); @@ -67,7 +70,7 @@ internal class E2_Navigate } } - private void DisplayFaces(Property.Models.Configuration configuration, string outputResolution, string selectedFileFullName) + private void DisplayFaces(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, string selectedFileFullName) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -75,10 +78,12 @@ internal class E2_Navigate string? rootResultsDirectory = Path.GetDirectoryName(Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, nameof(B_Metadata))); if (string.IsNullOrEmpty(rootResultsDirectory)) throw new Exception(); + string modelName = model.ToString(); + string predictorModelName = predictorModel.ToString(); string rootResultsDirectoryAbsoluteUri = new Uri(rootResultsDirectory).AbsoluteUri; - string dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); - string cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"); - string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); + string dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); + string cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"); + string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple = new(rootResultsDirectoryAbsoluteUri, cResizeContentDirectory, dFacesContentDirectory, eDistanceCollectionDirectory); FaceFileSystem[] faceFileSystemCollection = Shared.Models.Stateless.Methods.IFaceFileSystem.GetFaceFileSystemCollection(requestPath, tuple, selectedFileFullName); for (int i = 0; i < faceFileSystemCollection.Length; i++) @@ -90,7 +95,7 @@ internal class E2_Navigate // } } - private string Rename(Property.Models.Configuration configuration, string subSourceDirectory) + private string Rename(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string subSourceDirectory) { string result; if (_Log is null) @@ -109,7 +114,7 @@ internal class E2_Navigate else { _Log.Warn(string.Empty); - string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); + string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model.ToString(), predictorModel.ToString(), nameof(E_Distance), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); string relativePath = Property.Models.Stateless.IPath.GetRelativePath(subSourceDirectory, eDistanceCollectionDirectory.Length); if (relativePath.Length == 1) throw new Exception(); @@ -120,7 +125,7 @@ internal class E2_Navigate } else { - _Rename.DirectoryRename(configuration, relativePath, newDirectoryName); + _Rename.DirectoryRename(configuration, model, predictorModel, relativePath, newDirectoryName); _Log.Warn("Renamed..."); string? directoryName = Path.GetDirectoryName(subSourceDirectory); if (string.IsNullOrEmpty(directoryName)) @@ -131,7 +136,7 @@ internal class E2_Navigate return result; } - internal void Navigate(Property.Models.Configuration configuration, string outputResolution) + internal void Navigate(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -143,7 +148,7 @@ internal class E2_Navigate string? subSourceDirectory = string.Empty; Dictionary fileKeyValuePairs = new(); Dictionary directoryKeyValuePairs = new(); - string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), _Configuration.OutputResolutions[0], includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); + string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model.ToString(), predictorModel.ToString(), nameof(E_Distance), _Configuration.OutputResolutions[0], includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); if (!Directory.Exists(eDistanceCollectionDirectory)) _ = Directory.CreateDirectory(eDistanceCollectionDirectory); for (int z = 0; z < int.MaxValue; z++) @@ -161,8 +166,10 @@ internal class E2_Navigate fileKeyValuePairs.Clear(); for (int i = (int)ConsoleKey.A + subDirectories.Length; i < (subFiles.Length + (int)ConsoleKey.A + subDirectories.Length) && i <= (int)ConsoleKey.RightWindows; i++) fileKeyValuePairs.Add((ConsoleKey)i, i - (int)ConsoleKey.A); + if (!directoryKeyValuePairs.Any() && !fileKeyValuePairs.Any()) + break; _Log.Warn(""); - DisplayTags(configuration, outputResolution, subDirectories, directoryKeyValuePairs, subFiles, fileKeyValuePairs); + DisplayTags(configuration, model, predictorModel, outputResolution, subDirectories, directoryKeyValuePairs, subFiles, fileKeyValuePairs); _Log.Warn(string.Empty); _Log.Warn(string.Empty); _Log.Warn(string.Empty); @@ -180,7 +187,7 @@ internal class E2_Navigate } else { - subSourceDirectory = Rename(configuration, subSourceDirectory); + subSourceDirectory = Rename(configuration, model, predictorModel, subSourceDirectory); continue; } } @@ -212,7 +219,7 @@ internal class E2_Navigate { selectedFileFullName = subFiles[fileKeyValuePairs[consoleKey]]; _Log.Warn(string.Concat(">>> [", Path.GetFileName(selectedFileFullName), "]<", selectedFileFullName, ">?")); - DisplayFaces(configuration, outputResolution, selectedFileFullName); + DisplayFaces(configuration, model, predictorModel, outputResolution, selectedFileFullName); _Log.Warn(string.Empty); _Log.Warn(string.Empty); _Log.Warn(string.Empty); diff --git a/Instance/Models/_E3_Rename.cs b/Instance/Models/_E3_Rename.cs index 1d318bd..05a4a4f 100644 --- a/Instance/Models/_E3_Rename.cs +++ b/Instance/Models/_E3_Rename.cs @@ -1,3 +1,4 @@ +using FaceRecognitionDotNet; using System.Text.Json; using View_by_Distance.Metadata.Models; using View_by_Distance.Property.Models; @@ -28,7 +29,7 @@ internal class E3_Rename return result; } - internal string[] GetDirectoryRenameCollection(Property.Models.Configuration configuration, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny) + internal string[] GetDirectoryRenameCollection(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny) { List results = new(); bool add; @@ -41,9 +42,11 @@ internal class E3_Rename string aPropertySingletonDirectory; string bMetadataSingletonDirectory; string eDistanceCollectionDirectory; + string modelName = model.ToString(); string g2IdentifyCollectionDirectory; string d2FaceLandmarksContentDirectory; - add = Directory.Exists(string.Concat(Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"), relativePath)); + string predictorModelName = predictorModel.ToString(); + add = Directory.Exists(string.Concat(Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(C_Resize), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"), relativePath)); bMetadataSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(B_Metadata), "{}"); if (Directory.Exists(bMetadataSingletonDirectory)) { @@ -56,7 +59,7 @@ internal class E3_Rename to = Path.Combine(string.Concat(aPropertySingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(to); } - cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"); + cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(C_Resize), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"); if (Directory.Exists(cResizeContentDirectory)) { to = Path.Combine(string.Concat(cResizeContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); @@ -64,37 +67,37 @@ internal class E3_Rename } foreach (string outputResolution in _Configuration.ValidResolutions) { - cResizeSingletonDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "{}"); + cResizeSingletonDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "{}"); if (Directory.Exists(cResizeSingletonDirectory)) { to = Path.Combine(string.Concat(cResizeSingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(to); } - dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); + dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); if (Directory.Exists(dFacesContentDirectory)) { to = Path.Combine(string.Concat(dFacesContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(to); } - dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); + dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); if (Directory.Exists(dFacesCollectionDirectory)) { to = Path.Combine(string.Concat(dFacesCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(to); } - d2FaceLandmarksContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D2_FaceLandmarks), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); + d2FaceLandmarksContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(D2_FaceLandmarks), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); if (add && _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution) && Directory.Exists(d2FaceLandmarksContentDirectory)) { to = Path.Combine(string.Concat(d2FaceLandmarksContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(to); } - eDistanceContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); + eDistanceContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); if (Directory.Exists(eDistanceContentDirectory)) { to = Path.Combine(string.Concat(eDistanceContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(to); } - eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); + eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); if (Directory.Exists(eDistanceCollectionDirectory)) { to = Path.Combine(string.Concat(eDistanceCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); @@ -110,7 +113,7 @@ internal class E3_Rename return results.ToArray(); } - internal List GetDirectoryRenameCollections(Property.Models.Configuration configuration, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny) + internal List GetDirectoryRenameCollections(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny) { List results = new(); if (_Configuration?.PropertyConfiguration is null) @@ -126,9 +129,11 @@ internal class E3_Rename string eDistanceContentDirectory; string bMetadataSingletonDirectory; string aPropertySingletonDirectory; + string modelName = model.ToString(); string eDistanceCollectionDirectory; string g2IdentifyCollectionDirectory; string d2FaceLandmarksContentDirectory; + string predictorModelName = predictorModel.ToString(); if (!string.IsNullOrEmpty(relativePath)) { from = string.Concat(_Configuration.PropertyConfiguration.RootDirectory, relativePath); @@ -137,7 +142,7 @@ internal class E3_Rename } foreach (string outputResolution in _Configuration.ValidResolutions) { - add = Directory.Exists(string.Concat(Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"), relativePath)); + add = Directory.Exists(string.Concat(Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"), relativePath)); bMetadataSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(B_Metadata), "{}"); from = string.Concat(bMetadataSingletonDirectory, relativePath); exists = Directory.Exists(bMetadataSingletonDirectory); @@ -154,7 +159,7 @@ internal class E3_Rename to = Path.Combine(string.Concat(aPropertySingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(new string[] { from, to }); } - cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"); + cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"); from = string.Concat(cResizeContentDirectory, relativePath); exists = Directory.Exists(cResizeContentDirectory); if (exists) @@ -162,7 +167,7 @@ internal class E3_Rename to = Path.Combine(string.Concat(cResizeContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(new string[] { from, to }); } - cResizeSingletonDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "{}"); + cResizeSingletonDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "{}"); from = string.Concat(cResizeSingletonDirectory, relativePath); exists = Directory.Exists(cResizeSingletonDirectory); if (exists) @@ -170,7 +175,7 @@ internal class E3_Rename to = Path.Combine(string.Concat(cResizeSingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(new string[] { from, to }); } - dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); + dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); from = string.Concat(dFacesContentDirectory, relativePath); exists = Directory.Exists(dFacesContentDirectory); if (exists) @@ -178,7 +183,7 @@ internal class E3_Rename to = Path.Combine(string.Concat(dFacesContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(new string[] { from, to }); } - dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); + dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); from = string.Concat(dFacesCollectionDirectory, relativePath); exists = Directory.Exists(dFacesCollectionDirectory); if (exists) @@ -186,7 +191,7 @@ internal class E3_Rename to = Path.Combine(string.Concat(dFacesCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(new string[] { from, to }); } - d2FaceLandmarksContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D2_FaceLandmarks), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); + d2FaceLandmarksContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(D2_FaceLandmarks), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); from = string.Concat(d2FaceLandmarksContentDirectory, relativePath); exists = Directory.Exists(d2FaceLandmarksContentDirectory); if (!exists && add && _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) @@ -196,7 +201,7 @@ internal class E3_Rename to = Path.Combine(string.Concat(d2FaceLandmarksContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(new string[] { from, to }); } - eDistanceContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); + eDistanceContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); from = string.Concat(eDistanceContentDirectory, relativePath); exists = Directory.Exists(eDistanceContentDirectory); if (exists) @@ -204,7 +209,7 @@ internal class E3_Rename to = Path.Combine(string.Concat(eDistanceContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); results.Add(new string[] { from, to }); } - eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); + eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); from = string.Concat(eDistanceCollectionDirectory, relativePath); exists = Directory.Exists(eDistanceCollectionDirectory); if (exists) @@ -226,7 +231,7 @@ internal class E3_Rename return results; } - internal void DirectoryRename(Property.Models.Configuration configuration, string relativePath, string newDirectoryName) + internal void DirectoryRename(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string relativePath, string newDirectoryName) { if (_Configuration?.PropertyConfiguration is null) throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); @@ -236,7 +241,7 @@ internal class E3_Rename string error = "Error"; string target = "Target"; string pending = "Pending"; - DirectoryInfo directoryInfo; + System.IO.DirectoryInfo directoryInfo; IEnumerator fileInfoCollection; string oldValue = string.Concat("\"", relativePath); string oldDirectoryName = Path.GetFileName(relativePath); @@ -248,7 +253,7 @@ internal class E3_Rename string newValue = string.Concat("\"", Path.Combine(relativePathParent, newDirectoryName)); string e3RenameContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(E3_Rename), "()"); string jsonRootDirectory = Path.Combine(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, " - Copied"), string.Concat(directoryName, " - 4) Info"), _Configuration.PropertyConfiguration.DateGroup, "[]"); - directoryInfo = new DirectoryInfo(jsonRootDirectory); + directoryInfo = new System.IO.DirectoryInfo(jsonRootDirectory); if (!directoryInfo.Exists) directoryInfo.Create(); IEnumerator fileInfoCollection4 = directoryInfo.EnumerateFiles("*.json", SearchOption.AllDirectories).GetEnumerator(); @@ -257,7 +262,7 @@ internal class E3_Rename current = new(string.Empty); else current = fileInfoCollection4.Current; - List directoryCollections = GetDirectoryRenameCollections(configuration, relativePath, newDirectoryName, fileInfoCollection4MoveNext); + List directoryCollections = GetDirectoryRenameCollections(configuration, model, predictorModel, relativePath, newDirectoryName, fileInfoCollection4MoveNext); if ((from l in directoryCollections where l.Length != 2 select true).Any()) throw new Exception(); if (!Directory.Exists(e3RenameContentDirectory)) @@ -277,7 +282,7 @@ internal class E3_Rename { foreach (string[] directoryCollection in directoryCollections) { - directoryInfo = new DirectoryInfo(directoryCollection[0]); + directoryInfo = new System.IO.DirectoryInfo(directoryCollection[0]); if (!directoryInfo.Exists) continue; fileInfoCollection = directoryInfo.EnumerateFiles("*.json", SearchOption.AllDirectories).GetEnumerator(); @@ -314,7 +319,7 @@ internal class E3_Rename } } - internal void RenameQueue(Property.Models.Configuration configuration) + internal void RenameQueue(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel) { string[] lines; string[] segments; @@ -330,7 +335,7 @@ internal class E3_Rename segments = line.Split('\t'); if (segments.Length != 2) throw new Exception(); - DirectoryRename(configuration, segments[0], segments[1]); + DirectoryRename(configuration, model, predictorModel, segments[0], segments[1]); } } } diff --git a/Instance/Models/_E_Distance.cs b/Instance/Models/_E_Distance.cs index 5f91577..cefb581 100644 --- a/Instance/Models/_E_Distance.cs +++ b/Instance/Models/_E_Distance.cs @@ -31,11 +31,11 @@ internal class E_Distance return result; } - private static void LoadFaceEncodingCollections(string[] subFiles, List> faceCollections, List locationIndicesCollection, List faceEncodingCollection, List> faceEncodingCollections) + private static void LoadFaceEncodingCollections(PropertyHolder[] filteredPropertyHolderCollection, List> faceCollections, List locationIndicesCollection, List faceEncodingCollection, List> faceEncodingCollections) { List faceCollection; FaceEncoding faceEncoding; - for (int i = 0; i < subFiles.Length; i++) + for (int i = 0; i < filteredPropertyHolderCollection.Length; i++) { faceCollection = faceCollections[i]; if (!faceCollection.Any()) @@ -169,54 +169,65 @@ internal class E_Distance } } - private void LoadOrCreateThenSaveDistanceResults(Property.Models.Configuration configuration, string[] subFiles, List> faceCollections, List directories) + private void LoadOrCreateThenSaveDistanceResults(Property.Models.Configuration configuration, PropertyHolder[] filteredPropertyHolderCollection, List> faceCollections, List directories) { + FileInfo? fileInfo; string fileNameWithoutExtension; List locationIndicesCollection = new(); List> subFileTuples = new(); List faceEncodingCollection = new(); List> faceEncodingCollections = new(); - LoadFaceEncodingCollections(subFiles, faceCollections, locationIndicesCollection, faceEncodingCollection, faceEncodingCollections); + LoadFaceEncodingCollections(filteredPropertyHolderCollection, 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 < subFiles.Length; i++) + for (int i = 0; i < filteredPropertyHolderCollection.Length; i++) { - fileNameWithoutExtension = Path.GetFileNameWithoutExtension(subFiles[i]); - LoadOrCreateThenSaveDistanceResultsLoop(configuration, faceCollections, subFiles.Length, i, faceCollections[i], locationIndicesCollection, subFileTuples, faceEncodingCollection, faceEncodingCollections[i], fileNameWithoutExtension, directories[i][0], directories[i][1]); + fileInfo = filteredPropertyHolderCollection[i].FileInfo; + if (fileInfo is null) + continue; + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName); + LoadOrCreateThenSaveDistanceResultsLoop(configuration, faceCollections, filteredPropertyHolderCollection.Length, i, faceCollections[i], locationIndicesCollection, subFileTuples, faceEncodingCollection, faceEncodingCollections[i], fileNameWithoutExtension, directories[i][0], directories[i][1]); } } - internal void LoadOrCreateThenSaveDistanceResults(Property.Models.Configuration configuration, string sourceDirectory, string outputResolution, List> sourceDirectoryChanges, string[] subFiles, List> faceCollections) + internal void LoadOrCreateThenSaveDistanceResults(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string sourceDirectory, string outputResolution, List> sourceDirectoryChanges, PropertyHolder[] filteredPropertyHolderCollection, List> faceCollections) { if (_Configuration.CheckJsonForDistanceResults is null) throw new Exception(); if (_Configuration.PropertiesChangedForDistance is null) throw new Exception(); string json; + FileInfo? fileInfo; bool check = false; string parentCheck; - DirectoryInfo directoryInfo; - DirectoryInfo tvsDirectoryInfo; + FileInfo[] fileInfoCollection; + System.IO.DirectoryInfo directoryInfo; + System.IO.DirectoryInfo tvsDirectoryInfo; string fileNameWithoutExtension; List 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(configuration, - sourceDirectory, - nameof(E_Distance), - outputResolution, - includeResizeGroup: true, - includeModel: true, - includePredictorModel: true, - contentDescription: ".tvs File", - singletonDescription: string.Empty, - collectionDescription: "n json file(s) for each face found (one to many)"); - for (int i = 0; i < subFiles.Length; i++) + model.ToString(), + predictorModel.ToString(), + sourceDirectory, + nameof(E_Distance), + outputResolution, + includeResizeGroup: true, + includeModel: true, + includePredictorModel: true, + contentDescription: ".tvs File", + singletonDescription: string.Empty, + collectionDescription: "n json file(s) for each face found (one to many)"); + for (int i = 0; i < filteredPropertyHolderCollection.Length; i++) { - fileNameWithoutExtension = Path.GetFileNameWithoutExtension(subFiles[i]); - directoryInfo = new DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "[]"), fileNameWithoutExtension)); + fileInfo = filteredPropertyHolderCollection[i].FileInfo; + if (fileInfo is null) + continue; + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName); + directoryInfo = new System.IO.DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "[]"), fileNameWithoutExtension)); if (!directoryInfo.Exists) { if (directoryInfo.Parent?.Parent is null) @@ -229,14 +240,15 @@ internal class E_Distance Directory.Delete(parentCheck); } } - tvsDirectoryInfo = new DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "()"), fileNameWithoutExtension)); + tvsDirectoryInfo = new System.IO.DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "()"), fileNameWithoutExtension)); directories.Add(new string[] { directoryInfo.FullName, tvsDirectoryInfo.FullName }); if (_Configuration.CheckJsonForDistanceResults.Value && directoryInfo.Exists) { - foreach (FileInfo fileInfo in directoryInfo.GetFiles("*.json", SearchOption.AllDirectories)) + fileInfoCollection = directoryInfo.GetFiles("*.json", SearchOption.AllDirectories); + for (int j = 0; j < fileInfoCollection.Length; j++) { - json = Shared.Models.Stateless.Methods.IIndex.GetJson(fileInfo.FullName, fileInfo); - if (!_Configuration.PropertiesChangedForDistance.Value && Shared.Models.Stateless.Methods.IFace.GetFace(fileInfo.FullName) is null) + 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) check = true; } } @@ -252,16 +264,16 @@ internal class E_Distance check = true; } if (check) - LoadOrCreateThenSaveDistanceResults(configuration, subFiles, faceCollections, directories); + LoadOrCreateThenSaveDistanceResults(configuration, filteredPropertyHolderCollection, faceCollections, directories); _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(directoryInfoCollection[0].Replace("<>", "()")); } - private List<(string, List>)> GetFiles(Property.Models.Configuration configuration, string outputResolution) + private List<(string, List>)> GetFiles(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution) { string json; List>? facesKeyValuePairCollection; List<(string, List>)> results = new(); - string dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[[]]"); + string dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model.ToString(), predictorModel.ToString(), nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[[]]"); string[] dFacesCollectionFiles = Directory.GetFiles(dFacesCollectionDirectory, "*.json", SearchOption.TopDirectoryOnly); foreach (string dFacesCollectionFile in dFacesCollectionFiles) { @@ -311,10 +323,10 @@ internal class E_Distance return result; } - private void Save(Property.Models.Configuration configuration, string outputResolution, string eDistanceCollectionDirectory, int k, string relativePath, Shared.Models.Face face, List> faceAndFaceDistanceCollection) + private void Save(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, string eDistanceCollectionDirectory, int k, string relativePath, Shared.Models.Face face, List> faceAndFaceDistanceCollection) { if (string.IsNullOrEmpty(eDistanceCollectionDirectory)) - eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); + eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model.ToString(), predictorModel.ToString(), nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(face.RelativePath); string jsonDirectory = string.Concat(eDistanceCollectionDirectory, Path.Combine(relativePath, fileNameWithoutExtension)); if (!Directory.Exists(jsonDirectory)) @@ -333,7 +345,7 @@ internal class E_Distance return result; } - internal void LoadOrCreateThenSaveDirectoryDistanceResults(Property.Models.Configuration configuration, string outputResolution) + internal void LoadOrCreateThenSaveDirectoryDistanceResults(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -344,7 +356,7 @@ internal class E_Distance string eDistanceCollectionDirectory = string.Empty; Tuple faceAndFaceDistance; List> faceAndFaceDistanceCollection; - List<(string, List>)> files = GetFiles(configuration, outputResolution); + List<(string, List>)> files = GetFiles(configuration, model, predictorModel, outputResolution); List<(string, List, List)> matches = GetMatches(files); if (files.Count != matches.Count) throw new Exception(); @@ -380,7 +392,7 @@ internal class E_Distance if (faceAndFaceDistanceCollection.Any()) { faceAndFaceDistanceCollection = (from l in faceAndFaceDistanceCollection orderby l.Item2 select l).Take(_Configuration.CrossDirectoryMaxItemsInDistanceCollection.Value).ToList(); - Save(configuration, outputResolution, eDistanceCollectionDirectory, k, relativePath, face, faceAndFaceDistanceCollection); + Save(configuration, model, predictorModel, outputResolution, eDistanceCollectionDirectory, k, relativePath, face, faceAndFaceDistanceCollection); } } } diff --git a/Instance/Models/_G2_Identify.cs b/Instance/Models/_G2_Identify.cs index cd138cc..bf4c07a 100644 --- a/Instance/Models/_G2_Identify.cs +++ b/Instance/Models/_G2_Identify.cs @@ -90,11 +90,11 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify json = File.ReadAllText(named.FullName); Person[] people = a2People.GetPeople(configuration); Dictionary resultKeyValuePairs = new(); - string[] peopleBirthdates = (from l in people select Shared.Models.Stateless.Methods.IPersonBirthday.GetFormated(l.Birthday)).ToArray(); + string[] peopleBirthDates = (from l in people select Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(l.Birthday)).ToArray(); Dictionary sourceKeyValuePairs = JsonSerializer.Deserialize>(json); foreach (KeyValuePair keyValuePair in sourceKeyValuePairs) { - if (!(from l in keyValuePair.Value where peopleBirthdates.Contains(l) select false).Any()) + if (!(from l in keyValuePair.Value where peopleBirthDates.Contains(l) select false).Any()) continue; resultKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value); } diff --git a/Instance/Models/_G_Index.cs b/Instance/Models/_G_Index.cs index 2a7ce52..c1a0ea4 100644 --- a/Instance/Models/_G_Index.cs +++ b/Instance/Models/_G_Index.cs @@ -1,3 +1,4 @@ +using FaceRecognitionDotNet; using System.Text.Json; using System.Text.Json.Serialization; using View_by_Distance.Property.Models; @@ -103,7 +104,7 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex } } - private void WriteGroup(Property.Models.Configuration configuration, string outputResolution, List>> indexInfoTuples) + private void WriteGroup(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, List>> indexInfoTuples) { string json; G_Index[] indices; @@ -111,14 +112,14 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex foreach (Tuple> tuple in indexInfoTuples) { indices = (from l in tuple.Item2 select l.Value).ToArray(); - directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, tuple.Item1, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: string.Empty, collectionDescription: "Unknown A"); + directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, model.ToString(), predictorModel.ToString(), tuple.Item1, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: string.Empty, collectionDescription: "Unknown A"); json = JsonSerializer.Serialize(indices, _WriteIndentedJsonSerializerOptions); if (!Property.Models.Stateless.IPath.WriteAllText(string.Concat(directoryInfoCollection[0].Replace("<>", "[]"), ".json"), json, compareBeforeWrite: true)) continue; } } - private void AppendTSV(Property.Models.Configuration configuration, string outputResolution, Dictionary>> filePropertiesKeyValuePairs) + private void AppendTSV(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, Dictionary>> filePropertiesKeyValuePairs) { A_Property property; DateTime?[] dateTimes; @@ -137,11 +138,11 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex maximumDateTime = (from l in dateTimes where l.HasValue select l.Value).Max(); minimumDateTime = (from l in dateTimes where l.HasValue select l.Value).Min(); } - directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, tuples.Key, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: "Unkown B", collectionDescription: string.Empty); + directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, model.ToString(), predictorModel.ToString(), tuples.Key, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: "Unkown B", collectionDescription: string.Empty); } } - internal void SetIndex(Property.Models.Configuration configuration, string outputResolution, Dictionary>> filePropertiesKeyValuePairs) + internal void SetIndex(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, Dictionary>> filePropertiesKeyValuePairs) { if (_Configuration.PropertiesChangedForIndex is null) throw new Exception(); @@ -168,7 +169,7 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex foreach (KeyValuePair>> tuples in filePropertiesKeyValuePairs) { valuePairs = new Dictionary(); - directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, tuples.Key, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: "Unknown C", collectionDescription: string.Empty); + directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, model.ToString(), predictorModel.ToString(), tuples.Key, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: "Unknown C", collectionDescription: string.Empty); foreach (Tuple tuple in tuples.Value) { fileInfo = new FileInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "{}"), string.Concat(Path.GetFileNameWithoutExtension(tuple.Item1), ".json"))); @@ -204,8 +205,8 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex throw new Exception(string.Join(Environment.NewLine, parseExceptions)); if (neededTuples.Any()) throw new Exception(); - WriteGroup(configuration, outputResolution, indexInfoTuples); - AppendTSV(configuration, outputResolution, filePropertiesKeyValuePairs); + WriteGroup(configuration, model, predictorModel, outputResolution, indexInfoTuples); + AppendTSV(configuration, model, predictorModel, outputResolution, filePropertiesKeyValuePairs); } string Shared.Models.Stateless.Methods.IIndex.TestStatic_GetJson(string jsonFileFullName, FileInfo fileInfo) => throw new NotImplementedException(); diff --git a/Instance/appsettings.Development.json b/Instance/appsettings.Development.json index 44715f6..dd85324 100644 --- a/Instance/appsettings.Development.json +++ b/Instance/appsettings.Development.json @@ -9,7 +9,7 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "MaxDegreeOfParallelism": 6, + "MaxDegreeOfParallelism": 1, "Serilog": { "Using": [ "Serilog.Sinks.Console", @@ -52,14 +52,14 @@ "Configuration": { "CheckJsonForDistanceResults": true, "CrossDirectoryMaxItemsInDistanceCollection": 7, - "DateGroup": "2022-04-07", + "DateGroup": "2022-07-24", "DistanceFactor": 8, "FileNameDirectorySeparator": ".Z.", "ForceMetadataLastWriteTimeToCreationTime": false, "ForcePropertyLastWriteTimeToCreationTime": false, "ForceResizeLastWriteTimeToCreationTime": false, - "LoadOrCreateThenSaveDirectoryDistanceResults": true, - "LoadOrCreateThenSaveDistanceResults": true, + "LoadOrCreateThenSaveDirectoryDistanceResults": false, + "LoadOrCreateThenSaveDistanceResults": false, "LoadOrCreateThenSaveImageFacesResults": true, "LoadOrCreateThenSaveIndex": false, "LocationConfidenceFactor": 2, @@ -85,10 +85,11 @@ "PropertiesChangedForProperty": false, "PropertiesChangedForResize": false, "Reverse": false, - "RootDirectory": "C:/Tmp/phares/Pictures", + "xRootDirectory": "C:/Tmp/phares/Pictures", + "RootDirectory": "F:/Tmp/Phares/Compare/Images 2022-07-24 - 1539b2f974f07b6b5cbda8450faf0eec85d02eda - III", "SaveFullYearOfRandomFiles": true, "SaveResizedSubFiles": true, - "SearchForAbandonedFilesFull": true, + "SaveShortcuts": true, "SkipSearch": false, "TestDistanceResults": true, "WriteBitmapDataBytes": false, @@ -96,12 +97,73 @@ ".gif", ".GIF" ], - "OutputResolutions": [ + "JuliePhares": [ + "1500-01-16_00", + "1500-01-19_00", + "1500-01-20_00", + "1500-01-21_00", + "1500-01-25_00", + "1500-01-26_00", + "1500-01-27_00", + "1500-02-13_00", + "1500-02-17_00", + "1500-02-24_00", + "1500-02-25_00", + "1500-04-03_00", + "1500-04-06_00", + "1500-04-19_00", + "1500-05-03_00", + "1500-05-18_00", + "1500-05-28_00", + "1500-06-16_00", + "1500-06-26_00", + "1500-06-27_00", + "1500-07-07_00", + "1500-07-16_00", + "1720-09-30_05", + "1500-07-26_00", + "1500-08-03_00", + "1500-08-23_00", + "1500-08-24_00", + "1500-09-16_00", + "1500-09-21_00", + "1500-09-28_00", + "1500-10-14_00", + "1500-11-07_00", + "1500-11-09_00", + "1720-09-28_20", + "1501-01-08_00", + "1501-01-12_00", + "1501-01-13_00", + "1501-01-30_00", + "1501-03-09_00", + "1501-03-14_00", + "1501-03-22_00", + "1501-04-07_00", + "1501-04-10_00", + "1501-04-19_00", + "1501-05-06_00", + "1956-09-19_00", + "2012-09-17_00", + "1998-05-21_00", + "1960-03-01_00", + "1976-03-08_00", + "2007-09-07_00", + "2000-04-07_00", + "1980-01-17_00", + "1958-01-30_00", + "1976-01-05_00", + "1982-05-02_00" + ], + "xOutputResolutions": [ "176 x 176", "256 x 256", "353 x 353", "1024 x 768" ], + "OutputResolutions": [ + "1376 x 768" + ], "PropertyContentCollectionFiles": [], "SaveFaceLandmarkForOutputResolutions": [ "176 x 176", diff --git a/Instance/appsettings.Staging.json b/Instance/appsettings.Staging.json index e4860f7..a76bb50 100644 --- a/Instance/appsettings.Staging.json +++ b/Instance/appsettings.Staging.json @@ -52,7 +52,7 @@ "Configuration": { "CheckJsonForDistanceResults": true, "CrossDirectoryMaxItemsInDistanceCollection": 7, - "DateGroup": "2022-04-07", + "DateGroup": "2022-07-24", "DistanceFactor": 8, "FileNameDirectorySeparator": ".Z.", "ForceMetadataLastWriteTimeToCreationTime": false, @@ -88,7 +88,7 @@ "RootDirectory": "E:/Images", "SaveFullYearOfRandomFiles": true, "SaveResizedSubFiles": true, - "SearchForAbandonedFilesFull": false, + "SaveShortcuts": true, "SkipSearch": false, "TestDistanceResults": true, "WriteBitmapDataBytes": false, diff --git a/Instance/appsettings.json b/Instance/appsettings.json index cc6fe1b..42e8f7e 100644 --- a/Instance/appsettings.json +++ b/Instance/appsettings.json @@ -52,7 +52,7 @@ "Configuration": { "CheckJsonForDistanceResults": true, "CrossDirectoryMaxItemsInDistanceCollection": 7, - "DateGroup": "2022-04-07", + "DateGroup": "2022-07-24", "DistanceFactor": 8, "FileNameDirectorySeparator": ".Z.", "ForceMetadataLastWriteTimeToCreationTime": false, @@ -88,7 +88,7 @@ "RootDirectory": "D:/Images", "SaveFullYearOfRandomFiles": true, "SaveResizedSubFiles": true, - "SearchForAbandonedFilesFull": false, + "SaveShortcuts": true, "SkipSearch": false, "TestDistanceResults": true, "WriteBitmapDataBytes": false, diff --git a/Not-Copy-Copy/Models/Configuration.cs b/Not-Copy-Copy/Models/Configuration.cs index 08816ae..435e61e 100644 --- a/Not-Copy-Copy/Models/Configuration.cs +++ b/Not-Copy-Copy/Models/Configuration.cs @@ -30,7 +30,7 @@ public class Configuration return result; } - public void Set(Property.Models.Configuration propertyConfiguration) => _PropertyConfiguration = propertyConfiguration; + public void Set(Property.Models.Configuration configuration) => _PropertyConfiguration = configuration; public void Update() { diff --git a/Not-Copy-Copy/Not-Copy-Copy.cs b/Not-Copy-Copy/Not-Copy-Copy.cs index dbd313e..c510046 100644 --- a/Not-Copy-Copy/Not-Copy-Copy.cs +++ b/Not-Copy-Copy/Not-Copy-Copy.cs @@ -37,35 +37,25 @@ public class NotCopyCopy Property.Models.Configuration.Verify(propertyConfiguration); Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Verify(configuration); + bool reverse = false; + string modelName = nameof(modelName); + string predictorModelName = nameof(predictorModelName); _Configuration = configuration; - if (propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null) - throw new Exception($"{nameof(propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!"); if (propertyConfiguration.PopulatePropertyId is null) throw new Exception($"{nameof(propertyConfiguration.PopulatePropertyId)} is null!"); if (!_IsEnvironment.Development) throw new Exception("This program only allows development environments!"); - string searchPattern = "*"; - long ticks = DateTime.Now.Ticks; - List topDirectories = new(); - List compareSourceGroupCollection; - List selectedSourceGroupCollection; PropertyLogic propertyLogic = GetPropertyLogic(); - List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection; - groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(_Configuration.CompareSource, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); - if (appSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); - compareSourceGroupCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true, filterOnFirstPass: true); - if (appSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(PropertyLogic.GetParallelWork)); - topDirectories.Clear(); - groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(configuration.SelectedSource, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); - if (appSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); - selectedSourceGroupCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true, filterOnFirstPass: true); - if (appSettings.MaxDegreeOfParallelism.Value < 2) - ticks = LogDelta(ticks, nameof(PropertyLogic.GetParallelWork)); + propertyConfiguration.ChangeRootDirectory(configuration.CompareSource); + List comparePropertyHolderCollections = Property.Models.Stateless.A_Property.Get(propertyConfiguration, reverse, modelName, predictorModelName, propertyLogic); + propertyConfiguration.ChangeRootDirectory(configuration.SelectedSource); + List selectedPropertyHolderCollections = Property.Models.Stateless.A_Property.Get(propertyConfiguration, reverse, modelName, predictorModelName, propertyLogic); + if (comparePropertyHolderCollections.Count == selectedPropertyHolderCollections.Count) + throw new Exception(); string directoryName; List distinct = new(); + List compareSourceGroupCollection = new(); + List selectedSourceGroupCollection = new(); List<(string Source, string[] Destination)> copyCollection = GetCopyCollection(compareSourceGroupCollection, selectedSourceGroupCollection); foreach ((string source, string[] destination) in copyCollection) { @@ -134,20 +124,19 @@ public class NotCopyCopy private PropertyLogic GetPropertyLogic() { PropertyLogic result; - - string[] verifyToSeason = Array.Empty(); - if (_AppSettings.MaxDegreeOfParallelism is null) throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!"); if (_Configuration?.PropertyConfiguration is null) throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); - result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, verifyToSeason); + result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration); return result; } - private List<(string Source, string[] Destination)> GetCopyCollection(List compareSourceGroupCollection, List selectedSourceGroupCollection) + private List<(string Source, string[] Destination)> GetCopyCollection(List compareSourceGroupCollection, List selectedSourceGroupCollection) { List<(string Source, string[] Destination)> results = new(); + if (_Configuration?.PropertyConfiguration is null) + throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); string key; string fileName; A_Property? property; @@ -156,9 +145,9 @@ public class NotCopyCopy List destinationCollection; string filteredSourceDirectoryFile; Dictionary keyValuePairs = new(); - foreach (Group group in compareSourceGroupCollection) + foreach (Property.Models.DirectoryInfo group in compareSourceGroupCollection) { - for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++) + for (int i = 0; i < group.SourceDirectoryFileInfoCollection.Length; i++) { property = group.PropertyCollection[i]; if (property is null) @@ -167,9 +156,9 @@ public class NotCopyCopy keyValuePairs.Add(key, property); } } - foreach (Group group in selectedSourceGroupCollection) + foreach (Property.Models.DirectoryInfo group in selectedSourceGroupCollection) { - for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++) + for (int i = 0; i < group.SourceDirectoryFileInfoCollection.Length; i++) { destinationCollection = new(); property = group.PropertyCollection[i]; diff --git a/Not-Copy-Copy/appsettings.Development.json b/Not-Copy-Copy/appsettings.Development.json index 7596b7e..bdbfb8a 100644 --- a/Not-Copy-Copy/appsettings.Development.json +++ b/Not-Copy-Copy/appsettings.Development.json @@ -50,7 +50,7 @@ "WorkingDirectoryName": "PharesApps", "Windows": { "Configuration": { - "DateGroup": "2022-04-07", + "DateGroup": "2022-07-24", "FileNameDirectorySeparator": ".Z.", "ForcePropertyLastWriteTimeToCreationTime": false, "MaxImagesInDirectoryForTopLevelFirstPass": 50, diff --git a/PrepareForOld/Models/Configuration.cs b/PrepareForOld/Models/Configuration.cs index 208d9d9..48ed622 100644 --- a/PrepareForOld/Models/Configuration.cs +++ b/PrepareForOld/Models/Configuration.cs @@ -24,8 +24,8 @@ public class Configuration return result; } - public void Set(Property.Models.Configuration propertyConfiguration) => _PropertyConfiguration = propertyConfiguration; + public void Set(Property.Models.Configuration configuration) => _PropertyConfiguration = configuration; public void Update() => _PropertyConfiguration?.Update(); - + } \ No newline at end of file diff --git a/PrepareForOld/PrepareForOld.cs b/PrepareForOld/PrepareForOld.cs index 20244bf..b7d7c82 100644 --- a/PrepareForOld/PrepareForOld.cs +++ b/PrepareForOld/PrepareForOld.cs @@ -41,10 +41,10 @@ public class PrepareForOld Property.Models.Configuration.Verify(propertyConfiguration); Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Verify(configuration); + string modelName = nameof(modelName); + string predictorModelName = nameof(predictorModelName); if (propertyConfiguration.IgnoreExtensions is null) throw new Exception($"{nameof(propertyConfiguration.IgnoreExtensions)} is null!"); - if (propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null) - throw new Exception($"{nameof(propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!"); for (int i = 0; i < configuration.Spelling.Length; i++) { spellingA = configuration.Spelling[i]; diff --git a/PrepareForOld/appsettings.Development.json b/PrepareForOld/appsettings.Development.json index 4a7b4e1..8fbe054 100644 --- a/PrepareForOld/appsettings.Development.json +++ b/PrepareForOld/appsettings.Development.json @@ -50,7 +50,7 @@ "WorkingDirectoryName": "PharesApps", "Windows": { "Configuration": { - "DateGroup": "2022-04-07", + "DateGroup": "2022-07-24", "FileNameDirectorySeparator": ".Z.", "ForcePropertyLastWriteTimeToCreationTime": false, "KeepFullPath": false, diff --git a/Property-Compare/Models/PropertyCompareLogic.cs b/Property-Compare/Models/PropertyCompareLogic.cs index cd22e7f..cada82e 100644 --- a/Property-Compare/Models/PropertyCompareLogic.cs +++ b/Property-Compare/Models/PropertyCompareLogic.cs @@ -271,10 +271,10 @@ public class PropertyCompareLogic string[] filteredSourceDirectoryFiles; List collection = new(); bool isArg = aPropertySingletonDirectory.Contains(_Configuration.RootDirectory); + List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _MaxDegreeOfParallelism }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; - List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(aPropertySingletonDirectory, searchPattern, topDirectories); - int count = groupCollection.Count; + groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(aPropertySingletonDirectory, searchPattern, topDirectories); foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection) { if (!topDirectories.Any()) @@ -294,7 +294,7 @@ public class PropertyCompareLogic if (!filteredSourceDirectoryFiles.Any()) continue; totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); - using ProgressBar progressBar = new(filteredSourceDirectoryFiles.Length, $"{g}) {r + 1:000} / {count:000} - {sourceDirectory} - {filteredSourceDirectoryFiles.Length} file(s) - {totalSeconds} total second(s)", options); + using ProgressBar progressBar = new(filteredSourceDirectoryFiles.Length, $"{r + 1:000}.{g} / {groupCollection.Count:000}) {filteredSourceDirectoryFiles.Length:000} file(s) - {totalSeconds} total second(s) - {sourceDirectory}", options); _ = Parallel.For(0, filteredSourceDirectoryFiles.Length, parallelOptions, i => { try diff --git a/Property/Models/A_Property.cs b/Property/Models/A_Property.cs index b2a1aaf..4f410d9 100644 --- a/Property/Models/A_Property.cs +++ b/Property/Models/A_Property.cs @@ -103,8 +103,8 @@ public class A_Property : Shared.Models.Properties.IProperty, IProperty year = minimumDateTime.Value.ToString("yyyy"); else { - List datetimes = GetDateTimes(); - year = datetimes.Min().ToString("yyyy"); + List dateTimes = GetDateTimes(); + year = dateTimes.Min().ToString("yyyy"); } for (int i = 0; i < int.MaxValue; i++) { diff --git a/Property/Models/Configuration.cs b/Property/Models/Configuration.cs index f31252b..fedca39 100644 --- a/Property/Models/Configuration.cs +++ b/Property/Models/Configuration.cs @@ -98,4 +98,6 @@ public class Configuration throw new Exception($"{nameof(propertyConfiguration.RootDirectory)} must have a value and exits!"); } + public void ChangeRootDirectory(string rootDirectory) => _RootDirectory = rootDirectory; + } \ No newline at end of file diff --git a/Property/Models/DirectoryInfo.cs b/Property/Models/DirectoryInfo.cs new file mode 100644 index 0000000..a1d77b3 --- /dev/null +++ b/Property/Models/DirectoryInfo.cs @@ -0,0 +1,46 @@ +namespace View_by_Distance.Property.Models; + +public class DirectoryInfo +{ + + protected readonly FileInfo[] _SourceDirectoryFileInfoCollection; + protected readonly string[] _FilteredSourceDirectoryFiles; + protected readonly int _G; + protected readonly bool[] _Moved; + protected readonly bool?[] _Changed; + protected readonly A_Property?[] _PropertyCollection; + protected readonly FileInfo?[] _PropertyFileInfoCollection; + protected readonly int _R; + protected readonly string _SourceDirectory; + protected readonly bool[] _ValidImageFormatExtensionCollection; + protected readonly bool[] _WrongYear; + public FileInfo[] SourceDirectoryFileInfoCollection => _SourceDirectoryFileInfoCollection; + [Obsolete($"Use {nameof(SourceDirectoryFileInfoCollection)}")] + public string[] FilteredSourceDirectoryFiles => _FilteredSourceDirectoryFiles; + public int G => _G; + public bool[] Moved => _Moved; + public bool?[] Changed => _Changed; + public A_Property?[] PropertyCollection => _PropertyCollection; + public FileInfo?[] PropertyFileInfoCollection => _PropertyFileInfoCollection; + public int R => _R; + public string SourceDirectory => _SourceDirectory; + public bool[] ValidImageFormatExtensionCollection => _ValidImageFormatExtensionCollection; + public bool[] WrongYear => _WrongYear; + + public DirectoryInfo(int g, string sourceDirectory, string[] filteredSourceDirectoryFiles, int r) + { + int length = filteredSourceDirectoryFiles.Length; + _G = g; + _R = r; + _Changed = Array.Empty(); + _SourceDirectory = sourceDirectory; + _Moved = Enumerable.Repeat(false, length).ToArray(); + _WrongYear = Enumerable.Repeat(false, length).ToArray(); + _FilteredSourceDirectoryFiles = filteredSourceDirectoryFiles; + _PropertyCollection = Enumerable.Repeat(null, length).ToArray(); + _ValidImageFormatExtensionCollection = Enumerable.Repeat(false, length).ToArray(); + _PropertyFileInfoCollection = Enumerable.Repeat(null, length).ToArray(); + _SourceDirectoryFileInfoCollection = (from l in filteredSourceDirectoryFiles select new FileInfo(l)).ToArray(); + } + +} \ No newline at end of file diff --git a/Property/Models/Group.cs b/Property/Models/Group.cs deleted file mode 100644 index fbf817e..0000000 --- a/Property/Models/Group.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace View_by_Distance.Property.Models; - -public class Group -{ - - protected readonly int _G; - protected readonly string _SourceDirectory; - protected readonly string[] _FilteredSourceDirectoryFiles; - protected readonly int _R; - protected readonly bool[] _ValidImageFormatExtentionCollection; - protected readonly FileInfo?[] _PropertyFileInfoCollection; - protected readonly A_Property?[] _PropertyCollection; - public int G => _G; - public string SourceDirectory => _SourceDirectory; - public string[] FilteredSourceDirectoryFiles => _FilteredSourceDirectoryFiles; - public int R => _R; - public bool[] ValidImageFormatExtentionCollection => _ValidImageFormatExtentionCollection; - public FileInfo?[] PropertyFileInfoCollection => _PropertyFileInfoCollection; - public A_Property?[] PropertyCollection => _PropertyCollection; - - public Group(int g, string sourceDirectory, string[] filteredSourceDirectoryFiles, int r) - { - _G = g; - _SourceDirectory = sourceDirectory; - _FilteredSourceDirectoryFiles = filteredSourceDirectoryFiles; - _R = r; - _ValidImageFormatExtentionCollection = Enumerable.Repeat(false, filteredSourceDirectoryFiles.Length).ToArray(); - _PropertyFileInfoCollection = Enumerable.Repeat(null, filteredSourceDirectoryFiles.Length).ToArray(); - _PropertyCollection = Enumerable.Repeat(null, filteredSourceDirectoryFiles.Length).ToArray(); - } - -} \ No newline at end of file diff --git a/Property/Models/PropertyHolder.cs b/Property/Models/PropertyHolder.cs new file mode 100644 index 0000000..225a77e --- /dev/null +++ b/Property/Models/PropertyHolder.cs @@ -0,0 +1,83 @@ +using System.Text.Json.Serialization; + +namespace View_by_Distance.Property.Models; + +public class PropertyHolder +{ + + protected readonly bool? _Abandoned; + protected readonly bool? _Changed; + protected FileInfo? _FileInfo; + protected readonly int _G; + protected DateTime? _MinimumDateTime; + protected bool? _Moved; + protected readonly bool? _NoJson; + protected A_Property? _Property; + protected readonly int _R; + protected readonly string _RelativePath; + protected FileInfo? _ResizedFileInfo; + protected readonly string _SourceDirectory; + protected readonly string _SourceDirectoryFile; + protected bool? _ValidImageFormatExtension; + protected bool? _WrongYear; + public bool? Abandoned => _Abandoned; + public bool? Changed => _Changed; + public FileInfo? FileInfo => _FileInfo; + public int G => _G; + public DateTime? MinimumDateTime => _MinimumDateTime; + public bool? Moved => _Moved; + public bool? NoJson => _NoJson; + public A_Property? Property => _Property; + public int R => _R; + public string RelativePath => _RelativePath; + public FileInfo? ResizedFileInfo => _ResizedFileInfo; + public string SourceDirectory => _SourceDirectory; + public string SourceDirectoryFile => _SourceDirectoryFile; + public bool? ValidImageFormatExtension => _ValidImageFormatExtension; + public bool? WrongYear => _WrongYear; + + public PropertyHolder() + { + _G = -1; + _SourceDirectory = string.Empty; + _SourceDirectoryFile = string.Empty; + _RelativePath = string.Empty; + _R = -1; + } + + [JsonConstructor] + public PropertyHolder(int g, string sourceDirectory, string sourceDirectoryFile, string relativePath, int r, FileInfo? fileInfo, A_Property? property, bool? abandoned, bool? changed, bool? moved, bool? validImageFormatExtension, bool? wrongYear) + { + _Abandoned = abandoned; + _Changed = changed; + _FileInfo = fileInfo; + _G = g; + _Moved = moved; + _NoJson = abandoned is null; + _Property = property; + _R = r; + _RelativePath = relativePath; + _SourceDirectory = sourceDirectory; + _SourceDirectoryFile = sourceDirectoryFile; + _ValidImageFormatExtension = validImageFormatExtension; + _WrongYear = wrongYear; + _MinimumDateTime = Stateless.A_Property.GetMinimumDateTime(property); + } + + internal void SetValidImageFormatExtension(bool isValidImageFormatExtension) => _ValidImageFormatExtension = isValidImageFormatExtension; + + internal void SetWrongYear(bool wrongYear) => _WrongYear = wrongYear; + + internal void SetMoved(bool moved) => _Moved = moved; + + public void SetResizedFileInfo(FileInfo fileInfo) => _ResizedFileInfo = fileInfo; + + internal void Update(FileInfo fileInfo, A_Property property) + { + _Property = property; + _FileInfo = fileInfo; + } + + public bool Any() => (_Abandoned.HasValue && _Abandoned.Value) || (_Changed.HasValue && _Changed.Value) || (_Moved.HasValue && _Moved.Value) || (_NoJson.HasValue && _NoJson.Value); + +} \ No newline at end of file diff --git a/Property/Models/PropertyLogic.cs b/Property/Models/PropertyLogic.cs index fc789ff..e76aef7 100644 --- a/Property/Models/PropertyLogic.cs +++ b/Property/Models/PropertyLogic.cs @@ -14,47 +14,62 @@ namespace View_by_Distance.Property.Models; public class PropertyLogic { + protected readonly List _ExceptionsDirectories; protected readonly Dictionary _IndicesFromNew; protected readonly Dictionary _IndicesFromOld; + protected readonly Dictionary _NamedFaceInfo; public List AngleBracketCollection { get; } public Dictionary IndicesFromNew => _IndicesFromNew; public Dictionary IndicesFromOld => _IndicesFromOld; + public Dictionary NamedFaceInfo => _NamedFaceInfo; + public List ExceptionsDirectories => _ExceptionsDirectories; private readonly Serilog.ILogger? _Log; private readonly string[] _VerifyToSeason; private readonly int _MaxDegreeOfParallelism; private readonly ASCIIEncoding _ASCIIEncoding; private readonly Configuration _Configuration; - private readonly List _ExceptionsDirectories; private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; - public PropertyLogic(int maxDegreeOfParallelism, Configuration configuration, string[] verifyToSeason) + public PropertyLogic(int maxDegreeOfParallelism, Configuration configuration) { _Configuration = configuration; _ExceptionsDirectories = new(); - _VerifyToSeason = verifyToSeason; _ASCIIEncoding = new ASCIIEncoding(); AngleBracketCollection = new List(); _Log = Serilog.Log.ForContext(); _MaxDegreeOfParallelism = maxDegreeOfParallelism; _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; - if (verifyToSeason is null) + if (configuration.VerifyToSeason is null || !configuration.VerifyToSeason.Any()) throw new Exception(); + _VerifyToSeason = configuration.VerifyToSeason.Select(l => Path.Combine(configuration.RootDirectory, l)).ToArray(); string json; + string[] files; string fullPath; Dictionary? indicesFromOld; + Dictionary? namedFaceInfo; List>? collection; Dictionary indicesFromNew = new(); string? rootDirectoryParent = Path.GetDirectoryName(configuration.RootDirectory); if (string.IsNullOrEmpty(rootDirectoryParent)) throw new Exception($"{nameof(rootDirectoryParent)} is null!"); - string keyValuePairsJsonFile = Path.Combine(rootDirectoryParent, "keyValuePairs-637864726339738801.json"); - if (!File.Exists(keyValuePairsJsonFile)) + files = Directory.GetFiles(rootDirectoryParent, "*Named*.json", SearchOption.TopDirectoryOnly); + if (files.Length != 1) + namedFaceInfo = new(); + else + { + json = File.ReadAllText(files[0]); + namedFaceInfo = JsonSerializer.Deserialize>(json); + if (namedFaceInfo is null) + throw new Exception($"{nameof(namedFaceInfo)} is null!"); + } + files = Directory.GetFiles(rootDirectoryParent, "*keyValuePairs*.json", SearchOption.TopDirectoryOnly); + if (files.Length != 1) indicesFromOld = new(); else { - json = File.ReadAllText(keyValuePairsJsonFile); + json = File.ReadAllText(files[0]); indicesFromOld = JsonSerializer.Deserialize>(json); if (indicesFromOld is null) throw new Exception($"{nameof(indicesFromOld)} is null!"); @@ -77,6 +92,7 @@ public class PropertyLogic indicesFromNew.Add(keyValuePair.Key, keyValuePair.Value); } } + _NamedFaceInfo = namedFaceInfo; _IndicesFromNew = indicesFromNew; _IndicesFromOld = indicesFromOld; } @@ -124,9 +140,15 @@ public class PropertyLogic return results; } + public static List GetMetadataDateTimesByPattern(string dateTimeFormat, FileInfo filteredSourceDirectoryFileInfo) + { + List results = GetMetadataDateTimesByPattern(dateTimeFormat, filteredSourceDirectoryFileInfo.FullName); + return results; + } + #pragma warning disable CA1416 - private A_Property GetImageProperty(string angleBracket, string filteredSourceDirectoryFile, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id, List indices) + private A_Property GetImageProperty(string angleBracket, string filteredSourceDirectoryFile, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id, List indices, long fileInfoLength, DateTime creationTime, DateTime lastWriteTime) { A_Property result; if (_Log is null) @@ -149,11 +171,7 @@ public class PropertyLogic DateTime? dateTimeOriginal = null; string orientation = string.Empty; DateTime? dateTimeDigitized = null; - FileInfo fileInfo = new(filteredSourceDirectoryFile); - long fileInfoLength = fileInfo.Length; - DateTime creationTime = fileInfo.CreationTime; - DateTime lastWriteTime = fileInfo.LastWriteTime; - if (isValidMetadataExtensions) + if (!isValidImageFormatExtension && isValidMetadataExtensions) { dateTimeFormat = "ddd MMM dd HH:mm:ss yyyy"; List dateTimes = GetMetadataDateTimesByPattern(dateTimeFormat, filteredSourceDirectoryFile); @@ -294,9 +312,173 @@ public class PropertyLogic return result; } + private A_Property GetImagePropertyB(string angleBracket, FileInfo filteredSourceDirectoryFileInfo, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id, List indices) + { + A_Property result; + if (_Log is null) + throw new Exception($"{nameof(_Log)} is null!"); + if (_Configuration.WriteBitmapDataBytes is null) + throw new Exception($"{nameof(_Configuration.WriteBitmapDataBytes)} is null!"); + long ticks; + byte[] bytes; + string value; + int encodingHash; + int? width = null; + int? height = null; + string dateTimeFormat; + DateTime checkDateTime; + DateTime? dateTime = null; + PropertyItem? propertyItem; + string make = string.Empty; + string model = string.Empty; + DateTime? gpsDateStamp = null; + DateTime? dateTimeOriginal = null; + string orientation = string.Empty; + DateTime? dateTimeDigitized = null; + if (!isValidImageFormatExtension && isValidMetadataExtensions) + { + dateTimeFormat = "ddd MMM dd HH:mm:ss yyyy"; + List dateTimes = GetMetadataDateTimesByPattern(dateTimeFormat, filteredSourceDirectoryFileInfo); + if (dateTimes.Any()) + dateTimeOriginal = dateTimes.Min(); + } + else if (!isIgnoreExtension && isValidImageFormatExtension) + { + try + { + using Image image = Image.FromFile(filteredSourceDirectoryFileInfo.FullName); + if (populateId && (id is null || !indices.Any())) + { + using Bitmap bitmap = new(image); + Rectangle rectangle = new(0, 0, image.Width, image.Height); + BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat); + IntPtr intPtr = bitmapData.Scan0; + int length = bitmapData.Stride * bitmap.Height; + bytes = new byte[length]; + Marshal.Copy(intPtr, bytes, 0, length); + bitmap.UnlockBits(bitmapData); + if (id is null) + { + ticks = DateTime.Now.Ticks; + id = Stateless.A_Property.GetDeterministicHashCode(bytes); + if (_MaxDegreeOfParallelism < 2) + ticks = LogDelta(ticks, nameof(Stateless.A_Property.GetDeterministicHashCode)); + } + if (_Configuration.WriteBitmapDataBytes.Value) + { + FileInfo contentFileInfo = new(Path.Combine(angleBracket.Replace("<>", "()"), filteredSourceDirectoryFileInfo.Name)); + File.WriteAllBytes(Path.ChangeExtension(contentFileInfo.FullName, string.Empty), bytes); + } + if (_IndicesFromNew.ContainsKey(id.Value) && _IndicesFromNew[id.Value].Any()) + indices.AddRange(_IndicesFromNew[id.Value]); + else + { + ticks = DateTime.Now.Ticks; + string encoding = Encoding.Default.GetString(bytes); + if (_MaxDegreeOfParallelism < 2) + ticks = LogDelta(ticks, nameof(Encoding.Default.GetString)); + encodingHash = Stateless.A_Property.GetDeterministicHashCode(encoding); + if (_MaxDegreeOfParallelism < 2) + ticks = LogDelta(ticks, nameof(Stateless.A_Property.GetDeterministicHashCode)); + if (!_IndicesFromOld.ContainsKey(encodingHash)) + indices.Add(encodingHash); + else + indices.AddRange(_IndicesFromOld[encodingHash]); + } + } + width = image.Width; + height = image.Height; + dateTimeFormat = Stateless.A_Property.DateTimeFormat(); + if (image.PropertyIdList.Contains((int)IExif.Tags.DateTime)) + { + propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTime); + if (propertyItem?.Value is not null) + { + value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1); + if (value.Length > dateTimeFormat.Length) + value = value[..dateTimeFormat.Length]; + if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime)) + dateTime = checkDateTime; + } + } + if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeDigitized)) + { + propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeDigitized); + if (propertyItem?.Value is not null) + { + value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1); + if (value.Length > dateTimeFormat.Length) + value = value[..dateTimeFormat.Length]; + if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime)) + dateTimeDigitized = checkDateTime; + } + } + if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeOriginal)) + { + propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeOriginal); + if (propertyItem?.Value is not null) + { + value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1); + if (value.Length > dateTimeFormat.Length) + value = value[..dateTimeFormat.Length]; + if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime)) + dateTimeOriginal = checkDateTime; + } + } + if (image.PropertyIdList.Contains((int)IExif.Tags.GPSDateStamp)) + { + propertyItem = image.GetPropertyItem((int)IExif.Tags.GPSDateStamp); + if (propertyItem?.Value is not null) + { + value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1); + if (value.Length > dateTimeFormat.Length) + value = value[..dateTimeFormat.Length]; + if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime)) + gpsDateStamp = checkDateTime; + } + } + if (image.PropertyIdList.Contains((int)IExif.Tags.Make)) + { + propertyItem = image.GetPropertyItem((int)IExif.Tags.Make); + if (propertyItem?.Value is not null) + { + value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1); + make = value; + } + } + if (image.PropertyIdList.Contains((int)IExif.Tags.Model)) + { + propertyItem = image.GetPropertyItem((int)IExif.Tags.Model); + if (propertyItem?.Value is not null) + { + value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1); + model = value; + } + } + if (image.PropertyIdList.Contains((int)IExif.Tags.Orientation)) + { + propertyItem = image.GetPropertyItem((int)IExif.Tags.Orientation); + if (propertyItem?.Value is not null) + { + value = BitConverter.ToInt16(propertyItem.Value, 0).ToString(); + orientation = value; + } + } + } + catch (Exception) + { + _Log.Info(string.Concat(new StackFrame().GetMethod()?.Name, " <", filteredSourceDirectoryFileInfo.Name, ">")); + } + } + else + dateTimeOriginal = null; + result = new(filteredSourceDirectoryFileInfo.CreationTime, dateTime, dateTimeDigitized, dateTimeOriginal, filteredSourceDirectoryFileInfo.Length, gpsDateStamp, height, id, indices.ToArray(), filteredSourceDirectoryFileInfo.LastWriteTime, make, model, orientation, width); + return result; + } + #pragma warning restore CA1416 - private A_Property GetProperty(List> filteredSourceDirectoryFileTuples, List parseExceptions, bool firstPass, string angleBracket, string filteredSourceDirectoryFile, FileInfo fileInfo, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions) + private A_Property GetPropertyA(List> filteredSourceDirectoryFileTuples, List parseExceptions, bool firstPass, string angleBracket, FileInfo filteredSourceDirectoryFileInfo, FileInfo fileInfo, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions) { A_Property? result; if (_Configuration.ForcePropertyLastWriteTimeToCreationTime is null) @@ -309,7 +491,7 @@ public class PropertyLogic int? id = null; List indices = new(); bool hasWrongYearProperty = false; - string[] changesFrom = new string[] { "B_Metadata" }; + string[] changesFrom = Array.Empty(); bool populateId = !firstPass && _Configuration.PopulatePropertyId.Value; List dateTimes = (from l in filteredSourceDirectoryFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); if (!fileInfo.Exists) @@ -352,7 +534,7 @@ public class PropertyLogic id = property?.Id; if (property is not null && property.Indices.Any()) indices = property.Indices.ToList(); - property = GetImageProperty(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + property = GetImagePropertyB(angleBracket, filteredSourceDirectoryFileInfo, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); } if (!isIgnoreExtension && isValidImageFormatExtension && populateId && property is not null && !property.Indices.Any()) { @@ -360,25 +542,32 @@ public class PropertyLogic id = property?.Id; if (property is not null && property.Indices.Any()) indices = property.Indices.ToList(); - property = GetImageProperty(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + property = GetImagePropertyB(angleBracket, filteredSourceDirectoryFileInfo, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); } - if (!isIgnoreExtension && isValidImageFormatExtension && populateId && property is not null && property.LastWriteTime != new FileInfo(filteredSourceDirectoryFile).LastWriteTime) + if (!isIgnoreExtension && isValidImageFormatExtension && populateId && property is not null && property.LastWriteTime != filteredSourceDirectoryFileInfo.LastWriteTime) { check = false; id = null; indices.Clear(); - property = GetImageProperty(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + property = GetImagePropertyB(angleBracket, filteredSourceDirectoryFileInfo, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); } - if (!isIgnoreExtension && isValidImageFormatExtension && property?.Width is not null && property?.Height is not null && property.Width.Value == property.Height.Value && File.Exists(filteredSourceDirectoryFile)) + if (!isIgnoreExtension && isValidImageFormatExtension && property?.Width is not null && property?.Height is not null && property.Width.Value == property.Height.Value && filteredSourceDirectoryFileInfo.Exists) { check = false; id = property?.Id; if (property is not null && property.Indices.Any()) indices = property.Indices.ToList(); - property = GetImageProperty(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + property = GetImagePropertyB(angleBracket, filteredSourceDirectoryFileInfo, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); if (property?.Width is not null && property?.Height is not null && property.Width.Value != property.Height.Value) throw new Exception("Was square!"); } + // if (filteredSourceDirectoryFileFileInfo.CreationTime != property?.CreationTime || filteredSourceDirectoryFileFileInfo.LastWriteTime != property?.LastWriteTime) + // { + // check = false; + // id = null; + // indices.Clear(); + // property = GetImagePropertyB(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + // } if (json.Contains("WrongYear")) { id = property?.Id; @@ -402,7 +591,7 @@ public class PropertyLogic } if (result is null) { - result = GetImageProperty(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + result = GetImagePropertyB(angleBracket, filteredSourceDirectoryFileInfo, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions); if (populateId && IPath.WriteAllText(fileInfo.FullName, json, compareBeforeWrite: true)) { @@ -429,7 +618,145 @@ public class PropertyLogic return result; } - private bool AnyFilesMoved(Group group) + private A_Property GetPropertyB(List> filteredSourceDirectoryFileTuples, List parseExceptions, bool firstPass, string angleBracket, FileInfo filteredSourceDirectoryFileInfo, A_Property? property, FileInfo fileInfo, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions) + { + A_Property? result; + if (_Configuration.ForcePropertyLastWriteTimeToCreationTime is null) + throw new Exception($"{nameof(_Configuration.ForcePropertyLastWriteTimeToCreationTime)} is null!"); + if (_Configuration.PopulatePropertyId is null) + throw new Exception($"{nameof(_Configuration.PopulatePropertyId)} is null!"); + if (_Configuration.PropertiesChangedForProperty is null) + throw new Exception($"{nameof(_Configuration.PropertiesChangedForProperty)} is null!"); + string json; + int? id = null; + List indices = new(); + bool hasWrongYearProperty = false; + string[] changesFrom = Array.Empty(); + bool populateId = !firstPass && _Configuration.PopulatePropertyId.Value; + List dateTimes = (from l in filteredSourceDirectoryFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); + if (!fileInfo.Exists) + { + if (fileInfo.Directory?.Parent is null) + throw new Exception(); + string parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name); + if (File.Exists(parentCheck)) + { + File.Move(parentCheck, fileInfo.FullName); + fileInfo.Refresh(); + } + } + if (_Configuration.ForcePropertyLastWriteTimeToCreationTime.Value && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) + { + File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); + fileInfo.Refresh(); + } + if (_Configuration.ForcePropertyLastWriteTimeToCreationTime.Value && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime) + { + File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); + fileInfo.Refresh(); + } + if (_Configuration.PropertiesChangedForProperty.Value) + result = null; + else if (!fileInfo.Exists) + result = null; + else + { + json = File.ReadAllText(fileInfo.FullName); + try + { + bool check = true; + property = JsonSerializer.Deserialize(json); + if (!isIgnoreExtension && isValidImageFormatExtension && ((populateId && property?.Id is null) || property?.Width is null || property?.Height is null)) + { + check = false; + id = property?.Id; + if (property is not null && property.Indices.Any()) + indices = property.Indices.ToList(); + property = GetImagePropertyB(angleBracket, filteredSourceDirectoryFileInfo, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + } + if (!isIgnoreExtension && isValidImageFormatExtension && populateId && property is not null && !property.Indices.Any()) + { + check = false; + id = property?.Id; + if (property is not null && property.Indices.Any()) + indices = property.Indices.ToList(); + property = GetImagePropertyB(angleBracket, filteredSourceDirectoryFileInfo, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + } + if (!isIgnoreExtension && isValidImageFormatExtension && populateId && property is not null && property.LastWriteTime != filteredSourceDirectoryFileInfo.LastWriteTime) + { + check = false; + id = null; + indices.Clear(); + property = GetImagePropertyB(angleBracket, filteredSourceDirectoryFileInfo, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + } + if (!isIgnoreExtension && isValidImageFormatExtension && property?.Width is not null && property?.Height is not null && property.Width.Value == property.Height.Value && filteredSourceDirectoryFileInfo.Exists) + { + check = false; + id = property?.Id; + if (property is not null && property.Indices.Any()) + indices = property.Indices.ToList(); + property = GetImagePropertyB(angleBracket, filteredSourceDirectoryFileInfo, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + if (property?.Width is not null && property?.Height is not null && property.Width.Value != property.Height.Value) + throw new Exception("Was square!"); + } + // if (filteredSourceDirectoryFileFileInfo.CreationTime != property?.CreationTime || filteredSourceDirectoryFileFileInfo.LastWriteTime != property?.LastWriteTime) + // { + // check = false; + // id = null; + // indices.Clear(); + // property = GetImagePropertyB(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + // } + if (json.Contains("WrongYear")) + { + id = property?.Id; + hasWrongYearProperty = true; + } + if (property is null) + throw new Exception(); + if (!check) + result = null; + else + { + result = property; + filteredSourceDirectoryFileTuples.Add(new Tuple(nameof(A_Property), fileInfo.LastWriteTime)); + } + } + catch (Exception) + { + result = null; + parseExceptions.Add(nameof(A_Property)); + } + } + if (result is null) + { + result = GetImagePropertyB(angleBracket, filteredSourceDirectoryFileInfo, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); + json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions); + if (populateId && IPath.WriteAllText(fileInfo.FullName, json, compareBeforeWrite: true)) + { + if (!_Configuration.ForcePropertyLastWriteTimeToCreationTime.Value && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime)) + filteredSourceDirectoryFileTuples.Add(new Tuple(nameof(A_Property), DateTime.Now)); + else + { + File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); + fileInfo.Refresh(); + filteredSourceDirectoryFileTuples.Add(new Tuple(nameof(A_Property), fileInfo.CreationTime)); + } + } + } + else if (hasWrongYearProperty) + { + json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions); + if (IPath.WriteAllText(fileInfo.FullName, json, compareBeforeWrite: true)) + { + File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); + fileInfo.Refresh(); + filteredSourceDirectoryFileTuples.Add(new Tuple(nameof(A_Property), fileInfo.CreationTime)); + } + } + return result; + } + + private bool AnyFilesMoved(string sourceDirectory, PropertyHolder[] filteredPropertyHolderCollection) { bool result = false; if (_Log is null) @@ -440,52 +767,58 @@ public class PropertyLogic bool? isWrongYear; string seasonName; DateTime dateTime; - A_Property? property; string destinationFile; DateTime minimumDateTime; - FileInfo? propertyFileInfo; string destinationDirectory; string[] sourceDirectorySegments; - string filteredSourceDirectoryFile; - FileInfo filteredSourceDirectoryFileInfo; DateTime directoryMaximumOfMinimumDateTime = DateTime.MinValue; - for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++) + foreach (PropertyHolder propertyHolder in filteredPropertyHolderCollection) { - if (!group.ValidImageFormatExtentionCollection[i]) + if (propertyHolder.ValidImageFormatExtension is null || !propertyHolder.ValidImageFormatExtension.Value) continue; - property = group.PropertyCollection[i]; - if (property is null) + if (propertyHolder.Property is null) continue; - minimumDateTime = Stateless.A_Property.GetMinimumDateTime(property); + if (propertyHolder.FileInfo is null) + continue; + minimumDateTime = Stateless.A_Property.GetMinimumDateTime(propertyHolder.Property); if (minimumDateTime > directoryMaximumOfMinimumDateTime) directoryMaximumOfMinimumDateTime = minimumDateTime; - filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i]; - filteredSourceDirectoryFileInfo = new(filteredSourceDirectoryFile); - if (minimumDateTime != filteredSourceDirectoryFileInfo.CreationTime) + if (minimumDateTime != propertyHolder.FileInfo.CreationTime) { - (isWrongYear, matches) = property.IsWrongYear(filteredSourceDirectoryFile, minimumDateTime); + (isWrongYear, matches) = propertyHolder.Property.IsWrongYear(propertyHolder.FileInfo.FullName, minimumDateTime); if (isWrongYear is null || !isWrongYear.Value) dateTime = minimumDateTime; else { if (isWrongYear.HasValue && isWrongYear.Value) - _Log.Information($"Wrong Year? <{filteredSourceDirectoryFile}>"); + { + lock (propertyHolder) + propertyHolder.SetWrongYear(true); + } if (!matches.Any()) continue; if (!DateTime.TryParseExact(matches[0], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) continue; } try - { File.SetCreationTime(filteredSourceDirectoryFile, dateTime); } + { File.SetCreationTime(propertyHolder.FileInfo.FullName, dateTime); } catch (Exception) { } } - if (!_VerifyToSeason.Contains(group.SourceDirectory)) + if (!_VerifyToSeason.Contains(sourceDirectory)) continue; - propertyFileInfo = group.PropertyFileInfoCollection[i]; - if (propertyFileInfo is null) - continue; - sourceDirectorySegments = Path.GetFileName(group.SourceDirectory).Split(' '); + if (!propertyHolder.FileInfo.FullName.Contains("zzz ") && !propertyHolder.FileInfo.FullName.Contains("Camera ") && propertyHolder.Property.DateTimeOriginal.HasValue) + { + TimeSpan timeSpan = new(propertyHolder.Property.DateTimeOriginal.Value.Ticks - propertyHolder.Property.LastWriteTime.Ticks); + if (timeSpan.TotalHours > 6) + { + _Log.Warning($"*** propertyHolder.FileInfo.FullName <{propertyHolder.FileInfo.FullName}>"); + _Log.Warning($"*** DateTimeOriginal <{propertyHolder.Property.DateTimeOriginal.Value}>"); + _Log.Warning($"*** LastWriteTime <{propertyHolder.Property.LastWriteTime}>"); + _Log.Warning($"*** TotalHours <{timeSpan.TotalHours}>"); + } + } + sourceDirectorySegments = Path.GetFileName(sourceDirectory).Split(' '); (season, seasonName) = Stateless.A_Property.GetSeason(minimumDateTime.DayOfYear); if (sourceDirectorySegments[0] == "zzz") destinationDirectory = Path.Combine(_Configuration.RootDirectory, $"zzz ={minimumDateTime:yyyy}.{season} {seasonName} {string.Join(' ', sourceDirectorySegments.Skip(3))}"); @@ -493,74 +826,75 @@ public class PropertyLogic destinationDirectory = Path.Combine(_Configuration.RootDirectory, $"={minimumDateTime:yyyy}.{season} {seasonName} {string.Join(' ', sourceDirectorySegments.Skip(2))}"); else destinationDirectory = Path.Combine(_Configuration.RootDirectory, $"={minimumDateTime:yyyy}.{season} {seasonName}"); - if (destinationDirectory == group.SourceDirectory) + if (destinationDirectory == sourceDirectory) continue; + lock (propertyHolder) + propertyHolder.SetMoved(true); if (!result) result = true; if (!Directory.Exists(destinationDirectory)) _ = Directory.CreateDirectory(destinationDirectory); - destinationFile = Path.Combine(destinationDirectory, filteredSourceDirectoryFileInfo.Name); + destinationFile = Path.Combine(destinationDirectory, propertyHolder.FileInfo.Name); if (File.Exists(destinationFile)) { if (destinationFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture)) - destinationFile = Path.Combine(destinationDirectory, Path.ChangeExtension(filteredSourceDirectoryFileInfo.Name, ".jpeg")); + destinationFile = Path.Combine(destinationDirectory, Path.ChangeExtension(propertyHolder.FileInfo.Name, ".jpeg")); else if (destinationFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture)) - destinationFile = Path.Combine(destinationDirectory, Path.ChangeExtension(filteredSourceDirectoryFileInfo.Name, ".jpg")); + destinationFile = Path.Combine(destinationDirectory, Path.ChangeExtension(propertyHolder.FileInfo.Name, ".jpg")); } if (File.Exists(destinationFile)) { - _Log.Information($"*** source <{filteredSourceDirectoryFile}>"); + _Log.Information($"*** source <{propertyHolder.FileInfo.FullName}>"); _Log.Information($"*** destination <{destinationFile}>"); - if (propertyFileInfo.Exists) + if (propertyHolder.FileInfo.Exists) { - deleteFile = Path.ChangeExtension(propertyFileInfo.FullName, ".delete"); + deleteFile = Path.ChangeExtension(propertyHolder.FileInfo.FullName, ".delete"); if (File.Exists(deleteFile)) File.Delete(deleteFile); - File.Move(propertyFileInfo.FullName, deleteFile); + File.Move(propertyHolder.FileInfo.FullName, deleteFile); } } else { - File.Move(filteredSourceDirectoryFile, destinationFile); - if (propertyFileInfo.Exists) + File.Move(propertyHolder.FileInfo.FullName, destinationFile); + if (propertyHolder.FileInfo.Exists) { - deleteFile = Path.ChangeExtension(propertyFileInfo.FullName, ".delete"); + deleteFile = Path.ChangeExtension(propertyHolder.FileInfo.FullName, ".delete"); if (File.Exists(deleteFile)) File.Delete(deleteFile); - File.Move(propertyFileInfo.FullName, deleteFile); + File.Move(propertyHolder.FileInfo.FullName, deleteFile); } } } if (directoryMaximumOfMinimumDateTime != DateTime.MinValue) { - DirectoryInfo directoryInfo = new(group.SourceDirectory); + System.IO.DirectoryInfo directoryInfo = new(sourceDirectory); if (directoryInfo.LastWriteTime != directoryMaximumOfMinimumDateTime) - Directory.SetLastWriteTime(group.SourceDirectory, directoryMaximumOfMinimumDateTime); + Directory.SetLastWriteTime(sourceDirectory, directoryMaximumOfMinimumDateTime); } return result; } - private void WriteGroup(Group group, string angleBracket) + private void WriteGroup(int sourceDirectoryLength, PropertyHolder[] filteredPropertyHolderCollection, string angleBracket) { - if (!(from l in @group.PropertyCollection where l?.Width is null select true).Any()) + if (!(from l in filteredPropertyHolderCollection where l?.Property?.Width is null select true).Any()) { string key; string json; string checkFile; - A_Property? property; string checkDirectory; - int sourceDirectoryLength = group.SourceDirectory.Length; List> propertyCollectionKeyValuePairs = new(); JsonSerializerOptions writeIndentedJsonSerializerOptions = new() { WriteIndented = false }; - (int level, List directories) = IPath.Get(_Configuration.RootDirectory, group.SourceDirectory); + (int level, List directories) = IPath.Get(_Configuration.RootDirectory, filteredPropertyHolderCollection[0].SourceDirectory); string fileName = string.Concat(string.Join(_Configuration.FileNameDirectorySeparator, directories), ".json"); - for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++) + foreach (PropertyHolder propertyHolder in filteredPropertyHolderCollection) { - property = group.PropertyCollection[i]; - if (property is null) + if (propertyHolder.Property is null) continue; - key = IPath.GetRelativePath(group.FilteredSourceDirectoryFiles[i], sourceDirectoryLength); - propertyCollectionKeyValuePairs.Add(new KeyValuePair(key, property)); + if (propertyHolder.FileInfo is null) + continue; + key = IPath.GetRelativePath(propertyHolder.FileInfo.FullName, sourceDirectoryLength); + propertyCollectionKeyValuePairs.Add(new KeyValuePair(key, propertyHolder.Property)); } checkDirectory = IPath.GetDirectory(angleBracket, level, "[{}]"); checkFile = Path.Combine(checkDirectory, fileName); @@ -572,130 +906,132 @@ public class PropertyLogic } } - private (List> filteredSourceDirectoryFileTuples, bool isValidImageFormatExtension, FileInfo propertyFileInfo, A_Property property) ParallelForWork(bool firstPass, string angleBracket, string sourceDirectory, string filteredSourceDirectoryFile) + private void ParallelForWork(bool firstPass, string angleBracket, string sourceDirectory, List> filteredSourceDirectoryFileTuples, PropertyHolder propertyHolder) { + if (propertyHolder.FileInfo is null) + throw new Exception($"{nameof(propertyHolder.FileInfo)} is null!"); + A_Property property; List parseExceptions = new(); - List> filteredSourceDirectoryFileTuples = new(); - string extensionLowered = Path.GetExtension(filteredSourceDirectoryFile).ToLower(); + string extensionLowered = propertyHolder.FileInfo.Extension.ToLower(); bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(extensionLowered); + string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(propertyHolder.FileInfo.FullName); bool isValidImageFormatExtension = _Configuration.ValidImageFormatExtensions.Contains(extensionLowered); + lock (propertyHolder) + propertyHolder.SetValidImageFormatExtension(isValidImageFormatExtension); bool isIgnoreExtension = isValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(extensionLowered); - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filteredSourceDirectoryFile); string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{fileNameWithoutExtension}{extensionLowered}"); - if (isValidImageFormatExtension && filteredSourceDirectoryFile.Length == filteredSourceDirectoryFileExtensionLowered.Length && filteredSourceDirectoryFile != filteredSourceDirectoryFileExtensionLowered) - File.Move(filteredSourceDirectoryFile, filteredSourceDirectoryFileExtensionLowered); - string without = Path.Combine(angleBracket.Replace("<>", "{}"), $"{fileNameWithoutExtension}.json"); - FileInfo propertyFileInfo = new(Path.Combine(angleBracket.Replace("<>", "{}"), $"{fileNameWithoutExtension}{extensionLowered}.json")); - if (isValidImageFormatExtension && File.Exists(without)) + if (isValidImageFormatExtension && propertyHolder.FileInfo.FullName.Length == filteredSourceDirectoryFileExtensionLowered.Length && propertyHolder.FileInfo.FullName != filteredSourceDirectoryFileExtensionLowered) + File.Move(propertyHolder.FileInfo.FullName, filteredSourceDirectoryFileExtensionLowered); + if (propertyHolder.Changed is null || propertyHolder.Changed.Value || propertyHolder.Property is null) { - File.Move(without, propertyFileInfo.FullName); - propertyFileInfo.Refresh(); + string without = Path.Combine(angleBracket.Replace("<>", "{}"), $"{fileNameWithoutExtension}.json"); + FileInfo fileInfo = new(Path.Combine(angleBracket.Replace("<>", "{}"), $"{fileNameWithoutExtension}{extensionLowered}.json")); + if (isValidImageFormatExtension && File.Exists(without)) + { + File.Move(without, fileInfo.FullName); + fileInfo.Refresh(); + } + property = GetPropertyB(filteredSourceDirectoryFileTuples, parseExceptions, firstPass, angleBracket, propertyHolder.FileInfo, propertyHolder.Property, fileInfo, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions); + lock (propertyHolder) + propertyHolder.Update(fileInfo, property); } - A_Property property = GetProperty(filteredSourceDirectoryFileTuples, parseExceptions, firstPass, angleBracket, filteredSourceDirectoryFile, propertyFileInfo, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions); - return new(filteredSourceDirectoryFileTuples, isValidImageFormatExtension, propertyFileInfo, property); } - private int ParallelWork(bool firstPass, object @lock, long ticks, List> sourceDirectoryChanges, int count, Group group, string angleBracket) + private void ParallelWork(bool firstPass, List exceptions, List> sourceDirectoryChanges, int propertyHolderCollectionsCount, int g, string sourceDirectory, int r, PropertyHolder[] filteredPropertyHolderCollection, int totalSeconds, string angleBracket) { - int result = 0; - if (_Log is null) - throw new Exception($"{nameof(_Log)} is null!"); + List> filteredSourceDirectoryFileTuples = new(); ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _MaxDegreeOfParallelism }; - int totalSeconds = (int)Math.Truncate(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; - using (ProgressBar progressBar = new(group.FilteredSourceDirectoryFiles.Length, $"{group.G}) {group.R + 1:000} / {count:000} - {group.SourceDirectory} - {group.FilteredSourceDirectoryFiles.Length} file(s) - {totalSeconds} total second(s)", options)) - { - _ = Parallel.For(0, group.FilteredSourceDirectoryFiles.Length, parallelOptions, i => + using ProgressBar progressBar = new(filteredPropertyHolderCollection.Length, $"{r + 1:000}.{g} / {propertyHolderCollectionsCount:000}) {filteredPropertyHolderCollection.Length:000} file(s) - {totalSeconds} total second(s) - {sourceDirectory}", options); + _ = Parallel.For(0, filteredPropertyHolderCollection.Length, parallelOptions, i => + { + try { - try - { - long ticks = DateTime.Now.Ticks; - DateTime dateTime = DateTime.Now; - (List> filteredSourceDirectoryFileTuples, bool isValidImageFormatExtension, FileInfo propertyFileInfo, A_Property property) = ParallelForWork(firstPass, angleBracket, group.SourceDirectory, group.FilteredSourceDirectoryFiles[i]); - progressBar.Tick(); - if (_MaxDegreeOfParallelism < 2) - ticks = LogDelta(ticks, nameof(PropertyLogic.ParallelForWork)); - lock (@lock) - { - group.PropertyCollection[i] = property; - group.PropertyFileInfoCollection[i] = propertyFileInfo; - if (isValidImageFormatExtension) - group.ValidImageFormatExtentionCollection[i] = isValidImageFormatExtension; - sourceDirectoryChanges.AddRange(from l in filteredSourceDirectoryFileTuples where l.Item2 > dateTime select l); - } - } - catch (Exception ex) - { - result += 1; - _Log.Error(string.Concat(group.SourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex); - if (result == group.FilteredSourceDirectoryFiles.Length) - throw new Exception(string.Concat("All in [", group.SourceDirectory, "]failed!")); - } - }); - } - return result; + long ticks = DateTime.Now.Ticks; + DateTime dateTime = DateTime.Now; + List> collection; + ParallelForWork(firstPass, angleBracket, sourceDirectory, filteredSourceDirectoryFileTuples, filteredPropertyHolderCollection[i]); + progressBar.Tick(); + lock (filteredSourceDirectoryFileTuples) + collection = (from l in filteredSourceDirectoryFileTuples where l.Item2 > dateTime select l).ToList(); + lock (sourceDirectoryChanges) + sourceDirectoryChanges.AddRange(collection); + } + catch (Exception ex) + { + lock (exceptions) + exceptions.Add(ex); + } + }); } - private string SetAngleBracketCollectionAndGetZero(Configuration configuration, string sourceDirectory) + private string SetAngleBracketCollectionAndGetZero(Configuration configuration, string modelName, string predictorModelName, string sourceDirectory) { string result; AngleBracketCollection.Clear(); AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(configuration, - sourceDirectory, - nameof(A_Property), - string.Empty, - includeResizeGroup: false, - includeModel: false, - includePredictorModel: false, - contentDescription: string.Empty, - singletonDescription: "Properties for each image", - collectionDescription: string.Empty)); + modelName, + predictorModelName, + sourceDirectory, + nameof(A_Property), + string.Empty, + includeResizeGroup: false, + includeModel: false, + includePredictorModel: false, + contentDescription: string.Empty, + singletonDescription: "Properties for each image", + collectionDescription: string.Empty)); result = AngleBracketCollection[0]; return result; } - public List GetParallelWork(Configuration configuration, List topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection, bool firstPass, bool filterOnFirstPass) + public void ParallelWork(Configuration configuration, string modelName, string predictorModelName, long ticks, List propertyHolderCollections, bool firstPass) { - List results = new(); if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); if (_Configuration.PopulatePropertyId is null) throw new Exception($"{nameof(_Configuration.PopulatePropertyId)} is null!"); - Group group; - int exceptionCount; + int g; + int r; + int totalSeconds; string angleBracket; - object @lock = new(); - long ticks = DateTime.Now.Ticks; - string[] filteredSourceDirectoryFiles; + string sourceDirectory; + List exceptions = new(); + PropertyHolder[] filteredPropertyHolderCollection; List> sourceDirectoryChanges = new(); + int sourceDirectoryLength = configuration.RootDirectory.Length; + int propertyHolderCollectionsCount = propertyHolderCollections.Count; string propertyRoot = IResult.GetResultsGroupDirectory(configuration, nameof(A_Property)); - foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection) + foreach (PropertyHolder[] propertyHolderCollection in propertyHolderCollections) { - if (!topDirectories.Any()) + if (!propertyHolderCollection.Any()) continue; sourceDirectoryChanges.Clear(); - if (firstPass && !filterOnFirstPass) - filteredSourceDirectoryFiles = sourceDirectoryFiles; + if (firstPass) + filteredPropertyHolderCollection = (from l in propertyHolderCollection where l.NoJson is null || !l.NoJson.Value && (l.Changed is null || l.Changed.Value) select l).ToArray(); else - filteredSourceDirectoryFiles = (from l in sourceDirectoryFiles where !_Configuration.IgnoreExtensions.Contains(Path.GetExtension(l)) select l).ToArray(); - if (!filteredSourceDirectoryFiles.Any()) + filteredPropertyHolderCollection = (from l in propertyHolderCollection where l.FileInfo is not null && !_Configuration.IgnoreExtensions.Contains(l.FileInfo.Extension) select l).ToArray(); + if (!filteredPropertyHolderCollection.Any()) continue; - group = new(g, sourceDirectory, filteredSourceDirectoryFiles, r); - angleBracket = SetAngleBracketCollectionAndGetZero(configuration, sourceDirectory); - exceptionCount = ParallelWork(firstPass, @lock, ticks, sourceDirectoryChanges, groupCollection.Count, group, angleBracket); - if (exceptionCount != 0) + g = filteredPropertyHolderCollection[0].G; + r = filteredPropertyHolderCollection[0].R; + sourceDirectory = filteredPropertyHolderCollection[0].SourceDirectory; + totalSeconds = (int)Math.Truncate(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); + angleBracket = SetAngleBracketCollectionAndGetZero(configuration, modelName, predictorModelName, sourceDirectory); + ParallelWork(firstPass, exceptions, sourceDirectoryChanges, propertyHolderCollectionsCount, g, sourceDirectory, r, filteredPropertyHolderCollection, totalSeconds, angleBracket); + foreach (Exception exception in exceptions) + _Log.Error(string.Concat(sourceDirectory, Environment.NewLine, exception.Message, Environment.NewLine, exception.StackTrace), exception); + if (exceptions.Count == filteredPropertyHolderCollection.Length) + throw new Exception(string.Concat("All in [", sourceDirectory, "]failed!")); + if (exceptions.Count != 0) _ExceptionsDirectories.Add(sourceDirectory); - else - results.Add(group); bool? anyFilesMoved; - if (!firstPass || exceptionCount != 0) + if (!firstPass || exceptions.Count != 0) anyFilesMoved = null; else - anyFilesMoved = AnyFilesMoved(group); - if (exceptionCount != 0 || (anyFilesMoved is not null && anyFilesMoved.Value)) - results.Clear(); - if (exceptionCount == 0 && !firstPass && _Configuration.PopulatePropertyId.Value && (anyFilesMoved is null || !anyFilesMoved.Value)) - WriteGroup(group, angleBracket); + anyFilesMoved = AnyFilesMoved(sourceDirectory, filteredPropertyHolderCollection); + if (exceptions.Count == 0 && !firstPass && _Configuration.PopulatePropertyId.Value && (anyFilesMoved is null || !anyFilesMoved.Value)) + WriteGroup(sourceDirectoryLength, filteredPropertyHolderCollection, angleBracket); if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any()) { for (int y = 0; y < int.MaxValue; y++) @@ -707,27 +1043,18 @@ public class PropertyLogic _Log.Information(". . ."); } } - return results; - } - - public List DoWork(Configuration configuration, List topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection, bool firstPass) - { - List results = new(); - _ExceptionsDirectories.Clear(); - _ = GetParallelWork(configuration, topDirectories, groupCollection, firstPass, filterOnFirstPass: false); - results.AddRange(_ExceptionsDirectories); - return results; } public A_Property GetProperty(string angleBracket, string sourceDirectory, string filteredSourceDirectoryFile, List> filteredSourceDirectoryFileTuples, List parseExceptions, FileInfo fileInfo) { A_Property result; bool firstPass = false; - string extensionLowered = Path.GetExtension(filteredSourceDirectoryFile).ToLower(); + FileInfo filteredSourceDirectoryFileInfo = new(filteredSourceDirectoryFile); + string extensionLowered = filteredSourceDirectoryFileInfo.Extension.ToLower(); bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(extensionLowered); bool isValidImageFormatExtension = _Configuration.ValidImageFormatExtensions.Contains(extensionLowered); + string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filteredSourceDirectoryFileInfo.FullName); bool isIgnoreExtension = isValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(extensionLowered); - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filteredSourceDirectoryFile); string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{fileNameWithoutExtension}{extensionLowered}"); if (isValidImageFormatExtension && filteredSourceDirectoryFile.Length == filteredSourceDirectoryFileExtensionLowered.Length && filteredSourceDirectoryFile != filteredSourceDirectoryFileExtensionLowered) File.Move(filteredSourceDirectoryFile, filteredSourceDirectoryFileExtensionLowered); @@ -738,11 +1065,11 @@ public class PropertyLogic File.Move(without, propertyFileInfo.FullName); propertyFileInfo.Refresh(); } - result = GetProperty(filteredSourceDirectoryFileTuples, parseExceptions, firstPass, angleBracket, filteredSourceDirectoryFile, fileInfo, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions); + result = GetPropertyA(filteredSourceDirectoryFileTuples, parseExceptions, firstPass, angleBracket, filteredSourceDirectoryFileInfo, fileInfo, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions); return result; } - public (long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] GetPropertyIds(Configuration configuration, List groupCollection, bool saveToCollection) + public (long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] GetPropertyIds(Configuration configuration, string modelName, string predictorModelName, List groupCollection, bool saveToCollection) { List<(long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)> results = new(); int level; @@ -751,9 +1078,9 @@ public class PropertyLogic string checkDirectory; List directories; string propertyDirectory; - foreach (Group group in groupCollection) + foreach (DirectoryInfo group in groupCollection) { - angleBracket = SetAngleBracketCollectionAndGetZero(configuration, group.SourceDirectory); + angleBracket = SetAngleBracketCollectionAndGetZero(configuration, modelName, predictorModelName, group.SourceDirectory); if (string.IsNullOrEmpty(group.SourceDirectory)) throw new Exception(); if (!saveToCollection) @@ -766,7 +1093,7 @@ public class PropertyLogic } if (!Directory.Exists(propertyDirectory)) _ = Directory.CreateDirectory(propertyDirectory); - for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++) + for (int i = 0; i < group.SourceDirectoryFileInfoCollection.Length; i++) { property = group.PropertyCollection[i]; if (property?.Id is null) diff --git a/Property/Models/Stateless/A_Property.cs b/Property/Models/Stateless/A_Property.cs index bbc3879..2add6c5 100644 --- a/Property/Models/Stateless/A_Property.cs +++ b/Property/Models/Stateless/A_Property.cs @@ -1,3 +1,5 @@ +using System.Text.Json; + namespace View_by_Distance.Property.Models.Stateless; public static class A_Property @@ -26,10 +28,7 @@ public static class A_Property string[] sourceDirectoryFiles; List fileCollections = new(); if (!topDirectories.Any()) - { - topDirectories.Add(rootDirectory); topDirectories.AddRange(from l in Directory.GetDirectories(rootDirectory, "*", SearchOption.TopDirectoryOnly) select Path.GetFullPath(l)); - } for (int g = 1; g < 5; g++) { if (g == 4) @@ -105,6 +104,151 @@ public static class A_Property return results; } + public static List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> GetJsonGroupCollection(string rootDirectory) + { + List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> results; + bool reverse = false; + string searchPattern = "*.json"; + List topDirectories = new(); + int maxImagesInDirectoryForTopLevelFirstPass = 50; + results = GetGroupCollection(rootDirectory, searchPattern, topDirectories, maxImagesInDirectoryForTopLevelFirstPass, reverse); + return results; + } + + public static List<(int g, string sourceDirectory, FileInfo[] sourceDirectoryFiles, int r)> GetFileInfoGroupCollection(Models.Configuration configuration, bool reverse, string searchPattern, List topDirectories) + { + if (configuration.MaxImagesInDirectoryForTopLevelFirstPass is null) + throw new Exception($"{nameof(configuration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!"); + List<(int g, string sourceDirectory, FileInfo[] sourceDirectoryFiles, int r)> results = new(); + List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)>? collection = GetGroupCollection(configuration.RootDirectory, searchPattern, topDirectories, configuration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse); + foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in collection) + results.Add(new(g, sourceDirectory, (from l in sourceDirectoryFiles select new FileInfo(l)).ToArray(), r)); + return results; + } + + private static List<(int g, string sourceDirectory, List<(string sourceDirectoryFile, Models.A_Property? property)> collection, int r)> GetCollection(string rootDirectory, List<(int g, string sourceDirectory, string[] SourceDirectoryFiles, int r)> jsonCollection) + { + List<(int, string, List<(string, Models.A_Property?)>, int)> results = new(); + int length = rootDirectory.Length; + ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = Environment.ProcessorCount }; + _ = Parallel.For(0, jsonCollection.Count, parallelOptions, i => ParallelFor(jsonCollection, i, length, results)); + return results; + } + + private static List Populate(Models.Configuration configuration, string aPropertySingletonDirectory, List<(int, string, FileInfo[], int)> fileInfoGroupCollection, List<(int, string, List<(string, Models.A_Property?)>, int)> collectionFromJson) + { + List results = new(); + if (configuration.PropertiesChangedForProperty is null) + throw new Exception($"{configuration.PropertiesChangedForProperty} is null"); + int length; + string inferred; + string relativePath; + FileInfo keyFileInfo; + string keySourceDirectory; + List propertyHolderCollection; + Dictionary fileInfoKeyValuePairs = new(); + length = configuration.RootDirectory.Length; + foreach ((int g, string sourceDirectory, FileInfo[] sourceDirectoryFileInfoCollection, int r) in fileInfoGroupCollection) + { + foreach (FileInfo sourceDirectoryFileInfo in sourceDirectoryFileInfoCollection) + { + relativePath = $"{XPath.GetRelativePath(sourceDirectoryFileInfo.FullName, length)}.json"; + fileInfoKeyValuePairs.Add(relativePath, new(sourceDirectory, sourceDirectoryFileInfo)); + } + } + length = aPropertySingletonDirectory.Length; + foreach ((int g, string _, List<(string, Models.A_Property?)> collection, int r) in collectionFromJson) + { + if (!collection.Any()) + continue; + propertyHolderCollection = new(); + foreach ((string sourceDirectoryFile, Models.A_Property? property) in collection) + { + relativePath = XPath.GetRelativePath(sourceDirectoryFile, length); + if (!fileInfoKeyValuePairs.ContainsKey(relativePath)) + { + inferred = string.Concat(configuration.RootDirectory, relativePath); + keyFileInfo = new(inferred[..^5]); + keySourceDirectory = string.Concat(keyFileInfo.DirectoryName); + propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, true, null, null, null, null)); + } + else + { + keyFileInfo = fileInfoKeyValuePairs[relativePath].FileInfo; + keySourceDirectory = fileInfoKeyValuePairs[relativePath].SourceDirectory; + if (!fileInfoKeyValuePairs.Remove(relativePath)) + throw new Exception(); + if (property?.Id is null || property?.Width is null || property?.Height is null) + propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, false, null, null, null, null)); + else if (configuration.PropertiesChangedForProperty.Value || property.LastWriteTime != keyFileInfo.LastWriteTime || property.FileSize != keyFileInfo.Length) + propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, false, true, null, null, null)); + else + propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, false, false, null, null, null)); + } + } + if (propertyHolderCollection.Any()) + results.Add(propertyHolderCollection.ToArray()); + } + length = configuration.RootDirectory.Length; + foreach ((int g, string sourceDirectory, FileInfo[] sourceDirectoryFileInfoCollection, int r) in fileInfoGroupCollection) + { + propertyHolderCollection = new(); + foreach (FileInfo sourceDirectoryFileInfo in sourceDirectoryFileInfoCollection) + { + relativePath = $"{XPath.GetRelativePath(sourceDirectoryFileInfo.FullName, length)}.json"; + if (!fileInfoKeyValuePairs.ContainsKey(relativePath)) + continue; + if (!fileInfoKeyValuePairs.Remove(relativePath)) + throw new Exception(); + propertyHolderCollection.Add(new(g, sourceDirectory, relativePath, sourceDirectoryFileInfo.FullName, r, sourceDirectoryFileInfo, null, null, null, null, null, null)); + } + if (propertyHolderCollection.Any()) + results.Add(propertyHolderCollection.ToArray()); + } + if (fileInfoKeyValuePairs.Any()) + throw new Exception(); + results = (from l in results orderby l[0].G, l[0].R select l).ToList(); + return results; + } + + private static void ParallelFor(List<(int, string, string[], int)> jsonCollection, int i, int length, List<(int, string, List<(string, Models.A_Property?)>, int)> results) + { + string key; + string json; + Models.A_Property? property; + (int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) = jsonCollection[i]; + List<(string, Models.A_Property?)> collection = new(); + foreach (string sourceDirectoryFile in sourceDirectoryFiles) + { + json = File.ReadAllText(sourceDirectoryFile); + key = XPath.GetRelativePath(sourceDirectoryFile, length); + property = JsonSerializer.Deserialize(json); + collection.Add(new(sourceDirectoryFile, property)); + } + lock (results) + results.Add(new(g, sourceDirectory, collection, r)); + } + + public static List Get(Models.Configuration configuration, bool reverse, string modelName, string predictorModelName, PropertyLogic propertyLogic) + { + List results; + string searchPattern = "*"; + long ticks = DateTime.Now.Ticks; + List topDirectories = new(); + List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> jsonCollection; + List<(int g, string sourceDirectory, FileInfo[] sourceDirectoryFiles, int r)> fileInfoGroupCollection; + string aPropertySingletonDirectory = IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); + List<(int g, string sourceDirectory, List<(string sourceDirectoryFile, Models.A_Property? property)> collection, int r)> collectionFromJson; + jsonCollection = GetJsonGroupCollection(aPropertySingletonDirectory); + fileInfoGroupCollection = GetFileInfoGroupCollection(configuration, reverse, searchPattern, topDirectories); + collectionFromJson = GetCollection(aPropertySingletonDirectory, jsonCollection); + results = Populate(configuration, aPropertySingletonDirectory, fileInfoGroupCollection, collectionFromJson); + propertyLogic.ParallelWork(configuration, modelName, predictorModelName, ticks, results, firstPass: false); + if (propertyLogic.ExceptionsDirectories.Any()) + throw new Exception(); + return results; + } + public static int GetDeterministicHashCode(byte[] value) { int result; @@ -199,20 +343,20 @@ public static class A_Property result = DateTime.MinValue; else { - List datetimes = new() + List dateTimes = new() { property.CreationTime, property.LastWriteTime }; if (property.DateTime.HasValue) - datetimes.Add(property.DateTime.Value); + dateTimes.Add(property.DateTime.Value); if (property.DateTimeDigitized.HasValue) - datetimes.Add(property.DateTimeDigitized.Value); + dateTimes.Add(property.DateTimeDigitized.Value); if (property.DateTimeOriginal.HasValue) - datetimes.Add(property.DateTimeOriginal.Value); + dateTimes.Add(property.DateTimeOriginal.Value); if (property.GPSDateStamp.HasValue) - datetimes.Add(property.GPSDateStamp.Value); - result = datetimes.Min(); + dateTimes.Add(property.GPSDateStamp.Value); + result = dateTimes.Min(); } return result; } @@ -222,139 +366,17 @@ public static class A_Property public static DateTime GetMinimumDateTime(Models.A_Property? property) { DateTime result; - List datetimes; + List dateTimes; if (property is null) result = DateTime.MinValue; else { - datetimes = GetDateTimes(property); - result = datetimes.Min(); + dateTimes = GetDateTimes(property); + result = dateTimes.Min(); } return result; } - public static string[] GetDirectoryRenameCollection(Models.Configuration configuration, string outputResolution, string bMetadata, string cResizeName) - { - List results = new(); - string cResizeContentDirectory; - string cResizeSingletonDirectory; - string bMetadataSingletonDirectory; - string aPropertySingletonDirectory; - bMetadataSingletonDirectory = IResult.GetResultsDateGroupDirectory(configuration, bMetadata, "{}"); - if (Directory.Exists(bMetadataSingletonDirectory)) - results.Add(bMetadataSingletonDirectory); - aPropertySingletonDirectory = IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); - if (Directory.Exists(aPropertySingletonDirectory)) - results.Add(aPropertySingletonDirectory); - cResizeContentDirectory = Path.Combine(IResult.GetResultsFullGroupDirectory(configuration, cResizeName, outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"); - if (Directory.Exists(cResizeContentDirectory)) - results.Add(cResizeContentDirectory); - cResizeSingletonDirectory = Path.Combine(IResult.GetResultsFullGroupDirectory(configuration, cResizeName, outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "{}"); - if (Directory.Exists(cResizeSingletonDirectory)) - results.Add(cResizeSingletonDirectory); - return results.ToArray(); - } - - public static void SearchForAbandonedFilesFull(string argZero, string rootDirectory, bool onlyJson) - { - bool check; - string[] files; - string moveFile; - string extension; - string? directory; - const int last = 6; - string searchPattern; - string searchDirectory; - int lessThan = last + 1; - string? parentDirectory; - DirectoryInfo directoryInfo; - string fileNameWithoutExtension; - IEnumerator enumerator; - List fileMovePaths = new(); - List toReviewFiles = new(); - int rootDirectoryLength = rootDirectory.Length; - for (int i = 1; i < lessThan; i++) - { - files = i switch - { - 1 => Directory.GetFiles(rootDirectory, "*.json", SearchOption.AllDirectories), - 2 => Directory.GetFiles(rootDirectory, "*.nosj", SearchOption.AllDirectories), - 3 => Directory.GetFiles(rootDirectory, "*.jpeg", SearchOption.AllDirectories), - 4 => Directory.GetFiles(rootDirectory, "*.tvs", SearchOption.AllDirectories), - 5 => Directory.GetFiles(rootDirectory, "*.png", SearchOption.AllDirectories), - last => Directory.GetFiles(rootDirectory, "*", SearchOption.AllDirectories), - _ => Array.Empty() - }; - foreach (string file in files) - { - extension = Path.GetExtension(file); - if (extension == ".delete") - continue; - directory = Path.GetDirectoryName(file); - if (string.IsNullOrEmpty(directory)) - continue; - fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); - if (file.EndsWith(" - R.png")) - continue; - if (fileNameWithoutExtension.Length < 1) - continue; - if (fileNameWithoutExtension[1..] != string.Concat(" - ", Path.GetFileNameWithoutExtension(directory))) - { - searchPattern = string.Concat(fileNameWithoutExtension, '*'); - searchDirectory = string.Concat(argZero, directory[rootDirectoryLength..]); - } - else - { - if (fileNameWithoutExtension.Length < 4) - continue; - searchPattern = string.Concat(fileNameWithoutExtension[4..], '*'); - parentDirectory = Path.GetDirectoryName(directory); - if (string.IsNullOrEmpty(parentDirectory)) - continue; - searchDirectory = string.Concat(argZero, parentDirectory[rootDirectoryLength..]); - } - directoryInfo = new(searchDirectory); - if (!directoryInfo.Exists) - check = false; - else - { - enumerator = directoryInfo.EnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly).GetEnumerator(); - check = enumerator.MoveNext(); - } - if (check) - continue; - toReviewFiles.Add(file); - } - if (toReviewFiles.Any()) - throw new Exception("Need to fix property having the extension before .json extension!"); - foreach (string toReviewFile in toReviewFiles) - { - extension = Path.GetExtension(toReviewFile); - if (extension == ".delete") - continue; - directory = Path.GetDirectoryName(toReviewFile); - if (string.IsNullOrEmpty(directory)) - continue; - moveFile = Path.Combine(directory, Path.ChangeExtension(toReviewFile, ".delete")); - if (i == last) - fileMovePaths.Add(new string[] { toReviewFile, moveFile }); - else if (extension is ".nosj") - File.Delete(toReviewFile); - else - { - if (File.Exists(moveFile)) - File.Delete(moveFile); - File.Move(toReviewFile, moveFile); - } - } - toReviewFiles.Clear(); - if (onlyJson) - break; - } - if (fileMovePaths.Any()) - throw new Exception(string.Join(',', (from l in fileMovePaths select l[0]).ToArray())); - } - public static string GetDiffRootDirectory(string diffPropertyDirectory) { string result = string.Empty; @@ -374,4 +396,96 @@ public static class A_Property return result; } + public static double GetStandardDeviation(IEnumerable values, double average) + { + double result = 0; + if (!values.Any()) + throw new Exception("Collection must have at least one value!"); + double sum = values.Sum(l => (l - average) * (l - average)); + result = Math.Sqrt(sum / values.Count()); + return result; + } + + public static TimeSpan GetThreeStandardDeviationHigh(int minimum, PropertyHolder[] propertyHolderCollection) + { + TimeSpan result; + List ticksCollection = new(); + foreach (PropertyHolder propertyHolder in propertyHolderCollection) + { + if (propertyHolder.Property is null || propertyHolder.MinimumDateTime is null) + continue; + ticksCollection.Add(propertyHolder.MinimumDateTime.Value.Ticks); + } + long threeStandardDeviationHigh; + long min; + if (!ticksCollection.Any()) + min = 0; + else + min = ticksCollection.Min(); + if (ticksCollection.Count < minimum) + threeStandardDeviationHigh = long.MaxValue; + else + { + ticksCollection = (from l in ticksCollection select l - min).ToList(); + double sum = ticksCollection.Sum(); + double average = sum / ticksCollection.Count; + double standardDeviation = GetStandardDeviation(ticksCollection, average); + threeStandardDeviationHigh = (long)Math.Ceiling(average + min + (standardDeviation * 3)); + } + result = new TimeSpan(threeStandardDeviationHigh - min); + return result; + } + + public static (int, List, List) Get(PropertyHolder[] propertyHolderCollection, TimeSpan threeStandardDeviationHigh, int i) + { + List results = new(); + int j = i; + long? ticks; + TimeSpan timeSpan; + PropertyHolder propertyHolder; + List dateTimes = new(); + PropertyHolder nextPropertyHolder; + for (; j < propertyHolderCollection.Length; j++) + { + ticks = null; + propertyHolder = propertyHolderCollection[j]; + if (propertyHolder.Property is null || propertyHolder.MinimumDateTime is null) + continue; + for (int k = j + 1; k < propertyHolderCollection.Length; k++) + { + nextPropertyHolder = propertyHolderCollection[k]; + if (nextPropertyHolder.Property is not null && nextPropertyHolder.MinimumDateTime is not null) + { + ticks = nextPropertyHolder.MinimumDateTime.Value.Ticks; + break; + } + } + results.Add(propertyHolder); + dateTimes.Add(propertyHolder.MinimumDateTime.Value); + if (ticks.HasValue) + { + timeSpan = new(ticks.Value - propertyHolder.MinimumDateTime.Value.Ticks); + if (timeSpan > threeStandardDeviationHigh) + break; + } + } + return new(j, dateTimes, results); + } + + public static bool Any(List propertyHolderCollections) + { + bool result = false; + foreach (PropertyHolder[] propertyHolderCollection in propertyHolderCollections) + { + if (!propertyHolderCollection.Any()) + continue; + if ((from l in propertyHolderCollection where l.Any() select true).Any()) + { + result = true; + break; + } + } + return result; + } + } \ No newline at end of file diff --git a/Property/Models/Stateless/IResult.cs b/Property/Models/Stateless/IResult.cs index 0bde5ed..d576802 100644 --- a/Property/Models/Stateless/IResult.cs +++ b/Property/Models/Stateless/IResult.cs @@ -15,10 +15,10 @@ public interface IResult string TestStatic_GetResultsDateGroupDirectory(Models.Configuration configuration, string description, string jsonGroup); static string GetResultsDateGroupDirectory(Models.Configuration configuration, string description, string jsonGroup) => Result.GetResultsDateGroupDirectory(configuration, description, jsonGroup); - string TestStatic_GetResultsFullGroupDirectory(Models.Configuration configuration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel); - static string GetResultsFullGroupDirectory(Models.Configuration configuration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) => Result.GetResultsFullGroupDirectory(configuration, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel); + string TestStatic_GetResultsFullGroupDirectory(Models.Configuration configuration, string modelName, string predictorModelName, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel); + static string GetResultsFullGroupDirectory(Models.Configuration configuration, string modelName, string predictorModelName, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) => Result.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel); List TestStatic_GetDirectoryInfoCollection(Models.Configuration configuration, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription); - static List GetDirectoryInfoCollection(Models.Configuration configuration, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) => Result.GetDirectoryInfoCollection(configuration, sourceDirectory, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel, contentDescription, singletonDescription, collectionDescription); + static List GetDirectoryInfoCollection(Models.Configuration configuration, string modelName, string predictorModelName, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) => Result.GetDirectoryInfoCollection(configuration, modelName, predictorModelName, sourceDirectory, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel, contentDescription, singletonDescription, collectionDescription); } \ No newline at end of file diff --git a/Property/Models/Stateless/Result.cs b/Property/Models/Stateless/Result.cs index 531f4dc..3de00a7 100644 --- a/Property/Models/Stateless/Result.cs +++ b/Property/Models/Stateless/Result.cs @@ -33,14 +33,14 @@ internal class Result return result; } - internal static string GetResultsFullGroupDirectory(Models.Configuration configuration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) + internal static string GetResultsFullGroupDirectory(Models.Configuration configuration, string modelName, string predictorModelName, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) { string result = GetResultsDateGroupDirectory(configuration, description); if (includeResizeGroup) result = Path.Combine(result, outputResolution); if (includeModel && includePredictorModel) { - string dateGroupDirectory = string.Concat(outputResolution.Replace(" ", string.Empty), " - ", "_Configuration.ModelName", " - ", "_Configuration.PredictorModelName"); + string dateGroupDirectory = string.Concat(outputResolution.Replace(" ", string.Empty), " - ", modelName, " - ", predictorModelName); result = Path.Combine(result, dateGroupDirectory); } else if (includeModel) @@ -52,17 +52,17 @@ internal class Result return result; } - internal static List GetDirectoryInfoCollection(Models.Configuration configuration, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) + internal static List GetDirectoryInfoCollection(Models.Configuration configuration, string modelName, string predictorModelName, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) { List results = new(); string result = string.Empty; string checkDirectory; string sourceDirectorySegment = GetRelativePath(configuration, sourceDirectory); - string dateGroupDirectory = IResult.GetResultsFullGroupDirectory(configuration, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel); + string dateGroupDirectory = IResult.GetResultsFullGroupDirectory(configuration, modelName, predictorModelName, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel); if (!string.IsNullOrEmpty(contentDescription)) { result = string.Concat(Path.Combine(dateGroupDirectory, "<>"), sourceDirectorySegment); - DirectoryInfo contentDirectoryInfo = new(result.Replace("<>", "()")); + System.IO.DirectoryInfo contentDirectoryInfo = new(result.Replace("<>", "()")); if (!contentDirectoryInfo.Exists) contentDirectoryInfo.Create(); checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("() - ", contentDescription)); @@ -72,7 +72,7 @@ internal class Result if (!string.IsNullOrEmpty(singletonDescription)) { result = string.Concat(Path.Combine(dateGroupDirectory, "<>"), sourceDirectorySegment); - DirectoryInfo singletonDirectoryInfo = new(result.Replace("<>", "{}")); + System.IO.DirectoryInfo singletonDirectoryInfo = new(result.Replace("<>", "{}")); if (!singletonDirectoryInfo.Exists) singletonDirectoryInfo.Create(); checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("{} - ", singletonDescription)); @@ -82,7 +82,7 @@ internal class Result if (!string.IsNullOrEmpty(collectionDescription)) { result = string.Concat(Path.Combine(dateGroupDirectory, "<>"), sourceDirectorySegment); - DirectoryInfo collectionDirectoryInfo = new(result.Replace("<>", "[]")); + System.IO.DirectoryInfo collectionDirectoryInfo = new(result.Replace("<>", "[]")); if (!collectionDirectoryInfo.Exists) collectionDirectoryInfo.Create(); checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("[] - ", collectionDescription)); diff --git a/Resize/Models/_C_Resize.cs b/Resize/Models/_C_Resize.cs index 2861cca..90a98fc 100644 --- a/Resize/Models/_C_Resize.cs +++ b/Resize/Models/_C_Resize.cs @@ -119,44 +119,35 @@ public class C_Resize int outputResolutionOrientation = resize[2]; using Bitmap temp = new(subFile, useIcm: false); PropertyItem[] propertyItems = temp.PropertyItems; + bitmap = new(temp, outputResolutionWidth, outputResolutionHeight); switch (outputResolutionOrientation) // exif 274 { case 0: - bitmap = new(temp, outputResolutionWidth, outputResolutionHeight); break; case 1: - bitmap = new(temp, outputResolutionWidth, outputResolutionHeight); break; // 1 = Horizontal (normal) case 2: - bitmap = new(temp, outputResolutionWidth, outputResolutionHeight); bitmap.RotateFlip(RotateFlipType.RotateNoneFlipX); break; // 2 = Mirror horizontal case 3: - bitmap = new(temp, outputResolutionWidth, outputResolutionHeight); bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone); break; // 3 = Rotate 180 case 4: - bitmap = new(temp, outputResolutionWidth, outputResolutionHeight); bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); break; // 4 = Mirror vertical case 5: - bitmap = new(temp, outputResolutionHeight, outputResolutionWidth); bitmap.RotateFlip(RotateFlipType.Rotate270FlipX); break; // 5 = Mirror horizontal and rotate 270 CW case 6: - bitmap = new(temp, outputResolutionHeight, outputResolutionWidth); bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone); break; // 6 = Rotate 90 CW case 7: - bitmap = new(temp, outputResolutionHeight, outputResolutionWidth); bitmap.RotateFlip(RotateFlipType.Rotate90FlipX); break; // 7 = Mirror horizontal and rotate 90 CW case 8: - bitmap = new(temp, outputResolutionHeight, outputResolutionWidth); bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone); break; // 8 = Rotate 270 CW default: - bitmap = new(temp, outputResolutionWidth, outputResolutionHeight); break; } if (fileInfo is null) @@ -182,44 +173,35 @@ public class C_Resize int outputResolutionOrientation = resize[2]; using Bitmap temp = new(subFile, useIcm: false); PropertyItem[] propertyItems = temp.PropertyItems; + bitmap = new(temp, tempResolutionWidth, tempResolutionHeight); switch (outputResolutionOrientation) // exif 274 { case 0: - bitmap = new(temp, tempResolutionWidth, tempResolutionHeight); break; case 1: - bitmap = new(temp, tempResolutionWidth, tempResolutionHeight); break; // 1 = Horizontal (normal) case 2: - bitmap = new(temp, tempResolutionWidth, tempResolutionHeight); bitmap.RotateFlip(RotateFlipType.RotateNoneFlipX); break; // 2 = Mirror horizontal case 3: - bitmap = new(temp, tempResolutionWidth, tempResolutionHeight); bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone); break; // 3 = Rotate 180 case 4: - bitmap = new(temp, tempResolutionWidth, tempResolutionHeight); bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); break; // 4 = Mirror vertical case 5: - bitmap = new(temp, tempResolutionHeight, tempResolutionWidth); bitmap.RotateFlip(RotateFlipType.Rotate270FlipX); break; // 5 = Mirror horizontal and rotate 270 CW case 6: - bitmap = new(temp, tempResolutionHeight, tempResolutionWidth); bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone); break; // 6 = Rotate 90 CW case 7: - bitmap = new(temp, tempResolutionHeight, tempResolutionWidth); bitmap.RotateFlip(RotateFlipType.Rotate90FlipX); break; // 7 = Mirror horizontal and rotate 90 CW case 8: - bitmap = new(temp, tempResolutionHeight, tempResolutionWidth); bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone); break; // 8 = Rotate 270 CW default: - bitmap = new(temp, tempResolutionWidth, tempResolutionHeight); break; } Bitmap preRotated; diff --git a/Shared/Models/DirectoryFileSystem.cs b/Shared/Models/DirectoryFileSystem.cs index 2693242..ec0cc1a 100644 --- a/Shared/Models/DirectoryFileSystem.cs +++ b/Shared/Models/DirectoryFileSystem.cs @@ -4,7 +4,7 @@ using View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Shared.Models; -public class DirectoryFileSystem : Models.FileSystem, Properties.IDirectoryFileSystem, IDirectoryFileSystem +public class DirectoryFileSystem : FileSystem, Properties.IDirectoryFileSystem, IDirectoryFileSystem { // protected new string _ClassName; diff --git a/Shared/Models/Face.cs b/Shared/Models/Face.cs index c6945fb..d493a4b 100644 --- a/Shared/Models/Face.cs +++ b/Shared/Models/Face.cs @@ -9,25 +9,25 @@ public class Face : Properties.IFace, IFace protected double? _Α; protected DateTime _DateTime; - protected Models.FaceEncoding _FaceEncoding; - protected Dictionary _FaceLandmarks; - protected Models.OutputResolution _OutputResolution; - protected Models.Location _Location; + protected FaceEncoding _FaceEncoding; + protected Dictionary _FaceLandmarks; + protected OutputResolution _OutputResolution; + protected Location _Location; protected int? _LocationIndex; protected bool _Populated; protected string _RelativePath; public double? α => _Α; public DateTime DateTime => _DateTime; - public Models.FaceEncoding FaceEncoding => _FaceEncoding; - public Dictionary FaceLandmarks => _FaceLandmarks; - public Models.OutputResolution OutputResolution => _OutputResolution; - public Models.Location Location => _Location; + public FaceEncoding FaceEncoding => _FaceEncoding; + public Dictionary FaceLandmarks => _FaceLandmarks; + public OutputResolution OutputResolution => _OutputResolution; + public Location Location => _Location; public int? LocationIndex => _LocationIndex; public bool Populated => _Populated; public string RelativePath => _RelativePath; [JsonConstructor] - public Face(double? α, DateTime dateTime, View_by_Distance.Shared.Models.FaceEncoding faceEncoding, Dictionary faceLandmarks, Models.OutputResolution outputResolution, View_by_Distance.Shared.Models.Location location, int? locationIndex, bool populated, string relativePath) + public Face(double? α, DateTime dateTime, FaceEncoding faceEncoding, Dictionary faceLandmarks, OutputResolution outputResolution, Location location, int? locationIndex, bool populated, string relativePath) { _Α = α; _DateTime = dateTime; diff --git a/Shared/Models/FaceFileSystem.cs b/Shared/Models/FaceFileSystem.cs index 562d1e8..7851540 100644 --- a/Shared/Models/FaceFileSystem.cs +++ b/Shared/Models/FaceFileSystem.cs @@ -4,7 +4,7 @@ using View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Shared.Models; -public class FaceFileSystem : Models.FileSystem, Properties.IFaceFileSystem, IFaceFileSystem +public class FaceFileSystem : FileSystem, Properties.IFaceFileSystem, IFaceFileSystem { // protected new string _ClassName; diff --git a/Shared/Models/Navigate.cs b/Shared/Models/Navigate.cs index 4a4090f..25e8cfe 100644 --- a/Shared/Models/Navigate.cs +++ b/Shared/Models/Navigate.cs @@ -10,17 +10,17 @@ public class Navigate : Properties.INavigate protected string _SourceDirectory; protected string _DirectoryRelativePath; protected string _EncodedSourceDirectory; - protected Models.FaceFileSystem[] _FaceFileSystemCollection; - protected Models.DirectoryFileSystem[] _DirectoryFileSystemCollection; + protected FaceFileSystem[] _FaceFileSystemCollection; + protected DirectoryFileSystem[] _DirectoryFileSystemCollection; public List Levels => _Levels; public string SourceDirectory => _SourceDirectory; public string DirectoryRelativePath => _DirectoryRelativePath; public string EncodedSourceDirectory => _EncodedSourceDirectory; - public Models.FaceFileSystem[] FaceFileSystemCollection => _FaceFileSystemCollection; - public Models.DirectoryFileSystem[] DirectoryFileSystemCollection => _DirectoryFileSystemCollection; + public FaceFileSystem[] FaceFileSystemCollection => _FaceFileSystemCollection; + public DirectoryFileSystem[] DirectoryFileSystemCollection => _DirectoryFileSystemCollection; [JsonConstructor] - public Navigate(List levels, string sourceDirectory, string directoryRelativePath, string encodedSourceDirectory, Models.FaceFileSystem[] faceFileSystemCollection, Models.DirectoryFileSystem[] directoryFileSystemCollection) + public Navigate(List levels, string sourceDirectory, string directoryRelativePath, string encodedSourceDirectory, FaceFileSystem[] faceFileSystemCollection, DirectoryFileSystem[] directoryFileSystemCollection) { _Levels = levels; _SourceDirectory = sourceDirectory; diff --git a/Shared/Models/Properties/IFace.cs b/Shared/Models/Properties/IFace.cs index 71f8bf2..b263c28 100644 --- a/Shared/Models/Properties/IFace.cs +++ b/Shared/Models/Properties/IFace.cs @@ -7,11 +7,11 @@ public interface IFace public double? α { get; } #pragma warning restore IDE1006 public DateTime DateTime { get; } - public Models.FaceEncoding FaceEncoding { get; } - public Dictionary FaceLandmarks { get; } - public Models.Location Location { get; } + public FaceEncoding FaceEncoding { get; } + public Dictionary FaceLandmarks { get; } + public Location Location { get; } public int? LocationIndex { get; } - public Models.OutputResolution OutputResolution { get; } + public OutputResolution OutputResolution { get; } public bool Populated { get; } public string RelativePath { get; } diff --git a/Shared/Models/Properties/INavigate.cs b/Shared/Models/Properties/INavigate.cs index 27a73a3..d03641b 100644 --- a/Shared/Models/Properties/INavigate.cs +++ b/Shared/Models/Properties/INavigate.cs @@ -6,7 +6,7 @@ public interface INavigate public List Levels { get; } public string SourceDirectory { get; } public string DirectoryRelativePath { get; } - public Models.FaceFileSystem[] FaceFileSystemCollection { get; } - public Models.DirectoryFileSystem[] DirectoryFileSystemCollection { get; } + public FaceFileSystem[] FaceFileSystemCollection { get; } + public DirectoryFileSystem[] DirectoryFileSystemCollection { get; } } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/FaceFileSystem.cs b/Shared/Models/Stateless/Methods/FaceFileSystem.cs index dc67fcb..d49c3bf 100644 --- a/Shared/Models/Stateless/Methods/FaceFileSystem.cs +++ b/Shared/Models/Stateless/Methods/FaceFileSystem.cs @@ -27,7 +27,7 @@ internal abstract class FaceFileSystem { string json = File.ReadAllText(dataFullFileName); if (!json.Contains("MesaFab")) - throw new Exception($"Maybe file <{Path.GetFileNameWithoutExtension(fullFileName)}> was moved to <{files[0]}> (unkown)!"); + throw new Exception($"Maybe file <{Path.GetFileNameWithoutExtension(fullFileName)}> was moved to <{files[0]}> (unknown)!"); else { json = json.Replace("MesaFab", "Mesa Fab"); @@ -51,7 +51,7 @@ internal abstract class FaceFileSystem string? directoryName; string fileNameWithoutExtension; Models.FaceFileSystem faceFileSystem; - string eDistanceCollectionfileFullName; + string eDistanceCollectionFileFullName; Models.Face[] face = Face.GetFaces(selectedFileFullName); string extension = Path.GetExtension(selectedFileFullName); for (int i = 0; i < face.Length; i++) @@ -68,12 +68,12 @@ internal abstract class FaceFileSystem continue; fileNameWithoutExtension = Path.GetFileNameWithoutExtension(face[i].RelativePath); jsonFileName = string.Concat(locationIndex.Value, " - ", fileNameWithoutExtension, extension); - eDistanceCollectionfileFullName = string.Concat(tuple.E_DistanceCollectionDirectory, Path.Combine(directoryName, fileNameWithoutExtension, jsonFileName)); - if (i == 0 && extension is ".json" && eDistanceCollectionfileFullName != selectedFileFullName) + eDistanceCollectionFileFullName = string.Concat(tuple.E_DistanceCollectionDirectory, Path.Combine(directoryName, fileNameWithoutExtension, jsonFileName)); + if (i == 0 && extension is ".json" && eDistanceCollectionFileFullName != selectedFileFullName) throw new Exception(); - fileInfo = new(eDistanceCollectionfileFullName); + fileInfo = new(eDistanceCollectionFileFullName); if (!fileInfo.Exists) - throw new Exception($"File <{eDistanceCollectionfileFullName}> doesn't exist!"); + throw new Exception($"File <{eDistanceCollectionFileFullName}> doesn't exist!"); faceFileSystem = new Models.FaceFileSystem(requestPath, tuple.RootResultsDirectoryAbsoluteUri.Length, tuple.C_ResizeContentDirectory, tuple.D_FacesContentDirectory, fileInfo.FullName, face[i]); results.Add(faceFileSystem); } diff --git a/Shared/Models/Stateless/Methods/FileSystem.cs b/Shared/Models/Stateless/Methods/FileSystem.cs index c5a2989..569163c 100644 --- a/Shared/Models/Stateless/Methods/FileSystem.cs +++ b/Shared/Models/Stateless/Methods/FileSystem.cs @@ -18,7 +18,7 @@ internal abstract class FileSystem if (!subDirectoryFiles.MoveNext()) { directoryInfo = new(directories[i]); - fileSystem = new Models.DirectoryFileSystem(directoryInfo); + fileSystem = new DirectoryFileSystem(directoryInfo); results.Add(fileSystem); } else diff --git a/Shared/Models/Stateless/Methods/IPerson.cs b/Shared/Models/Stateless/Methods/IPerson.cs index d837cce..b141747 100644 --- a/Shared/Models/Stateless/Methods/IPerson.cs +++ b/Shared/Models/Stateless/Methods/IPerson.cs @@ -8,16 +8,16 @@ public interface IPerson Dictionary TestStatic_Split(string knownPeopleFile); static Dictionary Split(string knownPeopleFile) => Person.Split(knownPeopleFile); - Models.Person[] TestStatic_GetPeople(Models.Properties.IStorage storage); - static Models.Person[] GetPeople(Models.Properties.IStorage storage) => Person.GetPeople(storage); + Models.Person[] TestStatic_GetPeople(Properties.IStorage storage); + static Models.Person[] GetPeople(Properties.IStorage storage) => Person.GetPeople(storage); - void TestStatic_SavePerson(Models.Properties.IStorage storage, Models.Person person); - static void SavePerson(Models.Properties.IStorage storage, Models.Person person) => Person.SavePerson(storage, person); + void TestStatic_SavePerson(Properties.IStorage storage, Models.Person person); + static void SavePerson(Properties.IStorage storage, Models.Person person) => Person.SavePerson(storage, person); - string TestStatic_GetFileFullName(Models.Properties.IStorage storage, Models.Person person); - static string GetFileFullName(Models.Properties.IStorage storage, Models.Person person) => PersonBirthday.GetFileFullName(storage, person.Birthday); + string TestStatic_GetFileFullName(Properties.IStorage storage, Models.Person person); + static string GetFileFullName(Properties.IStorage storage, Models.Person person) => PersonBirthday.GetFileFullName(storage, person.Birthday); - Models.Person TestStatic_CreatePerson(Models.Properties.IStorage storage, Models.PersonBirthday birthday, Models.PersonName name, List comments, List urls, List numbers, List emails, List addresses); - static Models.Person CreatePerson(Models.Properties.IStorage storage, Models.PersonBirthday birthday, Models.PersonName name, List comments, List urls, List numbers, List emails, List addresses) => Person.CreatePerson(storage, birthday, name, comments, urls, numbers, emails, addresses); + Models.Person TestStatic_CreatePerson(Properties.IStorage storage, Models.PersonBirthday birthday, Models.PersonName name, List comments, List urls, List numbers, List emails, List addresses); + static Models.Person CreatePerson(Properties.IStorage storage, Models.PersonBirthday birthday, Models.PersonName name, List comments, List urls, List numbers, List emails, List addresses) => Person.CreatePerson(storage, birthday, name, comments, urls, numbers, emails, addresses); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPersonBirthday.cs b/Shared/Models/Stateless/Methods/IPersonBirthday.cs index 0862cb3..202c227 100644 --- a/Shared/Models/Stateless/Methods/IPersonBirthday.cs +++ b/Shared/Models/Stateless/Methods/IPersonBirthday.cs @@ -12,19 +12,19 @@ public interface IPersonBirthday string TestStatic_GetFormat() => PersonBirthday.GetFormat(); static string GetFormat() => PersonBirthday.GetFormat(); - Models.PersonBirthday TestStatic_GetNextBirthdate(Models.Properties.IStorage storage) => PersonBirthday.GetNextBirthdate(storage); - static Models.PersonBirthday GetNextBirthdate(Models.Properties.IStorage storage) => PersonBirthday.GetNextBirthdate(storage); + Models.PersonBirthday TestStatic_GetNextBirthDate(Properties.IStorage storage) => PersonBirthday.GetNextBirthDate(storage); + static Models.PersonBirthday GetNextBirthDate(Properties.IStorage storage) => PersonBirthday.GetNextBirthDate(storage); - string TestStatic_GetFormated(Models.PersonBirthday personBirthday) => PersonBirthday.GetFormated(personBirthday); - static string GetFormated(Models.PersonBirthday personBirthday) => PersonBirthday.GetFormated(personBirthday); + string TestStatic_GetFormatted(Models.PersonBirthday personBirthday) => PersonBirthday.GetFormatted(personBirthday); + static string GetFormatted(Models.PersonBirthday personBirthday) => PersonBirthday.GetFormatted(personBirthday); string TestStatic_GetFileName(Models.PersonBirthday personBirthday) => PersonBirthday.GetFileName(personBirthday); static string GetFileName(Models.PersonBirthday personBirthday) => PersonBirthday.GetFileName(personBirthday); - bool TestStatic_DoesBirthDateExits(Models.Properties.IStorage storage, Models.PersonBirthday personBirthday) => DoesBirthDateExits(storage, personBirthday); - static bool DoesBirthDateExits(Models.Properties.IStorage storage, Models.PersonBirthday personBirthday) => DoesBirthDateExits(storage, personBirthday); + bool TestStatic_DoesBirthDateExits(Properties.IStorage storage, Models.PersonBirthday personBirthday) => DoesBirthDateExits(storage, personBirthday); + static bool DoesBirthDateExits(Properties.IStorage storage, Models.PersonBirthday personBirthday) => DoesBirthDateExits(storage, personBirthday); - string TestStatic_GetFileFullName(Models.Properties.IStorage storage, Models.PersonBirthday personBirthday) => PersonBirthday.GetFileFullName(storage, personBirthday); - static string GetFileFullName(Models.Properties.IStorage storage, Models.PersonBirthday personBirthday) => PersonBirthday.GetFileFullName(storage, personBirthday); + string TestStatic_GetFileFullName(Properties.IStorage storage, Models.PersonBirthday personBirthday) => PersonBirthday.GetFileFullName(storage, personBirthday); + static string GetFileFullName(Properties.IStorage storage, Models.PersonBirthday personBirthday) => PersonBirthday.GetFileFullName(storage, personBirthday); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPersonName.cs b/Shared/Models/Stateless/Methods/IPersonName.cs index a238d1b..19dea92 100644 --- a/Shared/Models/Stateless/Methods/IPersonName.cs +++ b/Shared/Models/Stateless/Methods/IPersonName.cs @@ -5,4 +5,7 @@ public interface IPersonName // ... + string TestStatic_GetFullName(Models.PersonName personName); + static string GetFullName(Models.PersonName personName) => PersonName.GetFullName(personName); + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IStorage.cs b/Shared/Models/Stateless/Methods/IStorage.cs index 0f38465..340b432 100644 --- a/Shared/Models/Stateless/Methods/IStorage.cs +++ b/Shared/Models/Stateless/Methods/IStorage.cs @@ -8,7 +8,7 @@ public interface IStorage bool TestStatic_WriteAllText(string path, string contents, bool compareBeforeWrite); static bool WriteAllText(string path, string contents, bool compareBeforeWrite) => Storage.WriteAllText(path, contents, compareBeforeWrite); - (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) TestStatic_GetTuple(Models.Properties.IStorage storage); - static (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) GetTuple(Models.Properties.IStorage storage) => new(new Uri(storage.RootResultsDirectory).AbsoluteUri, Path.Combine(storage.ResizeRootDirectory, "()"), Path.Combine(storage.FaceRootDirectory, "()"), Path.Combine(storage.DistanceResultRootDirectory, "[]")); + (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) TestStatic_GetTuple(Properties.IStorage storage); + static (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) GetTuple(Properties.IStorage storage) => new(new Uri(storage.RootResultsDirectory).AbsoluteUri, Path.Combine(storage.ResizeRootDirectory, "()"), Path.Combine(storage.FaceRootDirectory, "()"), Path.Combine(storage.DistanceResultRootDirectory, "[]")); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/Person.cs b/Shared/Models/Stateless/Methods/Person.cs index 520be2b..c9a0d88 100644 --- a/Shared/Models/Stateless/Methods/Person.cs +++ b/Shared/Models/Stateless/Methods/Person.cs @@ -7,7 +7,7 @@ internal abstract class Person // ... - private static List ValidatePerson(Models.Properties.IStorage storage, Models.PersonId id, Models.PersonBirthday birthday, Models.PersonName name) + private static List ValidatePerson(Properties.IStorage storage, Models.PersonId id, Models.PersonBirthday birthday, Models.PersonName name) { List results = new(); if (birthday is null) @@ -21,16 +21,16 @@ internal abstract class Person if (name.First is null || string.IsNullOrEmpty(name.First.Value)) results.Add("Fist Name must be supplied!"); if (PersonBirthday.DoesBirthDateExits(storage, birthday)) - results.Add("Birthdate already exits!"); + results.Add("BirthDate already exits!"); return results; } - internal static Models.Person CreatePerson(Models.Properties.IStorage storage, Models.PersonBirthday birthday, Models.PersonName name, List comments, List urls, List numbers, List emails, List addresses) + internal static Models.Person CreatePerson(Properties.IStorage storage, Models.PersonBirthday birthday, Models.PersonName name, List comments, List urls, List numbers, List emails, List addresses) { Models.Person result; Models.PersonId id = new(birthday.Value.Ticks); if (birthday.Value == DateTime.MinValue) - birthday = PersonBirthday.GetNextBirthdate(storage); + birthday = PersonBirthday.GetNextBirthDate(storage); List results = ValidatePerson(storage, id, birthday, name); if (results.Any()) throw new Exception(string.Join(Environment.NewLine, results)); @@ -126,14 +126,14 @@ internal abstract class Person return results; } - internal static void SavePerson(Models.Properties.IStorage storage, Models.Person person) + internal static void SavePerson(Properties.IStorage storage, Models.Person person) { string fileName = IPerson.GetFileFullName(storage, person); string json = JsonSerializer.Serialize(person, new JsonSerializerOptions { WriteIndented = true }); _ = IStorage.WriteAllText(fileName, json, compareBeforeWrite: true); } - private static List GetPeopleFromText(Models.Properties.IStorage storage, string localKnownPeopleFile) + private static List GetPeopleFromText(Properties.IStorage storage, string localKnownPeopleFile) { List results = new(); string comment; @@ -175,7 +175,7 @@ internal abstract class Person return results; } - internal static Models.Person[] GetPeople(Models.Properties.IStorage storage) + internal static Models.Person[] GetPeople(Properties.IStorage storage) { List results = new(); string json; @@ -187,11 +187,14 @@ internal abstract class Person string directory = Path.Combine(storage.PeopleRootDirectory, "{}"); if (!Directory.Exists(directory)) _ = Directory.CreateDirectory(directory); - if (!Directory.Exists(storage.RootDirectory)) + string? rootDirectoryParent = Path.GetDirectoryName(storage.RootDirectory); + if (string.IsNullOrEmpty(rootDirectoryParent)) + throw new Exception($"{nameof(rootDirectoryParent)} is null!"); + if (!Directory.Exists(rootDirectoryParent)) localKnownPeopleFile = string.Empty; else { - files = Directory.GetFiles(storage.RootDirectory, "*People*.txt", SearchOption.TopDirectoryOnly); + files = Directory.GetFiles(rootDirectoryParent, "*People*.txt", SearchOption.TopDirectoryOnly); if (files.Any()) localKnownPeopleFile = files[0]; else diff --git a/Shared/Models/Stateless/Methods/PersonBirthday.cs b/Shared/Models/Stateless/Methods/PersonBirthday.cs index 3cd1506..b5b4983 100644 --- a/Shared/Models/Stateless/Methods/PersonBirthday.cs +++ b/Shared/Models/Stateless/Methods/PersonBirthday.cs @@ -8,9 +8,10 @@ internal abstract class PersonBirthday // ... internal static string GetFormat() => "yyyy-MM-dd_HH"; - internal static Models.PersonBirthday GetNextBirthdate(Models.Properties.IStorage storage) => throw new Exception(storage.ToString()); // Person.GetNextBirthdate(storage); - internal static string GetFormated(Models.PersonBirthday personBirthday) => personBirthday.Value.ToString(GetFormat()); + internal static Models.PersonBirthday GetNextBirthDate(Properties.IStorage storage) => throw new Exception(storage.ToString()); // Person.GetNextBirthDate(storage); + 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(Models.Properties.IStorage storage, Models.PersonBirthday personBirthday) => File.Exists(GetFileFullName(storage, personBirthday)); - internal static string GetFileFullName(Models.Properties.IStorage storage, Models.PersonBirthday personBirthday) => Path.Combine(storage.PeopleRootDirectory, "{}", GetFileName(personBirthday)); + internal static bool DoesBirthDateExits(Properties.IStorage storage, Models.PersonBirthday personBirthday) => File.Exists(GetFileFullName(storage, personBirthday)); + internal static string GetFileFullName(Properties.IStorage storage, Models.PersonBirthday personBirthday) => Path.Combine(storage.PeopleRootDirectory, "{}", GetFileName(personBirthday)); + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/PersonName.cs b/Shared/Models/Stateless/Methods/PersonName.cs index 02726af..a21bdeb 100644 --- a/Shared/Models/Stateless/Methods/PersonName.cs +++ b/Shared/Models/Stateless/Methods/PersonName.cs @@ -1,3 +1,5 @@ +using System.Text; + namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class PersonName @@ -57,4 +59,16 @@ internal abstract class PersonName return result; } + internal static string GetFullName(Models.PersonName personName) + { + StringBuilder result = new(); + if (personName.First is not null) + _ = result.Append(personName.First.Value); + if (personName.Middle is not null) + _ = result.Append(' ').Append(personName.Middle.Value); + if (personName.Last is not null) + _ = result.Append(' ').Append(personName.Last.Value); + return result.ToString(); + } + } \ No newline at end of file diff --git a/package.json b/package.json index 24d3946..3d9762e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "scripts": { "Alpha": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "build": "dotnet build --runtime win-x64 --self-contained", - "dotnet-format": "dotnet format --report .vscode --verbosity detailed --severity warn View-by-Distance.sln", + "dotnet-format": "dotnet format --report .vscode --verbosity detailed --severity warn", "pull": "git pull", "garbage-collect": "git gc", "A-Instance-Pictures": "set ASPNETCORE_ENVIRONMENT=Development&& dotnet run --project \"Instance\\Instance.csproj\" --runtime win-x64 --no-self-contained \"C:\\Tmp\\phares\\Pictures\" s", @@ -13,5 +13,13 @@ "Z-Compare-Publish-": "dotnet publish \"Compare\\Compare.csproj\" --configuration Release --runtime win-x64 --verbosity normal --self-contained true -o \"D:\\net6.0\\View-by-Distance\\Compare\\\"", "Z-Instance-Publish-": "dotnet publish \"Instance\\Instance.csproj\" --configuration Release --runtime win-x64 --verbosity normal --self-contained true -o \"D:\\net6.0\\View-by-Distance\\Instance\\\"", "Z-Instance-CUDA-Publish-": "dotnet publish \"Instance\\Instance.csproj\" --configuration Release --runtime win-x64 --verbosity normal --self-contained true -o \"D:\\net6.0\\View-by-Distance\\Instance-CUDA\\\"" + }, + "Notes": { + "a": "Keep creating the .json file the same way", + "b": "However load all .json files at the beginning", + "c": "When looping through all files and file not in collection path&name or date is different from collection value", + "d": "Get id in normal fashion", + "e": "If id is in collection update collection to new path/name", + "f": "If not save and add to collection" } } \ No newline at end of file