diff --git a/.vscode/launch.json b/.vscode/launch.json index 39acf54..cb44042 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -2,36 +2,145 @@ "version": "0.2.0", "configurations": [ { - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "name": ".NET Core Launch (console)", + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + }, + { + "name": "Compare", "type": "coreclr", "request": "launch", "preLaunchTask": "build", - // If you have changed target frameworks, make sure to update the program path. - "programC": "${workspaceFolder}/Compare/bin/Debug/net7.0/win-x64/Compare.dll", - "programD": "${workspaceFolder}/Date-Group/bin/Debug/net7.0/win-x64/Date-Group.dll", - "programDD": "${workspaceFolder}/Drag-Drop/bin/Debug/net7.0-windows/win-x64/Drag-Drop.dll", - "program": "${workspaceFolder}/Instance/bin/Debug/net7.0/win-x64/Instance.dll", - "programN": "${workspaceFolder}/Not-Copy-Copy/bin/Debug/net7.0/win-x64/Not-Copy-Copy.dll", - "programP": "${workspaceFolder}/PrepareForOld/bin/Debug/net7.0/win-x64/PrepareForOld.dll", + "program": "${workspaceFolder}/Compare/bin/Debug/net7.0/win-x64/Compare.dll", "args": [ "s" ], "env": { - "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console "console": "externalTerminal", "stopAtEntry": false, "requireExactSource": false }, { - "name": ".NET Core Attach", + "name": "Duplicate-Search", "type": "coreclr", - "request": "attach" + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/Duplicate-Search/bin/Debug/net7.0/win-x64/Duplicate-Search.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "cwd": "${workspaceFolder}", + "console": "externalTerminal", + "stopAtEntry": false, + "requireExactSource": false + }, + { + "name": "Date-Group", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/Date-Group/bin/Debug/net7.0/win-x64/Date-Group.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "cwd": "${workspaceFolder}", + "console": "externalTerminal", + "stopAtEntry": false, + "requireExactSource": false + }, + { + "name": "Delete-By-Relative", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/Delete-By-Relative/bin/Debug/net7.0/win-x64/Delete-By-Relative.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "cwd": "${workspaceFolder}", + "console": "externalTerminal", + "stopAtEntry": false, + "requireExactSource": false + }, + { + "name": "Drag-Drop", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/Drag-Drop/bin/Debug/net7.0-windows/win-x64/Drag-Drop.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "cwd": "${workspaceFolder}", + "console": "externalTerminal", + "stopAtEntry": false, + "requireExactSource": false + }, + { + "name": "Instance", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/Instance/bin/Debug/net7.0/win-x64/Instance.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "cwd": "${workspaceFolder}", + "console": "externalTerminal", + "stopAtEntry": false, + "requireExactSource": false + }, + { + "name": "Not-Copy-Copy", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/Not-Copy-Copy/bin/Debug/net7.0/win-x64/Not-Copy-Copy.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "cwd": "${workspaceFolder}", + "console": "externalTerminal", + "stopAtEntry": false, + "requireExactSource": false + }, + { + "name": "PrepareForOld", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/PrepareForOld/bin/Debug/net7.0/win-x64/PrepareForOld.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "cwd": "${workspaceFolder}", + "console": "externalTerminal", + "stopAtEntry": false, + "requireExactSource": false } ] } @@ -147,41 +256,46 @@ // https://scontent-lax3-1.xx.fbcdn.net/v/t1.18169-9/25110_107749419250772_1842086_n.jpg?_nc_cat=104&ccb=1-7&_nc_sid=09cbfe&_nc_ohc=xPyRCvImlaoAX9Z_UTs&_nc_ht=scontent-lax3-1.xx&oh=00_AT85xffhHDJlhzyFTBvWs8j3Gd4GyDCte_Pnd7hNM006sw&oe=635880C2 // https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/10259940_10153561109653458_6837681277740526675_n.jpg?_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=T1v9Wfqz8rUAX8y6bxq&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT9Y9j5s19n0EzgO_dZMom8tAweFYIrJLOEsrsr4HAWHkQ&oe=63588CAE // https://scontent-lax3-1.xx.fbcdn.net/v/t31.18172-8/17621858_10154253751886426_3939148233753829194_o.jpg?_nc_cat=104&ccb=1-7&_nc_sid=ad2b24&_nc_ohc=yMOqJQQBV80AX8Xlzr-&_nc_ht=scontent-lax3-1.xx&oh=00_AT_z0oeHJ0fqKhVA4WdgGE2cZSgL0bIKNXzPsY0zeLipAg&oe=6356AF4C -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// FileSizeChanged -// LastWriteTimeChanged -// LastWriteTimeChanged -// LastWriteTimeChanged -// LastWriteTimeChanged -// LastWriteTimeChanged -// LastWriteTimeChanged -// LastWriteTimeChanged -// LastWriteTimeChanged -// LastWriteTimeChanged -// LastWriteTimeChanged -// LastWriteTimeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// FileSizeChanged +// LastWriteTimeChanged +// LastWriteTimeChanged +// LastWriteTimeChanged +// LastWriteTimeChanged +// LastWriteTimeChanged +// LastWriteTimeChanged +// LastWriteTimeChanged +// LastWriteTimeChanged +// LastWriteTimeChanged +// LastWriteTimeChanged +// LastWriteTimeChanged // - Device Videos 2_0_0_3 - Current - Kristy Google // - Device Videos 2_0_0_3 - Current - Mike Google // - Device Videos 2_0_0_3 - Current - Tracy -// Chester & Linores ?Pearson? \ No newline at end of file +// Chester & Linores ?Pearson? +// Distance face files date time? +// If not Hog and Original image size resize face +// New json file with known locations at original image size +// Add person to metadata when saving to SaveResizedImagesByPersonKeyFormattedForOutputResolutions maybe SaveMappedForOutputResolutions +// GetFaceLocations \ No newline at end of file diff --git a/Compare/Compare.csproj b/Compare/Compare.csproj index 39f6d9d..657c642 100644 --- a/Compare/Compare.csproj +++ b/Compare/Compare.csproj @@ -35,8 +35,8 @@ - - + + @@ -45,7 +45,7 @@ - + diff --git a/Compare/appsettings.Development.json b/Compare/appsettings.Development.json index e71121a..51d7a90 100644 --- a/Compare/appsettings.Development.json +++ b/Compare/appsettings.Development.json @@ -87,14 +87,14 @@ "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", "PopulatePropertyId": true, "PropertiesChangedForProperty": false, - "RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8 - III", + "RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8", "WriteBitmapDataBytes": false, "IgnoreExtensions": [ ".gif", ".GIF" ], "PropertyContentCollectionFiles": [ - "/Images 2022-11-12 - c6aa7e8 - III - Results/A) Property/2022-11-12/[()]/637869381676042455.json", + "/Images 2022-11-12 - c6aa7e8 - Results/A) Property/2022-11-12/[()]/637869381676042455.json", "/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-11-12/[()]/637869733124119330.json", "/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-11-12/[()]/637869734240700328.json", "/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-11-12/[()]/637869734970730630.json", diff --git a/Compare/appsettings.json b/Compare/appsettings.json index 43832f5..adc03e7 100644 --- a/Compare/appsettings.json +++ b/Compare/appsettings.json @@ -94,7 +94,7 @@ ".GIF" ], "PropertyContentCollectionFiles": [ - "/Images 2022-11-12 - c6aa7e8 - III - Results/A) Property/2022-11-12/[()]/637869381676042455.json", + "/Images 2022-11-12 - c6aa7e8 - Results/A) Property/2022-11-12/[()]/637869381676042455.json", "/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-11-12/[()]/637869733124119330.json", "/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-11-12/[()]/637869734240700328.json", "/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-11-12/[()]/637869734970730630.json", diff --git a/Date-Group/Date-Group.csproj b/Date-Group/Date-Group.csproj index 15f10ef..ba41a2a 100644 --- a/Date-Group/Date-Group.csproj +++ b/Date-Group/Date-Group.csproj @@ -34,9 +34,9 @@ - + - + @@ -46,13 +46,16 @@ - + + + Always + Always diff --git a/Date-Group/DateGroup.cs b/Date-Group/DateGroup.cs index be7ef19..17aef6b 100644 --- a/Date-Group/DateGroup.cs +++ b/Date-Group/DateGroup.cs @@ -36,8 +36,9 @@ public class DateGroup _FileKeyValuePairs = new List>(); _FilePropertiesKeyValuePairs = new Dictionary>>(); Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); - Property.Models.Configuration.Verify(propertyConfiguration, requireExist: true); Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); + _Log.Information(propertyConfiguration.RootDirectory); + Property.Models.Configuration.Verify(propertyConfiguration, requireExist: true); Verify(configuration); bool reverse = false; _Configuration = configuration; @@ -141,8 +142,6 @@ public class DateGroup check += 1; if (configuration.ByHash) check += 1; - if (configuration.ByNone) - check += 1; if (configuration.BySeason) check += 1; if (configuration.ByWeek) @@ -256,18 +255,15 @@ public class DateGroup if (matches is not null && matches.Any()) break; } - matches ??= Array.Empty(); foreach (Item item in filteredItems) { - if (item.Property is null || (_Configuration.PropertyConfiguration.PopulatePropertyId && item.Property.Id is null)) - continue; directoryNames.Clear(); destinationCollection = new(); _ = destinationDirectoryName.Clear(); minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property); day = minimumDateTime.Value.ToString("MM-dd"); month = minimumDateTime.Value.ToString("MMMM"); - if (item.Property.Id is null) + if (item.Property?.Id is null) { flag = '#'; isWrongYear = null; @@ -294,6 +290,8 @@ public class DateGroup seasonValue = $".{season}"; if (isWrongYear is null || !isWrongYear.Value) year = $"{flag}{minimumDateTime.Value:yyyy}{seasonValue}"; + else if (matches is null || matches.Length < 3) + year = "----"; else { if (matches[0][0] != '~') @@ -303,9 +301,7 @@ public class DateGroup } topDirectoryName = Path.GetFileName(topDirectory); weekOfYear = calendar.GetWeekOfYear(minimumDateTime.Value, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00"); - if (_Configuration.ByNone) - directoryNames.Clear(); - else if (_Configuration.ByHash) + if (_Configuration.ByHash) directoryNames.Add($"{year} {seasonName}"); else if (_Configuration.BySeason && topDirectoryName.Length == 1 && topDirectoryName[0] == '_') directoryNames.Add($"{year} {seasonName}"); @@ -328,7 +324,7 @@ public class DateGroup { foreach (string sourceDirectoryNameSegment in topDirectorySegments) { - if (matches.Contains(sourceDirectoryNameSegment)) + if (matches is not null && matches.Contains(sourceDirectoryNameSegment)) _ = destinationDirectoryName.Append(year); else _ = destinationDirectoryName.Append(sourceDirectoryNameSegment); @@ -343,14 +339,19 @@ public class DateGroup throw new Exception(); } } - if (!_Configuration.ByHash || item.Property.Id is null) + if (!_Configuration.ByHash || item.Property?.Id is null) fileName = item.ImageFileHolder.Name; else fileName = $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}"; destinationCollection.Add(destinationDirectory); destinationCollection.AddRange(directoryNames); destinationCollection.Add(fileName); - results.Add(new(item, item.Property.LastWriteTime.Ticks, minimumDateTime.Value.Ticks, destinationCollection.ToArray())); + if (item.ImageFileHolder.LastWriteTime is null) + continue; + if (item.Property is not null) + results.Add(new(item, item.Property.LastWriteTime.Ticks, minimumDateTime.Value.Ticks, destinationCollection.ToArray())); + else + results.Add(new(item, item.ImageFileHolder.LastWriteTime.Value.Ticks, minimumDateTime.Value.Ticks, destinationCollection.ToArray())); } return results; } @@ -419,11 +420,12 @@ public class DateGroup { if (_Log is null) throw new NullReferenceException(nameof(_Log)); + string checkDirectory; bool hasDuplicate; string fullFileName; string directoryName; WindowsShortcut windowsShortcut; - string duplicate = "-Duplicate"; + string duplicate = "-Duplicates"; List filesDistinct = new(); List filesDuplicate = new(); List directoriesDistinct = new(); @@ -440,12 +442,17 @@ public class DateGroup directoriesDistinct.Add(directoryName); if (!Directory.Exists(directoryName)) _ = Directory.CreateDirectory(directoryName); - if (!Directory.Exists(string.Concat(directoryName, duplicate, " I"))) - _ = Directory.CreateDirectory(string.Concat(directoryName, duplicate, " I")); - if (!Directory.Exists(string.Concat(directoryName, duplicate, " II"))) - _ = Directory.CreateDirectory(string.Concat(directoryName, duplicate, " II")); + checkDirectory = Path.Combine(string.Concat(directoryName, duplicate), "I"); + if (!Directory.Exists(checkDirectory)) + _ = Directory.CreateDirectory(checkDirectory); + for (int i = 0; i < 200 - checkDirectory.Length; i++) + { + checkDirectory = string.Concat(checkDirectory, "I"); + if (!Directory.Exists(checkDirectory)) + _ = Directory.CreateDirectory(checkDirectory); + } } - _Log.Information("Ready to move files?"); + _Log.Information($"Ready to move {fileMoveCollectionAll.Length} file(s)?"); for (int y = 0; y < int.MaxValue; y++) { _Log.Information("Press \"Y\" key to move file(s) or close console to not move files"); @@ -460,16 +467,16 @@ public class DateGroup hasDuplicate = filesDuplicate.Contains(fullFileName); if (hasDuplicate) { - destination[1] = string.Concat(destination[1], duplicate, " I"); + destination[0] = Path.Combine(string.Concat(destination[0], duplicate), "I"); fullFileName = Path.Combine(destination); } - for (int i = 0; i < 256 - destination[1].Length; i++) + for (int i = 0; i < 200 - destination[0].Length; i++) { if (!File.Exists(fullFileName)) break; else { - destination[1] = string.Concat(destination[1], "I"); + destination[0] = string.Concat(destination[0], "I"); fullFileName = Path.Combine(destination); if (File.Exists(fullFileName)) continue; diff --git a/Date-Group/Models/Binder/Configuration.cs b/Date-Group/Models/Binder/Configuration.cs index 2bf92f8..13d701f 100644 --- a/Date-Group/Models/Binder/Configuration.cs +++ b/Date-Group/Models/Binder/Configuration.cs @@ -13,7 +13,6 @@ 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 None"), Required] public bool? ByNone { get; set; } [Display(Name = "By Season"), Required] public bool? BySeason { get; set; } [Display(Name = "By Week"), Required] public bool? ByWeek { get; set; } [Display(Name = "Ignore Subdirectories for Rename"), Required] public bool? KeepFullPath { get; set; } @@ -38,15 +37,20 @@ public class Configuration throw new NullReferenceException(nameof(configuration.ByDay)); if (configuration.ByHash is null) throw new NullReferenceException(nameof(configuration.ByHash)); - if (configuration.ByNone is null) - throw new NullReferenceException(nameof(configuration.ByNone)); if (configuration.BySeason is null) throw new NullReferenceException(nameof(configuration.BySeason)); if (configuration.ByWeek is null) throw new NullReferenceException(nameof(configuration.ByWeek)); if (configuration.KeepFullPath is null) throw new NullReferenceException(nameof(configuration.KeepFullPath)); - result = new(configuration.PropertyConfiguration, configuration.ByCreateDateShortcut.Value, configuration.ByDay.Value, configuration.ByHash.Value, configuration.ByNone.Value, configuration.BySeason.Value, configuration.ByWeek.Value, configuration.KeepFullPath.Value); + result = new( + configuration.PropertyConfiguration, + configuration.ByCreateDateShortcut.Value, + configuration.ByDay.Value, + configuration.ByHash.Value, + configuration.BySeason.Value, + configuration.ByWeek.Value, + configuration.KeepFullPath.Value); return result; } @@ -66,7 +70,7 @@ public class Configuration result = Get(configuration); if (configuration is null) throw new NullReferenceException(nameof(configuration)); - result.SetAndUpdate(propertyConfiguration, numberOfJitters: null, numberOfTimesToUpsample: null, modelName: null, predictorModelName: null); + result.SetAndUpdate(propertyConfiguration); return result; } diff --git a/Date-Group/Models/Configuration.cs b/Date-Group/Models/Configuration.cs index 994da49..f51ed57 100644 --- a/Date-Group/Models/Configuration.cs +++ b/Date-Group/Models/Configuration.cs @@ -12,17 +12,15 @@ public class Configuration public bool ByCreateDateShortcut { init; get; } public bool ByDay { init; get; } public bool ByHash { init; get; } - public bool ByNone { init; get; } public bool BySeason { init; get; } public bool ByWeek { init; get; } public bool KeepFullPath { init; get; } [JsonConstructor] - public Configuration(Property.Models.Configuration propertyConfiguration, bool byCreateDateShortcut, bool byDay, bool byHash, bool byNone, bool bySeason, bool byWeek, bool keepFullPath) + public Configuration(Property.Models.Configuration propertyConfiguration, bool byCreateDateShortcut, bool byDay, bool byHash, bool bySeason, bool byWeek, bool keepFullPath) { ByDay = byDay; ByHash = byHash; - ByNone = byNone; ByWeek = byWeek; BySeason = bySeason; KeepFullPath = keepFullPath; @@ -36,10 +34,10 @@ public class Configuration return result; } - public void SetAndUpdate(Property.Models.Configuration configuration, int? numberOfJitters, int? numberOfTimesToUpsample, string? modelName, string? predictorModelName) + public void SetAndUpdate(Property.Models.Configuration configuration) { _PropertyConfiguration = configuration; - _PropertyConfiguration.Update(numberOfJitters, numberOfTimesToUpsample, modelName, predictorModelName); + _PropertyConfiguration.Update(); } } \ No newline at end of file diff --git a/Date-Group/Program.cs b/Date-Group/Program.cs index f4f5a8d..0778a31 100644 --- a/Date-Group/Program.cs +++ b/Date-Group/Program.cs @@ -19,6 +19,7 @@ public class Program IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); IConfigurationRoot configurationRoot = configurationBuilder.Build(); AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); diff --git a/Date-Group/appsettings.Development.json b/Date-Group/appsettings.Development.json index 71babed..961e5f1 100644 --- a/Date-Group/appsettings.Development.json +++ b/Date-Group/appsettings.Development.json @@ -53,8 +53,7 @@ "ByCreateDateShortcut": false, "ByDay": false, "ByHash": false, - "ByNone": false, - "BySeason": true, + "BySeason": false, "ByWeek": false, "DateGroup": "2022-11-12", "FileNameDirectorySeparator": ".Z.", @@ -69,10 +68,10 @@ "ResultContent": "()", "ResultSingleton": "{}", "xRootDirectory": "C:/Tmp/phares/Pictures", - "xxRootDirectory": "C:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8 - III", - "xxxRootDirectory": "F:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8 - III", + "xxRootDirectory": "C:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8", + "xxxRootDirectory": "F:/Tmp/Phares/Compare/Not-Copy-Copy-All", + "RootDirectory": "C:/Tmp/Phares/Compare/Not-Copy-Copy-All", "xxxxRootDirectory": "F:/Tmp/Phares/2022-11-03-DCIM/DCIM/100D3400 2022", - "RootDirectory": "F:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8 - III/D", "WriteBitmapDataBytes": false, "IgnoreExtensions": [ ".gif", diff --git a/Date-Group/appsettings.json b/Date-Group/appsettings.json new file mode 100644 index 0000000..c91ce58 --- /dev/null +++ b/Date-Group/appsettings.json @@ -0,0 +1,348 @@ +{ + "Company": "Mike Phares", + "Linux": {}, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Log4netProvider": "Debug", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "MaxDegreeOfParallelism": 6, + "Serilog": { + "Using": [ + "Serilog.Sinks.Console", + "Serilog.Sinks.File" + ], + "MinimumLevel": "Debug", + "WriteTo": [ + { + "Name": "Debug", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "Console", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "%workingDirectory% - Log/log-.txt", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}", + "rollingInterval": "Hour" + } + } + ], + "Enrich": [ + "FromLogContext", + "WithMachineName", + "WithThreadId" + ], + "Properties": { + "Application": "Sample" + } + }, + "WorkingDirectoryName": "PharesApps", + "Windows": { + "Configuration": { + "ByCreateDateShortcut": false, + "ByDay": false, + "ByHash": false, + "BySeason": false, + "ByWeek": false, + "DateGroup": "2022-11-12", + "FileNameDirectorySeparator": ".Z.", + "ForcePropertyLastWriteTimeToCreationTime": false, + "KeepFullPath": false, + "MaxImagesInDirectoryForTopLevelFirstPass": 10, + "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", + "PopulatePropertyId": false, + "PropertiesChangedForProperty": false, + "ResultAllInOne": "_ _ _", + "ResultCollection": "[]", + "ResultContent": "()", + "ResultSingleton": "{}", + "xRootDirectory": "C:/Tmp/phares/Pictures", + "xxRootDirectory": "C:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8", + "RootDirectory": "F:/Tmp/Phares/Compare/Not-Copy-Copy-All", + "xxxxRootDirectory": "F:/Tmp/Phares/2022-11-03-DCIM/DCIM/100D3400 2022", + "WriteBitmapDataBytes": false, + "IgnoreExtensions": [ + ".gif", + ".GIF" + ], + "PropertyContentCollectionFiles": [], + "ValidImageFormatExtensions": [ + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".png", + ".PNG", + ".tiff", + ".TIFF" + ], + "ValidMetadataExtensions": [ + ".3gp", + ".3GP", + ".avi", + ".AVI", + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".ico", + ".ICO", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".m4v", + ".M4V", + ".mov", + ".MOV", + ".mp4", + ".MP4", + ".mta", + ".MTA", + ".png", + ".PNG", + ".tiff", + ".TIFF" + ], + "VerifyToSeason": [ + ". 2000", + ". 2001", + ". 2002", + ". 2003", + ". 2004", + ". 2005", + ". 2006", + ". 2007", + ". 2008", + ". 2009", + ". 2010", + ". 2011", + ". 2012", + ". 2013", + ". 2014", + ". 2015", + ". 2016", + ". 2017", + ". 2018", + ". 2019", + ". 2020", + ". 2021", + ". 2022", + ". 2023", + ". 2024", + ". 2025", + ". 2026", + ". 2027", + ". 2028", + ". 2029", + "=2000.0 Winter", + "=2002.1 Spring", + "=2002.4 Winter", + "=2003.0 Winter", + "=2003.1 Spring", + "=2003.3 Fall", + "=2003.4 Winter", + "=2004.0 Winter", + "=2005.1 Spring", + "=2005.2 Summer", + "=2005.3 Fall", + "=2005.4 Winter", + "=2006.0 Winter", + "=2006.1 Spring", + "=2006.3 Fall", + "=2007.0 Winter", + "=2007.2 Summer Logan Michael", + "=2007.2 Summer", + "=2007.3 Fall Logan Michael", + "=2007.4 Winter Logan Michael", + "=2008.0 Winter Logan Michael", + "=2008.1 Spring Logan Michael", + "=2008.2 Summer Logan Michael", + "=2008.2 Summer", + "=2008.3 Fall Logan Michael", + "=2009.0 Winter Logan Michael", + "=2009.0 Winter", + "=2009.1 Spring Logan Michael", + "=2009.1 Spring", + "=2009.2 Summer Logan Michael", + "=2009.2 Summer", + "=2009.3 Fall Logan Michael", + "=2009.3 Fall", + "=2009.4 Winter Logan Michael", + "=2009.4 Winter", + "=2010.0 Winter Logan Michael", + "=2010.0 Winter", + "=2010.1 Spring Logan Michael", + "=2010.1 Spring", + "=2010.2 Summer", + "=2010.3 Fall Logan Michael", + "=2010.3 Fall", + "=2010.4 Winter", + "=2011.0 Winter", + "=2011.1 Spring", + "=2011.2 Summer", + "=2011.3 Fall", + "=2011.4 Winter", + "=2012.0 Winter Chelsea 2012", + "=2012.0 Winter Chelsea", + "=2012.0 Winter", + "=2012.1 Spring Chelsea", + "=2012.1 Spring", + "=2012.2 Summer Chelsea", + "=2012.2 Summer", + "=2012.3 Fall Chelsea", + "=2012.3 Fall", + "=2012.4 Winter Chelsea", + "=2012.4 Winter", + "=2013.0 Winter Chelsea 2013", + "=2013.0 Winter Chelsea", + "=2013.0 Winter", + "=2013.1 Spring", + "=2013.2 Summer Chelsea", + "=2013.2 Summer", + "=2013.3 Fall Chelsea", + "=2013.3 Fall", + "=2013.4 Winter", + "=2014.0 Winter", + "=2014.1 Spring", + "=2014.2 Summer", + "=2014.3 Fall", + "=2014.4 Winter", + "=2015.0 Winter", + "=2015.1 Spring", + "=2015.2 Summer", + "=2015.3 Fall", + "=2015.4 Winter", + "=2016.0 Winter", + "=2016.1 Spring", + "=2016.2 Summer", + "=2016.3 Fall", + "=2016.4 Winter", + "=2017.1 Spring", + "=2017.2 Summer", + "=2017.3 Fall", + "=2017.4 Winter", + "=2018.0 Winter", + "=2018.1 Spring", + "=2018.3 Fall", + "=2018.4 Winter", + "=2019.0 Winter", + "=2019.1 Spring", + "=2019.2 Summer", + "=2019.3 Fall", + "=2019.4 Winter", + "=2020.0 Winter", + "=2020.1 Spring", + "=2020.2 Summer", + "=2020.3 Fall", + "=2020.4 Winter", + "=2021.1 Spring", + "=2021.2 Summer", + "=2021.3 Fall", + "=2021.4 Winter", + "=2022.0 Winter", + "=2022.1 Spring", + "Anthem 2015", + "April 2010", + "April 2013", + "December 2006", + "December 2010", + "Fall 2005", + "Fall 2015", + "Fall 2016", + "Fall 2017", + "Fall 2018", + "Fall 2019", + "Fall 2020", + "Fall 2021", + "February 2010", + "January 2015", + "July 2010", + "June 2010", + "Kids 2005", + "March 2013", + "May 2010", + "May 2011", + "May 2013", + "October 2005", + "October 2014", + "Spring 2013", + "Spring 2014", + "Spring 2016", + "Spring 2018", + "Spring 2019", + "Spring 2020", + "Summer 2011", + "Summer 2012", + "Summer 2013", + "Summer 2014", + "Summer 2015", + "Summer 2016", + "Summer 2017", + "Summer 2018", + "Summer 2020", + "Summer 2021", + "Winter 2015", + "Winter 2016", + "Winter 2017", + "Winter 2018", + "Winter 2019-2020", + "Winter 2020", + "zzz =2005.0 Winter Tracy Pictures", + "zzz =2005.1 Spring Tracy Pictures", + "zzz =2005.2 Summer Tracy Pictures", + "zzz =2005.3 Fall Tracy Pictures", + "zzz =2005.4 Winter Tracy Pictures", + "zzz =2006.1 Spring Tracy Pictures", + "zzz =2007.0 Winter Tracy Pictures", + "zzz =2007.2 Summer Tracy Pictures", + "zzz =2008.0 Winter Tracy Pictures", + "zzz =2008.2 Summer Tracy Pictures", + "zzz =2009.0 Winter Tracy Pictures", + "zzz =2009.2 Summer Tracy Pictures", + "zzz =2009.3 Fall Tracy Pictures", + "zzz =2009.4 Winter Tracy Pictures", + "zzz =2010.0 Winter Tracy Pictures", + "zzz =2010.1 Spring Tracy Pictures", + "zzz =2010.2 Summer Tracy Pictures", + "zzz =2010.3 Fall Tracy Pictures", + "zzz =2011.0 Winter Tracy Pictures", + "zzz =2011.1 Spring Tracy Pictures", + "zzz =2011.2 Summer Tracy Pictures", + "zzz =2011.3 Fall Tracy Pictures", + "zzz =2011.4 Winter Tracy Pictures", + "zzz =2012.0 Winter Tracy Pictures", + "zzz =2012.1 Spring Tracy Pictures", + "zzz =2012.2 Summer Tracy Pictures", + "zzz =2012.3 Fall Tracy Pictures", + "zzz =2012.4 Winter Tracy Pictures", + "zzz =2013.0 Winter Tracy Pictures", + "zzz =2013.1 Spring Tracy Pictures", + "zzz =2013.2 Summer Tracy Pictures", + "zzz =2013.3 Fall Tracy Pictures", + "zzz =2013.4 Winter Tracy Pictures", + "zzz =2014.0 Winter Tracy Pictures", + "zzz =2014.1 Spring Tracy Pictures", + "zzz =2014.2 Summer Tracy Pictures", + "zzz =2014.3 Fall Tracy Pictures", + "zzz =2014.4 Winter Tracy Pictures", + "zzz =2015.0 Winter Tracy Pictures" + ] + } + } +} \ No newline at end of file diff --git a/Delete-By-Relative/.vscode/format-report.json b/Delete-By-Relative/.vscode/format-report.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/Delete-By-Relative/.vscode/format-report.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/Delete-By-Relative/.vscode/launch.json b/Delete-By-Relative/.vscode/launch.json new file mode 100644 index 0000000..f7b185a --- /dev/null +++ b/Delete-By-Relative/.vscode/launch.json @@ -0,0 +1,32 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/bin/Debug/net6.0/win-x64/Duplicate-Search.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development", + }, + "cwd": "${workspaceFolder}", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "externalTerminal", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processName": "Duplicate-Search" + } + ] +} \ No newline at end of file diff --git a/Delete-By-Relative/.vscode/settings.json b/Delete-By-Relative/.vscode/settings.json new file mode 100644 index 0000000..768342e --- /dev/null +++ b/Delete-By-Relative/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "cSpell.words": [ + "Barrick", + "bcdfghjklmnpqrstvwxyz", + "Beichler", + "Bohdi", + "Dlib", + "exif", + "nosj", + "Phares", + "Serilog", + "Vericruz" + ] +} \ No newline at end of file diff --git a/Delete-By-Relative/.vscode/tasks.json b/Delete-By-Relative/.vscode/tasks.json new file mode 100644 index 0000000..3c2eb55 --- /dev/null +++ b/Delete-By-Relative/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/Duplicate-Search.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/Duplicate-Search.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/Duplicate-Search.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/Delete-By-Relative/Delete-By-Relative.csproj b/Delete-By-Relative/Delete-By-Relative.csproj new file mode 100644 index 0000000..53272a2 --- /dev/null +++ b/Delete-By-Relative/Delete-By-Relative.csproj @@ -0,0 +1,62 @@ + + + enable + 10.0 + enable + Exe + win-x64 + net7.0 + + + Phares.View.by.Distance.Delete.By.Relative + false + 6.0.100.1 + Mike Phares + Phares + true + snupkg + + + true + true + true + + + Windows + + + OSX + + + Linux + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + Always + + + \ No newline at end of file diff --git a/Delete-By-Relative/DeleteByRelative.cs b/Delete-By-Relative/DeleteByRelative.cs new file mode 100644 index 0000000..2f64e09 --- /dev/null +++ b/Delete-By-Relative/DeleteByRelative.cs @@ -0,0 +1,82 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using View_by_Distance.Delete.By.Relative.Models; +using View_by_Distance.Property.Models; +using View_by_Distance.Shared.Models.Methods; + +namespace View_by_Distance.Delete.By.Relative; + +public class DeleteByRelative +{ + + public DeleteByRelative(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) + { + if (isSilent) + { } + if (console is null) + { } + string relativePath; + string checkFileName; + string searchPattern = "*"; + long ticks = DateTime.Now.Ticks; + ILogger? log = Log.ForContext(); + Configuration configuration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); + configuration.Update(); + log.Information(configuration.RootDirectory); + int length = configuration.RootDirectory.Length; + if (string.IsNullOrEmpty(appSettings.CompareRootDirectory) || Path.GetFullPath(appSettings.CompareRootDirectory) == Path.GetFullPath(configuration.RootDirectory)) + throw new Exception("Check AppSettings file!"); + IEnumerable<(string directory, string[] files)> leftCollection = Shared.Models.Stateless.Methods.IFileHolder.GetFiles(configuration.RootDirectory, searchPattern); + List leftRelativeFiles = new(); + foreach ((_, string[] files) in leftCollection) + { + foreach (string file in files) + { + relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(file, length); + leftRelativeFiles.Add(Path.GetFullPath(string.Concat(appSettings.CompareRootDirectory, relativePath))); + } + } + List deleteFiles = new(); + IEnumerable<(string, string[])> rightCollection = Shared.Models.Stateless.Methods.IFileHolder.GetFiles(appSettings.CompareRootDirectory, searchPattern); + foreach ((_, string[] files) in rightCollection) + { + foreach (string file in files) + { + checkFileName = Path.GetFullPath(file); + if (!leftRelativeFiles.Contains(checkFileName)) + continue; + deleteFiles.Add(checkFileName); + } + } + string? alongSideDirectory; + string directoryName = Path.GetFileName(appSettings.CompareRootDirectory); + if (Path.GetPathRoot(appSettings.CompareRootDirectory) == appSettings.CompareRootDirectory) + alongSideDirectory = appSettings.CompareRootDirectory; + else + alongSideDirectory = Path.GetDirectoryName(appSettings.CompareRootDirectory); + if (alongSideDirectory is null) + throw new NullReferenceException(nameof(alongSideDirectory)); + string deleteLog = Path.Combine(alongSideDirectory, $"{directoryName}-{ticks}.tsv"); + File.WriteAllLines(deleteLog, deleteFiles); + log.Information($"Ready to delete {deleteFiles.Count} file(s)? See <{deleteLog}>"); + for (int y = 0; y < int.MaxValue; y++) + { + log.Information("Press \"Y\" key to delete file(s) or close console to not delete files"); + if (Console.ReadKey().Key == ConsoleKey.Y) + break; + } + log.Information(". . ."); + foreach (string deleteFile in deleteFiles) + { + File.Delete(deleteFile); + checkFileName = $"{deleteFile}.id"; + if (!File.Exists(checkFileName)) + continue; + File.Delete(checkFileName); + } + for (int i = 1; i < 5; i++) + _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(appSettings.CompareRootDirectory); + } + +} \ No newline at end of file diff --git a/Delete-By-Relative/Models/AppSettings.cs b/Delete-By-Relative/Models/AppSettings.cs new file mode 100644 index 0000000..1c4eabc --- /dev/null +++ b/Delete-By-Relative/Models/AppSettings.cs @@ -0,0 +1,31 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace View_by_Distance.Delete.By.Relative.Models; + +public class AppSettings +{ + + public string Company { init; get; } + public string CompareRootDirectory { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string OutputExtension { init; get; } + public string WorkingDirectoryName { init; get; } + + [JsonConstructor] + public AppSettings(string company, string compareRootDirectory, int maxDegreeOfParallelism, string outputExtension, string workingDirectoryName) + { + Company = company; + CompareRootDirectory = compareRootDirectory; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + OutputExtension = outputExtension; + WorkingDirectoryName = workingDirectoryName; + } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + +} \ No newline at end of file diff --git a/Delete-By-Relative/Models/Binder/AppSettings.cs b/Delete-By-Relative/Models/Binder/AppSettings.cs new file mode 100644 index 0000000..b6c3b82 --- /dev/null +++ b/Delete-By-Relative/Models/Binder/AppSettings.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.Configuration; +using System.Text.Json; + +namespace View_by_Distance.Delete.By.Relative.Models.Binder; + +public class AppSettings +{ + +#nullable disable + + public string Company { get; set; } + public string CompareRootDirectory { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string OutputExtension { get; set; } + public string WorkingDirectoryName { get; set; } + +#nullable restore + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + + private static Models.AppSettings Get(AppSettings? appSettings) + { + Models.AppSettings result; + if (appSettings?.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + result = new( + appSettings.Company, + appSettings.CompareRootDirectory, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.OutputExtension, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings? appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + +} \ No newline at end of file diff --git a/Delete-By-Relative/Models/Stateless/SerilogExtensionMethods.cs b/Delete-By-Relative/Models/Stateless/SerilogExtensionMethods.cs new file mode 100644 index 0000000..7e4d443 --- /dev/null +++ b/Delete-By-Relative/Models/Stateless/SerilogExtensionMethods.cs @@ -0,0 +1,10 @@ +namespace View_by_Distance.Delete.By.Relative.Models.Stateless; + +public static class SerilogExtensionMethods +{ + + internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate); + + internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate); + +} \ No newline at end of file diff --git a/Delete-By-Relative/Program.cs b/Delete-By-Relative/Program.cs new file mode 100644 index 0000000..2a8ae46 --- /dev/null +++ b/Delete-By-Relative/Program.cs @@ -0,0 +1,70 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using System.Diagnostics; +using System.Reflection; +using View_by_Distance.Delete.By.Relative.Models; +using View_by_Distance.Shared.Models.Stateless.Methods; + +namespace View_by_Distance.Delete.By.Relative; + +public class Program +{ + + public static void Secondary(List args) + { + LoggerConfiguration loggerConfiguration = new(); + Assembly assembly = Assembly.GetExecutingAssembly(); + bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug"); + IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); + IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() + .AddEnvironmentVariables() + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); + IConfigurationRoot configurationRoot = configurationBuilder.Build(); + AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount) + throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!"); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); + string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); + Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); + _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); + Log.Logger = loggerConfiguration.CreateLogger(); + ILogger log = Log.ForContext(); + int silentIndex = args.IndexOf("s"); + if (silentIndex > -1) + args.RemoveAt(silentIndex); + try + { + if (args is null) + throw new Exception("args is null!"); + Shared.Models.Console console = new(); + _ = new DeleteByRelative(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console); + } + catch (Exception ex) + { + log.Fatal(string.Concat(ex.Message, Environment.NewLine, ex.StackTrace)); + } + finally + { + Log.CloseAndFlush(); + } + if (silentIndex > -1) + log.Debug("Done. Bye"); + else + { + log.Debug("Done. Press 'Enter' to end"); + _ = Console.ReadLine(); + } + } + + public static void Main(string[] args) + { + if (args is not null) + Secondary(args.ToList()); + else + Secondary(new List()); + } + +} \ No newline at end of file diff --git a/Delete-By-Relative/appsettings.Development.json b/Delete-By-Relative/appsettings.Development.json new file mode 100644 index 0000000..c3729dc --- /dev/null +++ b/Delete-By-Relative/appsettings.Development.json @@ -0,0 +1,245 @@ +{ + "xCompareRootDirectory": "D:/Tmp/Phares/Not-Copy-Copy-All", + "xxCompareRootDirectory": "E:/www/Images - Results/C) Resize/2021-11-03/2256 x 1496/()", + "xxxCompareRootDirectory": "C:/Tmp/Phares/Compare/.Delete-Not-Copy-Copy-All", + "CompareRootDirectory": "C:/Tmp/Phares/Compare/Not-Copy-Copy-Duplicates", + "Logging": { + "LogLevel": { + "Log4netProvider": "Debug" + } + }, + "MaxDegreeOfParallelism": 6, + "Serilog": { + "MinimumLevel": "Debug" + }, + "Windows": { + "Configuration": { + "RootDirectory": "F:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8 - Results/A) Property/2022-11-12/{}", + "xRootDirectory": "F:/Tmp/Phares/Compare/Not-Copy-Copy-All - Results/A) Property/2022-11-12/{}", + "VerifyToSeason": [ + ". 2000", + ". 2001", + ". 2002", + ". 2003", + ". 2004", + ". 2005", + ". 2006", + ". 2007", + ". 2008", + ". 2009", + ". 2010", + ". 2011", + ". 2012", + ". 2013", + ". 2014", + ". 2015", + ". 2016", + ". 2017", + ". 2018", + ". 2019", + ". 2020", + ". 2021", + ". 2022", + ". 2023", + ". 2024", + ". 2025", + ". 2026", + ". 2027", + ". 2028", + ". 2029", + "=2000.0 Winter", + "=2002.1 Spring", + "=2002.4 Winter", + "=2003.0 Winter", + "=2003.1 Spring", + "=2003.3 Fall", + "=2003.4 Winter", + "=2004.0 Winter", + "=2005.1 Spring", + "=2005.2 Summer", + "=2005.3 Fall", + "=2005.4 Winter", + "=2006.0 Winter", + "=2006.1 Spring", + "=2006.3 Fall", + "=2007.0 Winter", + "=2007.2 Summer Logan Michael", + "=2007.2 Summer", + "=2007.3 Fall Logan Michael", + "=2007.4 Winter Logan Michael", + "=2008.0 Winter Logan Michael", + "=2008.1 Spring Logan Michael", + "=2008.2 Summer Logan Michael", + "=2008.2 Summer", + "=2008.3 Fall Logan Michael", + "=2009.0 Winter Logan Michael", + "=2009.0 Winter", + "=2009.1 Spring Logan Michael", + "=2009.1 Spring", + "=2009.2 Summer Logan Michael", + "=2009.2 Summer", + "=2009.3 Fall Logan Michael", + "=2009.3 Fall", + "=2009.4 Winter Logan Michael", + "=2009.4 Winter", + "=2010.0 Winter Logan Michael", + "=2010.0 Winter", + "=2010.1 Spring Logan Michael", + "=2010.1 Spring", + "=2010.2 Summer", + "=2010.3 Fall Logan Michael", + "=2010.3 Fall", + "=2010.4 Winter", + "=2011.0 Winter", + "=2011.1 Spring", + "=2011.2 Summer", + "=2011.3 Fall", + "=2011.4 Winter", + "=2012.0 Winter Chelsea 2012", + "=2012.0 Winter Chelsea", + "=2012.0 Winter", + "=2012.1 Spring Chelsea", + "=2012.1 Spring", + "=2012.2 Summer Chelsea", + "=2012.2 Summer", + "=2012.3 Fall Chelsea", + "=2012.3 Fall", + "=2012.4 Winter Chelsea", + "=2012.4 Winter", + "=2013.0 Winter Chelsea 2013", + "=2013.0 Winter Chelsea", + "=2013.0 Winter", + "=2013.1 Spring", + "=2013.2 Summer Chelsea", + "=2013.2 Summer", + "=2013.3 Fall Chelsea", + "=2013.3 Fall", + "=2013.4 Winter", + "=2014.0 Winter", + "=2014.1 Spring", + "=2014.2 Summer", + "=2014.3 Fall", + "=2014.4 Winter", + "=2015.0 Winter", + "=2015.1 Spring", + "=2015.2 Summer", + "=2015.3 Fall", + "=2015.4 Winter", + "=2016.0 Winter", + "=2016.1 Spring", + "=2016.2 Summer", + "=2016.3 Fall", + "=2016.4 Winter", + "=2017.1 Spring", + "=2017.2 Summer", + "=2017.3 Fall", + "=2017.4 Winter", + "=2018.0 Winter", + "=2018.1 Spring", + "=2018.3 Fall", + "=2018.4 Winter", + "=2019.0 Winter", + "=2019.1 Spring", + "=2019.2 Summer", + "=2019.3 Fall", + "=2019.4 Winter", + "=2020.0 Winter", + "=2020.1 Spring", + "=2020.2 Summer", + "=2020.3 Fall", + "=2020.4 Winter", + "=2021.1 Spring", + "=2021.2 Summer", + "=2021.3 Fall", + "=2021.4 Winter", + "=2022.0 Winter", + "=2022.1 Spring", + "Anthem 2015", + "April 2010", + "April 2013", + "December 2006", + "December 2010", + "Fall 2005", + "Fall 2015", + "Fall 2016", + "Fall 2017", + "Fall 2018", + "Fall 2019", + "Fall 2020", + "Fall 2021", + "February 2010", + "January 2015", + "July 2010", + "June 2010", + "Kids 2005", + "March 2013", + "May 2010", + "May 2011", + "May 2013", + "October 2005", + "October 2014", + "Spring 2013", + "Spring 2014", + "Spring 2016", + "Spring 2018", + "Spring 2019", + "Spring 2020", + "Summer 2011", + "Summer 2012", + "Summer 2013", + "Summer 2014", + "Summer 2015", + "Summer 2016", + "Summer 2017", + "Summer 2018", + "Summer 2020", + "Summer 2021", + "Winter 2015", + "Winter 2016", + "Winter 2017", + "Winter 2018", + "Winter 2019-2020", + "Winter 2020", + "zzz =2005.0 Winter Tracy Pictures", + "zzz =2005.1 Spring Tracy Pictures", + "zzz =2005.2 Summer Tracy Pictures", + "zzz =2005.3 Fall Tracy Pictures", + "zzz =2005.4 Winter Tracy Pictures", + "zzz =2006.1 Spring Tracy Pictures", + "zzz =2007.0 Winter Tracy Pictures", + "zzz =2007.2 Summer Tracy Pictures", + "zzz =2008.0 Winter Tracy Pictures", + "zzz =2008.2 Summer Tracy Pictures", + "zzz =2009.0 Winter Tracy Pictures", + "zzz =2009.2 Summer Tracy Pictures", + "zzz =2009.3 Fall Tracy Pictures", + "zzz =2009.4 Winter Tracy Pictures", + "zzz =2010.0 Winter Tracy Pictures", + "zzz =2010.1 Spring Tracy Pictures", + "zzz =2010.2 Summer Tracy Pictures", + "zzz =2010.3 Fall Tracy Pictures", + "zzz =2011.0 Winter Tracy Pictures", + "zzz =2011.1 Spring Tracy Pictures", + "zzz =2011.2 Summer Tracy Pictures", + "zzz =2011.3 Fall Tracy Pictures", + "zzz =2011.4 Winter Tracy Pictures", + "zzz =2012.0 Winter Tracy Pictures", + "zzz =2012.1 Spring Tracy Pictures", + "zzz =2012.2 Summer Tracy Pictures", + "zzz =2012.3 Fall Tracy Pictures", + "zzz =2012.4 Winter Tracy Pictures", + "zzz =2013.0 Winter Tracy Pictures", + "zzz =2013.1 Spring Tracy Pictures", + "zzz =2013.2 Summer Tracy Pictures", + "zzz =2013.3 Fall Tracy Pictures", + "zzz =2013.4 Winter Tracy Pictures", + "zzz =2014.0 Winter Tracy Pictures", + "zzz =2014.1 Spring Tracy Pictures", + "zzz =2014.2 Summer Tracy Pictures", + "zzz =2014.3 Fall Tracy Pictures", + "zzz =2014.4 Winter Tracy Pictures", + "zzz =2015.0 Winter Tracy Pictures" + ] + } + } +} \ No newline at end of file diff --git a/Delete-By-Relative/appsettings.json b/Delete-By-Relative/appsettings.json new file mode 100644 index 0000000..21aca76 --- /dev/null +++ b/Delete-By-Relative/appsettings.json @@ -0,0 +1,117 @@ +{ + "CompareRootDirectory": "", + "Company": "Mike Phares", + "Linux": {}, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Log4netProvider": "Debug", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "MaxDegreeOfParallelism": 6, + "Serilog": { + "Using": [ + "Serilog.Sinks.Console", + "Serilog.Sinks.File" + ], + "MinimumLevel": "Information", + "WriteTo": [ + { + "Name": "Debug", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "Console", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "%workingDirectory% - Log/log-.txt", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}", + "rollingInterval": "Hour" + } + } + ], + "Enrich": [ + "FromLogContext", + "WithMachineName", + "WithThreadId" + ], + "Properties": { + "Application": "Sample" + } + }, + "WorkingDirectoryName": "PharesApps", + "Windows": { + "Configuration": { + "DateGroup": "2022-11-12", + "DiffPropertyDirectory": "", + "FileNameDirectorySeparator": ".Z.", + "ForcePropertyLastWriteTimeToCreationTime": false, + "MaxImagesInDirectoryForTopLevelFirstPass": 10, + "OutputExtension": ".jpg", + "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", + "PopulatePropertyId": true, + "PropertiesChangedForProperty": false, + "ResultAllInOne": "_ _ _", + "ResultCollection": "[]", + "ResultContent": "()", + "ResultSingleton": "{}", + "RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8", + "WriteBitmapDataBytes": false, + "IgnoreExtensions": [ + ".gif", + ".GIF" + ], + "ValidImageFormatExtensions": [ + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".png", + ".PNG", + ".tiff", + ".TIFF" + ], + "ValidMetadataExtensions": [ + ".3gp", + ".3GP", + ".avi", + ".AVI", + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".ico", + ".ICO", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".m4v", + ".M4V", + ".mov", + ".MOV", + ".mp4", + ".MP4", + ".mta", + ".MTA", + ".png", + ".PNG", + ".tiff", + ".TIFF" + ] + } + } +} \ No newline at end of file diff --git a/Distance/Distance.csproj b/Distance/Distance.csproj index 0e64d91..a28a166 100644 --- a/Distance/Distance.csproj +++ b/Distance/Distance.csproj @@ -39,7 +39,7 @@ - + diff --git a/Distance/Models/MapLogicSupport.cs b/Distance/Models/MapLogicSupport.cs index f64a915..9f4ee38 100644 --- a/Distance/Models/MapLogicSupport.cs +++ b/Distance/Models/MapLogicSupport.cs @@ -135,7 +135,7 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport } foreach (Sorting sorting in collection) { - if (face.Mapping is null || faceDistanceEncoding.NormalizedPixelPercentage is null) + if (face.Mapping is null || faceDistanceEncoding.NormalizedRectangle is null) throw new NotSupportedException(); if (sorting.DaysDelta > rangeDaysDeltaTolerance) { @@ -165,12 +165,10 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport return results; } - private static List GetSortingCollection(MapLogic mapLogic, List faceDistanceEncodings, int faceDistanceContainersLength, int i, FaceDistance faceDistanceEncoding) + private static List GetSortingCollection(MapLogic mapLogic, List faceDistanceEncodings, int i, FaceDistance faceDistanceEncoding) { List results; List faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding); - if (faceDistanceLengths.Count != faceDistanceContainersLength) - throw new NotSupportedException(); results = mapLogic.GetSortingCollection(i, faceDistanceEncoding, faceDistanceLengths); return results; } @@ -187,7 +185,7 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport throw new NotSupportedException(); if (face.FaceDistance?.Encoding is not FaceRecognitionDotNet.FaceEncoding faceEncoding) continue; - faceDistance = new(face.Mapping.MappingFromLocation.ConfidencePercent, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedPixelPercentage); + faceDistance = new(face.Mapping.MappingFromLocation.ConfidencePercent, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedRectangle); faceDistanceContainer = new(face, faceDistance); collection.Add(faceDistanceContainer); } @@ -195,7 +193,7 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport return results; } - private static List GetFaceDistanceEncodings(FaceDistanceContainer[] faceDistanceContainers) + private static List GetFaceDistanceEncodings(FaceDistanceContainer[] faceDistanceContainers, List missingFaceDistanceContainers) { List faceDistanceEncodings = new(); foreach (FaceDistanceContainer faceDistanceContainer in faceDistanceContainers) @@ -204,30 +202,36 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport continue; faceDistanceEncodings.Add(faceDistanceContainer.FaceDistance); } + foreach (FaceDistanceContainer faceDistanceContainer in missingFaceDistanceContainers) + { + if (faceDistanceContainer.FaceDistance.Encoding is null) + continue; + faceDistanceEncodings.Add(faceDistanceContainer.FaceDistance); + } return faceDistanceEncodings; } - public SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, Face[] distinctFilteredFaces, int? useFiltersCounter) + public SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, Face[] distinctFilteredFaces, List missingFaceDistanceContainers, int? useFiltersCounter) { SortingContainer[] results; List collection = new(); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(distinctFilteredFaces); - List faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers); + List faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers, missingFaceDistanceContainers); string message = $") {faceDistanceContainers.Length:000} Get Sorting Containers Then Set Face Mapping Sorting Collection - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using ProgressBar progressBar = new(faceDistanceContainers.Length, message, options); _ = Parallel.For(0, faceDistanceContainers.Length, parallelOptions, (i, state) => { progressBar.Tick(); - Face face = faceDistanceContainers[i].Face; - if (face.Mapping is null) - throw new NotSupportedException(); FaceDistance faceDistanceEncoding = faceDistanceContainers[i].FaceDistance; if (mapLogic.Used(faceDistanceEncoding)) return; - List sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, faceDistanceContainers.Length, i, faceDistanceEncoding); + Face face = faceDistanceContainers[i].Face; + if (face.Mapping is null) + throw new NotSupportedException(); + List sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, i, faceDistanceEncoding); if (!sortingCollection.Any()) return; List sortingContainers = GetSortingContainers(face, faceDistanceEncoding, sortingCollection, useFiltersCounter); @@ -268,7 +272,7 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport return; progressBar.Tick(); faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); - FaceDistance faceDistance = new(face.Mapping.MappingFromLocation.ConfidencePercent, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedPixelPercentage); + FaceDistance faceDistance = new(face.Mapping.MappingFromLocation.ConfidencePercent, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedRectangle); lock (face) face.SetFaceDistance(faceDistance); }); @@ -325,7 +329,7 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport } } - public static Dictionary> GetIdToNormalizedPixelPercentageToFace(Mapping[] mappingCollection) + public static Dictionary> GetIdToNormalizedRectangleToFace(Mapping[] mappingCollection) { Dictionary> results = new(); Dictionary keyValuePairs; @@ -334,9 +338,9 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport if (!results.ContainsKey(mapping.MappingFromItem.Id)) results.Add(mapping.MappingFromItem.Id, new()); keyValuePairs = results[mapping.MappingFromItem.Id]; - if (keyValuePairs.ContainsKey(mapping.MappingFromLocation.NormalizedPixelPercentage)) - throw new NotSupportedException(); - keyValuePairs.Add(mapping.MappingFromLocation.NormalizedPixelPercentage, mapping); + if (keyValuePairs.ContainsKey(mapping.MappingFromLocation.NormalizedRectangle)) + continue; + keyValuePairs.Add(mapping.MappingFromLocation.NormalizedRectangle, mapping); } return results; } diff --git a/Distance/Models/_E_Distance.cs b/Distance/Models/_E_Distance.cs index f11c82d..7fd1084 100644 --- a/Distance/Models/_E_Distance.cs +++ b/Distance/Models/_E_Distance.cs @@ -1,3 +1,4 @@ +using ShellProgressBar; using System.Text.Json; using View_by_Distance.Distance.Models.Stateless; using View_by_Distance.FaceRecognitionDotNet; @@ -18,11 +19,10 @@ public partial class E_Distance private readonly bool _DistanceMoveUnableToMatch; private readonly List _AllMappedFaceFiles; private readonly double[] _RangeDistanceTolerance; - private readonly int _DistancePixelDistanceTolerance; private readonly List _AllMappedFaceFileNames; private readonly List _DuplicateMappedFaceFiles; - public E_Distance(bool distanceMoveUnableToMatch, int distancePixelDistanceTolerance, bool distanceRenameToMatch, int faceConfidencePercent, double[] rangeDistanceTolerance, double[] rangeFaceConfidence) + public E_Distance(bool distanceMoveUnableToMatch, bool distanceRenameToMatch, int faceConfidencePercent, double[] rangeDistanceTolerance, double[] rangeFaceConfidence) { _Debug = new(); _Moved = new(); @@ -36,7 +36,6 @@ public partial class E_Distance _FaceConfidencePercent = faceConfidencePercent; _RangeDistanceTolerance = rangeDistanceTolerance; _DistanceMoveUnableToMatch = distanceMoveUnableToMatch; - _DistancePixelDistanceTolerance = distancePixelDistanceTolerance; } private void MoveUnableToMatch(string eDistanceContentDirectory, string mappedFaceFile, string mappedFaceFileName) @@ -85,12 +84,12 @@ public partial class E_Distance _Moved.Add(mappedFaceFile); } - private FaceDistanceContainer[] GetFaceDistanceContainers(MappingFromItem mappingFromItem, Face[] filteredFaces) + private FaceDistanceContainer[] GetFaceDistanceContainers(MappingFromItem mappingFromItem, List filteredFaces) { FaceDistanceContainer[] results; int confidencePercent; + int normalizedRectangle; FaceDistance faceDistance; - int normalizedPixelPercentage; FaceDistanceContainer faceDistanceContainer; List collection = new(); foreach (Face face in filteredFaces) @@ -98,13 +97,13 @@ public partial class E_Distance if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) throw new NotSupportedException(); confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_FaceConfidencePercent, _RangeFaceConfidence, face.Location.Confidence); - normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); + normalizedRectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); if (face.FaceDistance?.Encoding is not null && face.FaceDistance.Encoding is FaceRecognitionDotNet.FaceEncoding faceEncoding) - faceDistance = new(confidencePercent, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedPixelPercentage); + faceDistance = new(confidencePercent, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedRectangle); else { faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); - faceDistance = new(confidencePercent, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedPixelPercentage); + faceDistance = new(confidencePercent, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedRectangle); lock (filteredFaces) face.SetFaceDistance(faceDistance); } @@ -127,119 +126,45 @@ public partial class E_Distance return faceDistanceEncodings; } - private List<(Face Face, double? Length)> GetValues(MappingFromItem mappingFromItem, Face[] filteredFaces, string json) + private List<(Face Face, double? Length)> GetValues(MappingFromItem mappingFromItem, Face[] faces, Shared.Models.FaceEncoding modelsFaceEncoding, int normalizedRectangle) { List<(Face Face, double? Length)> results = new(); Face face; FaceDistance faceDistanceLength; - Shared.Models.FaceEncoding? modelsFaceEncoding = JsonSerializer.Deserialize(json); - if (modelsFaceEncoding is null) - throw new NotSupportedException(); - FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding = FaceRecognition.LoadFaceEncoding(modelsFaceEncoding.RawEncoding); - FaceDistance faceDistanceEncoding = new(faceRecognitionDotNetFaceEncoding); - FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(mappingFromItem, filteredFaces); - int faceDistanceContainersLength = faceDistanceContainers.Length; - if (faceDistanceContainersLength != filteredFaces.Length) - throw new NotSupportedException(); - List faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers); - if (faceDistanceEncodings.Count != filteredFaces.Length) - throw new NotSupportedException(); - List faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding); - if (faceDistanceLengths.Count != faceDistanceContainersLength) - throw new NotSupportedException(); - for (int i = 0; i < filteredFaces.Length; i++) + List filteredFaces = FilterByIntersect(faces, normalizedRectangle); + if (filteredFaces.Any()) { - face = filteredFaces[i]; - faceDistanceLength = faceDistanceLengths[i]; - if (faceDistanceLength.Length is null) + FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding = FaceRecognition.LoadFaceEncoding(modelsFaceEncoding.RawEncoding); + FaceDistance faceDistanceEncoding = new(faceRecognitionDotNetFaceEncoding); + FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(mappingFromItem, filteredFaces); + int faceDistanceContainersLength = faceDistanceContainers.Length; + if (faceDistanceContainersLength != filteredFaces.Count) throw new NotSupportedException(); - results.Add(new(face, faceDistanceLength.Length.Value)); + List faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers); + if (faceDistanceEncodings.Count != filteredFaces.Count) + throw new NotSupportedException(); + List faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding); + if (faceDistanceLengths.Count != faceDistanceContainersLength) + throw new NotSupportedException(); + for (int i = 0; i < filteredFaces.Count; i++) + { + face = filteredFaces[i]; + faceDistanceLength = faceDistanceLengths[i]; + if (faceDistanceLength.Length is null) + throw new NotSupportedException(); + results.Add(new(face, faceDistanceLength.Length.Value)); + } } return results; } - private (Face, double?)[] GetClosestFaceByDistanceIgnoringTolerance(MappingFromItem mappingFromItem, Face[] filteredFaces, string json) + private (Face, double?)[] GetClosestFaceByDistanceIgnoringTolerance(MappingFromItem mappingFromItem, int normalizedRectangle, Face[] filteredFaces, Shared.Models.FaceEncoding modelsFaceEncoding) { (Face, double?)[] results; - List<(Face Face, double? Length)> collection = GetValues(mappingFromItem, filteredFaces, json); + List<(Face Face, double? Length)> collection = GetValues(mappingFromItem, filteredFaces, modelsFaceEncoding, normalizedRectangle); results = (from l in collection orderby l.Length select l).Take(1).ToArray(); - (Face face, double? length) = results.First(); - lock (_Debug) - _Debug.Add(length); - return results; - } - - private static (int?, int?) GetXY(int normalizedPixelPercentage, OutputResolution? outputResolution) - { - int? x; - int? y; - if (outputResolution is null) - { - x = null; - y = null; - } - else - { - string normalizedPixelPercentagePadded = Shared.Models.Stateless.Methods.ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = Shared.Models.Stateless.Methods.ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, outputResolution.Width, outputResolution.Height, normalizedPixelPercentagePadded); - } - return new(x, y); - } - - private (Face, double?)[] GetClosestFaceByPixel(Face[] filteredFaces, int? x1, int? y1) - { - (Face, double?)[] results; - int? x2; - int? y2; - double distance; - int normalizedPixelPercentageLoop; - string normalizedPixelPercentagePadded; - List<(Face Face, double? Order)> collection = new(); - if (x1 is null || y1 is null) - throw new NotSupportedException(); - foreach (Face face in filteredFaces) - { - if (face.Location is null || face.OutputResolution is null) - throw new NotSupportedException(); - normalizedPixelPercentageLoop = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); - normalizedPixelPercentagePadded = Shared.Models.Stateless.Methods.ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentageLoop); - (x2, y2) = Shared.Models.Stateless.Methods.ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution.Width, face.OutputResolution.Height, normalizedPixelPercentagePadded); - if (x2 is null || y2 is null) - throw new NotSupportedException(); - distance = Math.Sqrt(Math.Pow(x1.Value - x2.Value, 2) + Math.Pow(y1.Value - y2.Value, 2)); - collection.Add(new(face, distance)); - } - results = (from l in collection orderby l.Order where l.Order < _DistancePixelDistanceTolerance select l).Take(1).ToArray(); - return results; - } - - private (Face, double?)[] GetClosestFaceByPixel(Face[] filteredFaces, int normalizedPixelPercentage) - { - if (!filteredFaces.Any()) - throw new NotSupportedException(); - (Face, double?)[] results; - const int zero = 0; - OutputResolution? outputResolution = filteredFaces[zero].OutputResolution; - (int? x1, int? y1) = GetXY(normalizedPixelPercentage, outputResolution); - results = GetClosestFaceByPixel(filteredFaces, x1, y1); - return results; - } - - private (Face, double?)[] GetClosestFaceByPixel(Face[] filteredFaces, string json) - { - if (!filteredFaces.Any()) - throw new NotSupportedException(); - (Face, double?)[] results; - const int zero = 0; - OutputResolution? outputResolution = filteredFaces[zero].OutputResolution; - if (outputResolution is null) - throw new NullReferenceException(nameof(outputResolution)); - Location? location = JsonSerializer.Deserialize(json); - if (location is null) - throw new NullReferenceException(nameof(location)); - int normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, outputResolution); - (int? x1, int? y1) = GetXY(normalizedPixelPercentage, outputResolution); - results = GetClosestFaceByPixel(filteredFaces, x1, y1); + (Face _, double? length) = results.First(); + _Debug.Add(length); return results; } @@ -276,7 +201,7 @@ public partial class E_Distance mappedFaceDirectory = Path.GetDirectoryName(mappedFaceFile); if (mappedFaceDirectory is null) throw new NotSupportedException(); - deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(mappingFromItem.Id, face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); + deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(mappingFromItem.Id, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); checkFile = Path.Combine(mappedFaceDirectory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}"); if (checkFile == mappedFaceFile) continue; @@ -312,17 +237,44 @@ public partial class E_Distance } } - public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, string? eDistanceContentDirectory, MappingFromItem mappingFromItem, List faces, List<(string MappedFaceFile, int normalizedPixelPercentage)> collection) + private static List FilterByIntersect(Face[] faces, int normalizedRectangle) + { + List results = new(); + results.AddRange(faces); + // double? percent; + // System.Drawing.Rectangle checkRectangle; + // System.Drawing.Rectangle sourceRectangle; + // System.Drawing.Rectangle intersectRectangle; + // string npp = normalizedRectangle.ToString(); + // foreach (Face face in faces) + // { + // if (face.Location is null || face.OutputResolution is null) + // continue; + // sourceRectangle = new(npp, npp, npp, npp); + // checkRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top); + // intersectRectangle = System.Drawing.Rectangle.Intersect(sourceRectangle, checkRectangle); + // if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0) + // continue; + // percent = (double)intersectRectangle.Width * intersectRectangle.Height / (checkRectangle.Width * checkRectangle.Height); + // if (percent < 0.000001) + // continue; + // results.Add(face); + // } + return results; + } + + public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, string? eDistanceContentDirectory, MappingFromItem mappingFromItem, List faces, List<(string MappedFaceFile, int normalizedRectangle)> collection) { string? json; string[] matches; FileInfo? fileInfo; string mappedFaceFileName; List<(Face, double?)> checkFaces = new(); + Shared.Models.FaceEncoding? modelsFaceEncoding; Face[] filteredFaces = (from l in faces where l.FaceEncoding is not null && l.Location is not null && l.OutputResolution is not null select l).ToArray(); if (filteredFaces.Length != faces.Count) checkFaces.Clear(); - foreach ((string mappedFaceFile, int normalizedPixelPercentage) in collection) + foreach ((string mappedFaceFile, int normalizedRectangle) in collection) { if (!filteredFaces.Any()) break; @@ -343,19 +295,10 @@ public partial class E_Distance if (checkFaces.Count != 1 && !string.IsNullOrEmpty(json)) { checkFaces.Clear(); - if (json is null) + modelsFaceEncoding = JsonSerializer.Deserialize(json); + if (modelsFaceEncoding is null) throw new NotSupportedException(); - checkFaces.AddRange(GetClosestFaceByDistanceIgnoringTolerance(mappingFromItem, filteredFaces, json)); - } - if (checkFaces.Count != 1 && _DistancePixelDistanceTolerance > 0) - { - checkFaces.Clear(); - json = Metadata.Models.Stateless.IMetadata.GetFaceLocation(mappedFaceFile); - if (json is not null) - checkFaces.AddRange(GetClosestFaceByPixel(filteredFaces, json)); - else - checkFaces.AddRange(GetClosestFaceByPixel(filteredFaces, normalizedPixelPercentage)); - throw new NotImplementedException("Without a tolerance this should not ever occur!"); + checkFaces.AddRange(GetClosestFaceByDistanceIgnoringTolerance(mappingFromItem, normalizedRectangle, filteredFaces, modelsFaceEncoding)); } if (!checkFaces.Any()) { @@ -415,4 +358,57 @@ public partial class E_Distance _DuplicateMappedFaceFiles.Clear(); } + public List GetMissingFaceDistanceContainer(int maxDegreeOfParallelism, long ticks, string dFacesCollectionDirectory, Dictionary> missingIdThenNormalizedRectangleToPersonContainers) + { + List results = new(); + string[] files; + List? faces; + int confidencePercent; + int normalizedRectangle; + bool? isWrongYear = null; + FaceDistance faceDistance; + List<(int id, string json)> collection = new(); + FaceDistanceContainer faceDistanceContainer; + foreach (KeyValuePair> keyValuePair in missingIdThenNormalizedRectangleToPersonContainers) + { + files = Directory.GetFiles(dFacesCollectionDirectory, $"{keyValuePair.Key}*.json", SearchOption.TopDirectoryOnly); + if (files.Length != 1) + continue; + collection.Add(new(keyValuePair.Key, Shared.Models.Stateless.Methods.IFace.GetJson(files[0]))); + } + int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); + ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; + string message = $") {collection.Count:000} Setting missing distance containers - {totalSeconds} total second(s)"; + ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; + using ProgressBar progressBar = new(collection.Count, message, options); + _ = Parallel.For(0, collection.Count, parallelOptions, (i, state) => + { + progressBar.Tick(); + int id = collection[i].id; + string json = collection[i].json; + faces = JsonSerializer.Deserialize>(json); + if (faces is null) + throw new NullReferenceException(nameof(faces)); + foreach (Face face in faces) + { + if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) + continue; + confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_FaceConfidencePercent, _RangeFaceConfidence, face.Location.Confidence); + normalizedRectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); + if (face.FaceDistance?.Encoding is not null && face.FaceDistance.Encoding is FaceRecognitionDotNet.FaceEncoding faceEncoding) + faceDistance = new(confidencePercent, faceEncoding, id, isWrongYear, face.DateTime, normalizedRectangle); + else + { + faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); + faceDistance = new(confidencePercent, faceEncoding, id, isWrongYear, face.DateTime, normalizedRectangle); + face.SetFaceDistance(faceDistance); + } + faceDistanceContainer = new(face, faceDistance); + lock (results) + results.Add(faceDistanceContainer); + } + }); + return results; + } + } \ No newline at end of file diff --git a/Drag-Drop/Form.cs b/Drag-Drop/Form.cs index d39038e..f43ba5a 100644 --- a/Drag-Drop/Form.cs +++ b/Drag-Drop/Form.cs @@ -48,9 +48,12 @@ public partial class Form : System.Windows.Forms.Form isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() - .AddJsonFile(isEnvironment.AppSettingsFileName); + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); configurationRoot = configurationBuilder.Build(); appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); @@ -176,6 +179,7 @@ public partial class Form : System.Windows.Forms.Form _ProgressBar.Step = 1; bool isIgnoreExtension; _ProgressBar.Value = 0; + bool skipOneAllAreNumbers; DateTime? minimumDateTime; _ProgressBar.Visible = true; bool isValidImageFormatExtension; @@ -187,14 +191,18 @@ public partial class Form : System.Windows.Forms.Form _ProgressBar.PerformStep(); fileHolder = new(file); _Lines.Add(fileHolder.NameWithoutExtension); + if (fileHolder.ExtensionLowered == ".id" || fileHolder.DirectoryName is null) + continue; + if (files.Contains($"{fileHolder.FullName}.id")) + continue; isValidImageFormatExtension = _Configuration.PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered); isIgnoreExtension = isValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered); - if (fileHolder.CreationTime is null || fileHolder.Name.Contains(fileHolder.CreationTime.Value.ToString("yy"))) - continue; - if (fileHolder.LastWriteTime is null || fileHolder.Name.Contains(fileHolder.LastWriteTime.Value.ToString("yy"))) - continue; - if (fileHolder.NameWithoutExtension.Length == 1 || fileHolder.NameWithoutExtension[1..].All(l => char.IsNumber(l))) - continue; + if (fileHolder.NameWithoutExtension.Length > 4) + { + skipOneAllAreNumbers = fileHolder.NameWithoutExtension[1..].All(l => char.IsNumber(l)); + if ((skipOneAllAreNumbers && fileHolder.NameWithoutExtension[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileHolder.NameWithoutExtension[0]))) + continue; + } if (!isIgnoreExtension && isValidImageFormatExtension) extraLargeBitmapThumbnail = null; else @@ -210,16 +218,19 @@ public partial class Form : System.Windows.Forms.Form } if (fileHolder.DirectoryName is null) continue; - dateTime = IProperty.GetDateTimeFromName(fileHolder); - if (dateTime is not null && fileHolder.Name.Contains(dateTime.Value.ToString("yy"))) - continue; (minimumDateTime, id, message) = IProperty.Get(fileHolder); if (id is null) continue; - if (minimumDateTime is not null && fileHolder.Name.Contains(minimumDateTime.Value.ToString("yy"))) - continue; - if (dateTime is not null && minimumDateTime is not null && minimumDateTime.Value != dateTime.Value) + dateTime = IProperty.GetDateTimeFromName(fileHolder); + if (dateTime is not null && minimumDateTime is not null && new TimeSpan(Math.Abs(minimumDateTime.Value.Ticks - dateTime.Value.Ticks)).TotalMinutes > 2) + { + checkFile = Path.Combine(fileHolder.DirectoryName, $"{dateTime.Value:yyyy-MM-dd}.{dateTime.Value.Ticks}{fileHolder.ExtensionLowered}"); + if (checkFile == fileHolder.FullName || File.Exists(checkFile)) + continue; + File.Move(fileHolder.FullName, checkFile); + File.WriteAllText($"{checkFile}.id", $"{id.Value}{Environment.NewLine}{fileHolder.Name}"); continue; + } if (extraLargeBitmapThumbnail is not null) { File.Delete(fileHolder.FullName); @@ -228,9 +239,10 @@ public partial class Form : System.Windows.Forms.Form continue; } checkFile = Path.Combine(fileHolder.DirectoryName, $"{id.Value}{fileHolder.ExtensionLowered}"); - if (File.Exists(checkFile)) + if (checkFile == fileHolder.FullName || File.Exists(checkFile)) continue; File.Move(fileHolder.FullName, checkFile); + File.WriteAllText($"{checkFile}.id", $"{id.Value}{Environment.NewLine}{fileHolder.Name}"); } _ProgressBar.Visible = false; } diff --git a/Drag-Drop/Models/Binder/Configuration.cs b/Drag-Drop/Models/Binder/Configuration.cs index 97c6d25..70a1671 100644 --- a/Drag-Drop/Models/Binder/Configuration.cs +++ b/Drag-Drop/Models/Binder/Configuration.cs @@ -190,7 +190,7 @@ public class Configuration configuration = configurationSection.Get(); } result = Get(configuration); - result.SetAndUpdate(propertyConfiguration, null, null, null, null); + result.SetAndUpdate(propertyConfiguration); return result; } diff --git a/Drag-Drop/Models/Configuration.cs b/Drag-Drop/Models/Configuration.cs index 4604bb2..b84cc67 100644 --- a/Drag-Drop/Models/Configuration.cs +++ b/Drag-Drop/Models/Configuration.cs @@ -145,10 +145,10 @@ public class Configuration return result; } - public void SetAndUpdate(Property.Models.Configuration configuration, int? numberOfJitters, int? numberOfTimesToUpsample, string? modelName, string? predictorModelName) + public void SetAndUpdate(Property.Models.Configuration configuration) { _PropertyConfiguration = configuration; - _PropertyConfiguration.Update(numberOfJitters, numberOfTimesToUpsample, modelName, predictorModelName); + _PropertyConfiguration.Update(); } } \ No newline at end of file diff --git a/Duplicate-Search/.vscode/format-report.json b/Duplicate-Search/.vscode/format-report.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/Duplicate-Search/.vscode/format-report.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/Duplicate-Search/.vscode/launch.json b/Duplicate-Search/.vscode/launch.json new file mode 100644 index 0000000..f7b185a --- /dev/null +++ b/Duplicate-Search/.vscode/launch.json @@ -0,0 +1,32 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/bin/Debug/net6.0/win-x64/Duplicate-Search.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development", + }, + "cwd": "${workspaceFolder}", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "externalTerminal", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processName": "Duplicate-Search" + } + ] +} \ No newline at end of file diff --git a/Duplicate-Search/.vscode/settings.json b/Duplicate-Search/.vscode/settings.json new file mode 100644 index 0000000..768342e --- /dev/null +++ b/Duplicate-Search/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "cSpell.words": [ + "Barrick", + "bcdfghjklmnpqrstvwxyz", + "Beichler", + "Bohdi", + "Dlib", + "exif", + "nosj", + "Phares", + "Serilog", + "Vericruz" + ] +} \ No newline at end of file diff --git a/Duplicate-Search/.vscode/tasks.json b/Duplicate-Search/.vscode/tasks.json new file mode 100644 index 0000000..3c2eb55 --- /dev/null +++ b/Duplicate-Search/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/Duplicate-Search.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/Duplicate-Search.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/Duplicate-Search.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/Duplicate-Search/Duplicate-Search.csproj b/Duplicate-Search/Duplicate-Search.csproj new file mode 100644 index 0000000..26ef879 --- /dev/null +++ b/Duplicate-Search/Duplicate-Search.csproj @@ -0,0 +1,62 @@ + + + enable + 10.0 + enable + Exe + win-x64 + net7.0 + + + Phares.View.by.Distance.Duplicate-Search + false + 6.0.100.1 + Mike Phares + Phares + true + snupkg + + + true + true + true + + + Windows + + + OSX + + + Linux + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + Always + + + \ No newline at end of file diff --git a/Duplicate-Search/DuplicateSearch.cs b/Duplicate-Search/DuplicateSearch.cs new file mode 100644 index 0000000..ed75619 --- /dev/null +++ b/Duplicate-Search/DuplicateSearch.cs @@ -0,0 +1,255 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using ShellProgressBar; +using System.Text; +using System.Text.Json; +using View_by_Distance.Duplicate.Search.Models; +using View_by_Distance.Property.Models; +using View_by_Distance.Shared.Models; +using View_by_Distance.Shared.Models.Methods; + +namespace View_by_Distance.Duplicate.Search; + +public class DuplicateSearch +{ + + public DuplicateSearch(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) + { + if (isSilent) + { } + if (console is null) + { } + string searchPattern = "*"; + long ticks = DateTime.Now.Ticks; + ILogger? log = Log.ForContext(); + Configuration configuration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); + configuration.Update(); + log.Information(configuration.RootDirectory); + if (appSettings.IndexOnly) + WriteIndexData(ticks, configuration, searchPattern); + else + { + Configuration.Verify(configuration, requireExist: false); + string argZero = args.Count > 0 ? Path.GetFullPath(args[0]) : Path.GetFullPath(configuration.RootDirectory); + bool argZeroIsConfigurationRootDirectory = configuration.RootDirectory == argZero; + Container[] containers = GetContainers(appSettings, ticks, argZero, configuration, argZeroIsConfigurationRootDirectory); + string destinationRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, "Z) Moved"); + List preloadIds = GetPreloadIds(destinationRoot); + Dictionary> idToCollection = GetIdToCollection(appSettings, argZero, configuration, argZeroIsConfigurationRootDirectory, containers, destinationRoot, preloadIds); + int duplicates = (from l in idToCollection where l.Value.Count > 1 select 1).Sum(); + if (duplicates == 0) + log.Information($"Found {duplicates} duplicate file(s)"); + else + QuestionMove(ticks, log, destinationRoot, idToCollection, duplicates); + } + } + + private static void WriteIndexData(long ticks, Configuration configuration, string searchPattern) + { + string? alongSideDirectory; + string directoryName = Path.GetFileName(configuration.RootDirectory); + if (Path.GetPathRoot(configuration.RootDirectory) == configuration.RootDirectory) + alongSideDirectory = configuration.RootDirectory; + else + alongSideDirectory = Path.GetDirectoryName(configuration.RootDirectory); + if (alongSideDirectory is null) + throw new NullReferenceException(nameof(alongSideDirectory)); + IEnumerable<(string, string[])> files = Shared.Models.Stateless.Methods.IFileHolder.GetFiles(configuration.RootDirectory, searchPattern); + List fileHolders = Shared.Models.Stateless.Methods.IFileHolder.GetFileHolders(files.ToArray()); + File.WriteAllLines(Path.Combine(alongSideDirectory, $"{directoryName}-{ticks}.tsv"), fileHolders.Select(l => l.FullName)); + string json = JsonSerializer.Serialize(fileHolders); + File.WriteAllText(Path.Combine(alongSideDirectory, $"{directoryName}-{ticks}.json"), json); + } + + private static void Move(ILogger log, long ticks, string destinationRoot, List<(FileHolder ImageFileHolder, string Destination)> collection) + { + StringBuilder stringBuilder = new(); + foreach ((FileHolder fileHolder, string destination) in collection) + { + _ = stringBuilder.AppendLine(fileHolder.FullName); + _ = stringBuilder.AppendLine(destination); + } + _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(destinationRoot, $"{ticks}file(s).lsv"), stringBuilder.ToString(), updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); + log.Information($"Ready to move {collection.Count} file(s)?"); + for (int y = 0; y < int.MaxValue; y++) + { + log.Information("Press \"Y\" key to move file(s) or close console to not move files"); + if (System.Console.ReadKey().Key == ConsoleKey.Y) + break; + } + log.Information(". . ."); + foreach ((FileHolder fileHolder, string destination) in collection) + { + try + { File.Move(fileHolder.FullName, destination); } + catch (Exception exception) + { log.Error(exception, $"Failed to move <{fileHolder.FullName}>"); } + } + log.Information($"{collection.Count} file(s) moved"); + for (int y = 0; y < int.MaxValue; y++) + { + log.Information("Press \"Y\" key to move file(s) back or close console to leave them moved"); + if (System.Console.ReadKey().Key != ConsoleKey.Y) + continue; + log.Information(". . ."); + foreach ((FileHolder fileHolder, string destination) in collection) + { + if (!File.Exists(destination)) + continue; + if (File.Exists(fileHolder.FullName)) + continue; + try + { File.Move(destination, fileHolder.FullName); } + catch (Exception exception) + { log.Error(exception, $"Failed to move <{destination}>"); } + } + } + log.Information(". . ."); + } + + private static void QuestionMove(long ticks, ILogger log, string destinationRoot, Dictionary> idToCollection, int duplicates) + { + int[] ids = (from l in idToCollection orderby l.Key where l.Value.Any(m => m is not null) select l.Key).ToArray(); + _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(destinationRoot, $"{ticks}-id(s).lsv"), string.Join(Environment.NewLine, ids), updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); + string json = JsonSerializer.Serialize(idToCollection, new JsonSerializerOptions { WriteIndented = true }); + _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(destinationRoot, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); + log.Information($"Found {duplicates} duplicate file(s)"); + for (int y = 0; y < int.MaxValue; y++) + { + log.Information("Press \"Y\" key to continue or close console to leave them moved"); + if (System.Console.ReadKey().Key != ConsoleKey.Y) + continue; + log.Information(". . ."); + List<(FileHolder ImageFileHolder, string Destination)> collection = GetCollectionAndCreateDirectories(idToCollection); + Move(log, ticks, destinationRoot, collection); + } + } + + private static Container[] GetContainers(AppSettings appSettings, long ticks, string argZero, Configuration configuration, bool argZeroIsConfigurationRootDirectory) + { + int j; + int f; + int t; + Container[] containers; + int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); + string message = $") Building Container(s) - {totalSeconds} total second(s)"; + A_Property propertyLogic = new(appSettings.MaxDegreeOfParallelism, configuration, appSettings.OutputExtension, appSettings.Reverse); + ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; + using (ProgressBar progressBar = new(1, message, options)) + { + progressBar.Tick(); + (j, f, t, containers) = Property.Models.Stateless.Container.GetContainers(configuration, propertyLogic); + } + if (appSettings.SortContainers) + containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(configuration, appSettings.IgnoreRelativePaths, argZeroIsConfigurationRootDirectory, argZero, containers); + return containers; + } + + private static Dictionary> GetIdToCollection(AppSettings appSettings, string argZero, Configuration configuration, bool argZeroIsConfigurationRootDirectory, Container[] containers, string destinationRoot, List preloadIds) + { + Dictionary> results = new(); + string directory; + const int zero = 0; + Item[] filteredItems; + bool isIgnoreRelativePath; + FileHolder resizedFileHolder; + DateTime[] containerDateTimes; + MappingFromItem? mappingFromItem; + List? collection; + const string duplicates = "-Duplicate(s)"; + if (containers.Any()) + { + foreach (int id in preloadIds) + results.Add(id, new() { null }); + } + foreach (Container container in containers) + { + if (!container.Items.Any()) + continue; + if (!argZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) + continue; + filteredItems = Shared.Models.Stateless.Methods.IContainer.GetFilterItems(configuration, container); + if (!filteredItems.Any()) + continue; + isIgnoreRelativePath = appSettings.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(configuration, appSettings.IgnoreRelativePaths, container.SourceDirectory); + containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems); + foreach (Item item in filteredItems) + { + if (item.Property?.Id is null) + { + if (int.TryParse(item.ImageFileHolder.NameWithoutExtension, out int id)) + continue; + continue; + } + if (!results.TryGetValue(item.Property.Id.Value, out collection)) + results.Add(item.Property.Id.Value, new()); + if (collection is null && !results.TryGetValue(item.Property.Id.Value, out collection)) + continue; + if (collection.Count == 0) + directory = $"0{duplicates}"; + else + directory = $"{collection.Count + 1}{duplicates}"; + if (collection.Count == 1) + { + mappingFromItem = collection[zero]; + if (mappingFromItem is not null) + { + resizedFileHolder = new(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}")); + collection[0] = new(mappingFromItem.ContainerDateTimes, mappingFromItem.Id, mappingFromItem.ImageFileHolder, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, mappingFromItem.RelativePath, resizedFileHolder); + } + } + resizedFileHolder = new(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath)); + mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); + collection.Add(mappingFromItem); + } + } + return results; + } + + private static List<(FileHolder ImageFileHolder, string Destination)> GetCollectionAndCreateDirectories(Dictionary> idToCollection) + { + List<(FileHolder ImageFileHolder, string Destination)> results = new(); + List collection = new(); + foreach (KeyValuePair> keyValuePair in idToCollection) + { + foreach (MappingFromItem? mappingFromItem in keyValuePair.Value) + { + if (mappingFromItem?.ResizedFileHolder.DirectoryName is null) + continue; + if (!mappingFromItem.ImageFileHolder.Exists || mappingFromItem.ResizedFileHolder.Exists) + continue; + collection.Add(mappingFromItem.ResizedFileHolder.DirectoryName); + results.Add(new(mappingFromItem.ImageFileHolder, mappingFromItem.ResizedFileHolder.FullName)); + } + } + foreach (string directory in collection.Distinct()) + { + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); + } + return results; + } + + private static List GetPreloadIds(string destinationRoot) + { + List results = new(); + string[] lines; + string preloadDirectory = Path.Combine(destinationRoot, "Preload"); + if (!Directory.Exists(preloadDirectory)) + _ = Directory.CreateDirectory(preloadDirectory); + string[] files = Directory.GetFiles(preloadDirectory, "*.lsv", SearchOption.TopDirectoryOnly); + foreach (string file in files) + { + lines = File.ReadAllLines(file); + foreach (string line in lines) + { + if (string.IsNullOrEmpty(line) || !int.TryParse(line, out int id) || id == 0) + continue; + results.Add(id); + } + } + return results; + } + +} \ No newline at end of file diff --git a/Duplicate-Search/Models/AppSettings.cs b/Duplicate-Search/Models/AppSettings.cs new file mode 100644 index 0000000..382773f --- /dev/null +++ b/Duplicate-Search/Models/AppSettings.cs @@ -0,0 +1,37 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace View_by_Distance.Duplicate.Search.Models; + +public class AppSettings +{ + + public string Company { init; get; } + public bool IndexOnly { init; get; } + public string[] IgnoreRelativePaths { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string OutputExtension { init; get; } + public bool SortContainers { init; get; } + public bool Reverse { init; get; } + public string WorkingDirectoryName { init; get; } + + [JsonConstructor] + public AppSettings(string company, bool indexOnly, string[] ignoreRelativePaths, int maxDegreeOfParallelism, string outputExtension, bool sortContainers, bool reverse, string workingDirectoryName) + { + Company = company; + IndexOnly = indexOnly; + IgnoreRelativePaths = ignoreRelativePaths; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + OutputExtension = outputExtension; + SortContainers = sortContainers; + Reverse = reverse; + WorkingDirectoryName = workingDirectoryName; + } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + +} \ No newline at end of file diff --git a/Duplicate-Search/Models/Binder/AppSettings.cs b/Duplicate-Search/Models/Binder/AppSettings.cs new file mode 100644 index 0000000..a3d8f6b --- /dev/null +++ b/Duplicate-Search/Models/Binder/AppSettings.cs @@ -0,0 +1,62 @@ +using Microsoft.Extensions.Configuration; +using System.Text.Json; + +namespace View_by_Distance.Duplicate.Search.Models.Binder; + +public class AppSettings +{ + +#nullable disable + + public string Company { get; set; } + public bool? IndexOnly { get; set; } + public string[] IgnoreRelativePaths { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string OutputExtension { get; set; } + public bool? SortContainers { get; set; } + public bool? Reverse { get; set; } + public string WorkingDirectoryName { get; set; } + +#nullable restore + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + + private static Models.AppSettings Get(AppSettings? appSettings) + { + Models.AppSettings result; + if (appSettings?.IndexOnly is null) + throw new NullReferenceException(nameof(appSettings.IndexOnly)); + if (appSettings?.IgnoreRelativePaths is null) + throw new NullReferenceException(nameof(appSettings.IgnoreRelativePaths)); + if (appSettings?.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + if (appSettings?.SortContainers is null) + throw new NullReferenceException(nameof(appSettings.SortContainers)); + if (appSettings?.Reverse is null) + throw new NullReferenceException(nameof(appSettings.Reverse)); + result = new( + appSettings.Company, + appSettings.IndexOnly.Value, + appSettings.IgnoreRelativePaths, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.OutputExtension, + appSettings.SortContainers.Value, + appSettings.Reverse.Value, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings? appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + +} \ No newline at end of file diff --git a/Duplicate-Search/Models/Stateless/SerilogExtensionMethods.cs b/Duplicate-Search/Models/Stateless/SerilogExtensionMethods.cs new file mode 100644 index 0000000..e8b4399 --- /dev/null +++ b/Duplicate-Search/Models/Stateless/SerilogExtensionMethods.cs @@ -0,0 +1,10 @@ +namespace View_by_Distance.Duplicate.Search.Models.Stateless; + +public static class SerilogExtensionMethods +{ + + internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate); + + internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate); + +} \ No newline at end of file diff --git a/Duplicate-Search/Program.cs b/Duplicate-Search/Program.cs new file mode 100644 index 0000000..170dbbb --- /dev/null +++ b/Duplicate-Search/Program.cs @@ -0,0 +1,70 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using System.Diagnostics; +using System.Reflection; +using View_by_Distance.Duplicate.Search.Models; +using View_by_Distance.Shared.Models.Stateless.Methods; + +namespace View_by_Distance.Duplicate.Search; + +public class Program +{ + + public static void Secondary(List args) + { + LoggerConfiguration loggerConfiguration = new(); + Assembly assembly = Assembly.GetExecutingAssembly(); + bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug"); + IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); + IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() + .AddEnvironmentVariables() + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); + IConfigurationRoot configurationRoot = configurationBuilder.Build(); + AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount) + throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!"); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); + string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); + Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); + _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); + Log.Logger = loggerConfiguration.CreateLogger(); + ILogger log = Log.ForContext(); + int silentIndex = args.IndexOf("s"); + if (silentIndex > -1) + args.RemoveAt(silentIndex); + try + { + if (args is null) + throw new Exception("args is null!"); + Shared.Models.Console console = new(); + _ = new DuplicateSearch(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console); + } + catch (Exception ex) + { + log.Fatal(string.Concat(ex.Message, Environment.NewLine, ex.StackTrace)); + } + finally + { + Log.CloseAndFlush(); + } + if (silentIndex > -1) + log.Debug("Done. Bye"); + else + { + log.Debug("Done. Press 'Enter' to end"); + _ = Console.ReadLine(); + } + } + + public static void Main(string[] args) + { + if (args is not null) + Secondary(args.ToList()); + else + Secondary(new List()); + } + +} \ No newline at end of file diff --git a/Duplicate-Search/appsettings.Development.json b/Duplicate-Search/appsettings.Development.json new file mode 100644 index 0000000..ed60195 --- /dev/null +++ b/Duplicate-Search/appsettings.Development.json @@ -0,0 +1,356 @@ +{ + "IndexOnly": false, + "Logging": { + "LogLevel": { + "Log4netProvider": "Debug" + } + }, + "MaxDegreeOfParallelism": 6, + "Serilog": { + "MinimumLevel": "Debug" + }, + "SortContainers": false, + "IgnoreRelativePaths": [ + "3757 W Whitman 2017", + "501 Playful Meadows 2006", + "501 Playful Meadows 2007", + "501 Playful Meadows 2008", + "501 Playful Meadows 2009", + "501 Playful Meadows 2010", + "501 Playful Meadows 2013", + "501 Playful Meadows 2015", + "6309 Evesham 2003", + "6309 Evesham 2004", + "Crystal's Wedding 2003", + "Danny's Wedding 2009", + "Door images 2019", + "Family Pictures 2006", + "Family Pictures 2007", + "Family Pictures 2011", + "Family Pictures 2013", + "GrandPrix 2004", + "Kids School Pictures 2004", + "Kristy 2002", + "Kristy Parents Wedding 2005", + "Logan Ultrasound 2007", + "Mandy's Dogs 2008", + "Motorcycles 2010", + "Motorcycles 2013", + "Motorcycles 2014", + "Phares Slides", + "Portrait Innovations April 2008", + "Portrait Innovations December 2007", + "Portrait Innovations June 2008", + "Portrait Innovations March 2012", + "The guys house 2000", + "Tracy Pictures 2005", + "Tracy Pictures 2006", + "Tracy Pictures 2007", + "Tracy Pictures 2008", + "Tracy Pictures 2009", + "Tracy Pictures 2010", + "Tracy Pictures 2011", + "Tracy Pictures 2012", + "Tracy Pictures 2013 Jan-July", + "Tracy Pictures 2013 July- Dec", + "Tracy Pictures 2014", + "Tracy Pictures 2015", + "Tracy Took The Kids 2006", + "Tracy's Bday 2012", + "Tracy's Wedding 2002", + "Trip to Colorado 10 2002", + "Trip to Colorado June 2002", + "Tub 2002", + "Vericruz 2011", + "zzz =2005.1 Spring Tracy Pictures", + "zzz =2005.2 Summer Tracy Pictures", + "zzz =2005.3 Fall Tracy Pictures", + "zzz =2005.4 Winter Tracy Pictures", + "zzz =2006.1 Spring Tracy Pictures", + "zzz =2007.0 Winter Tracy Pictures", + "zzz =2007.2 Summer Tracy Pictures", + "zzz =2008.2 Summer Tracy Pictures", + "zzz =2009.0 Winter Tracy Pictures", + "zzz =2009.2 Summer Tracy Pictures", + "zzz =2009.3 Fall Tracy Pictures", + "zzz =2009.4 Winter Tracy Pictures", + "zzz =2010.0 Winter Tracy Pictures", + "zzz =2010.1 Spring Tracy Pictures", + "zzz =2010.2 Summer Tracy Pictures", + "zzz =2010.3 Fall Tracy Pictures", + "zzz =2011.0 Winter Tracy Pictures", + "zzz =2011.1 Spring Tracy Pictures", + "zzz =2011.2 Summer Tracy Pictures", + "zzz =2011.3 Fall Tracy Pictures", + "zzz =2011.4 Winter Tracy Pictures", + "zzz =2012.0 Winter Tracy Pictures", + "zzz =2012.1 Spring Tracy Pictures", + "zzz =2012.2 Summer Tracy Pictures", + "zzz =2012.3 Fall Tracy Pictures", + "zzz =2012.4 Winter Tracy Pictures", + "zzz =2013.0 Winter Tracy Pictures", + "zzz =2013.1 Spring Tracy Pictures", + "zzz =2013.2 Summer Tracy Pictures", + "zzz =2013.3 Fall Tracy Pictures", + "zzz =2013.4 Winter Tracy Pictures", + "zzz =2014.0 Winter Tracy Pictures", + "zzz =2014.1 Spring Tracy Pictures", + "zzz =2014.2 Summer Tracy Pictures", + "zzz =2014.3 Fall Tracy Pictures", + "zzz =2014.4 Winter Tracy Pictures", + "zzz =2015.0 Winter Tracy Pictures", + "zzz Family Pictures", + "zzz Family Pictures", + "zzz Family Pictures", + "zzz Family Pictures", + "zzz GrandPrix", + "zzz Motorcycles", + "zzz Motorcycles", + "zzz Motorcycles", + "zzz Parents Yard", + "zzz Phares Family Pictures", + "zzz Phares Slides ####", + "zzz Portrait Innovations April", + "zzz Portrait Innovations Files", + "zzz Portrait Innovations June", + "zzz Portrait Innovations March", + "zzz Rex Memorial ####", + "zzz Scanned Grandma's Quilt ####", + "zzz Scanned Pictures Of Kids ####", + "zzz Scanned Prints ####", + "zzz Slide in Name Order Originals (622) ####", + "zzz Tub", + "zzz Vericruz" + ], + "Windows": { + "Configuration": { + "xRootDirectory": "F:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8", + "xxRootDirectory": "F:/Tmp/Phares/Compare/Not-Copy-Copy-All", + "RootDirectory": "E:/", + "VerifyToSeason": [ + ". 2000", + ". 2001", + ". 2002", + ". 2003", + ". 2004", + ". 2005", + ". 2006", + ". 2007", + ". 2008", + ". 2009", + ". 2010", + ". 2011", + ". 2012", + ". 2013", + ". 2014", + ". 2015", + ". 2016", + ". 2017", + ". 2018", + ". 2019", + ". 2020", + ". 2021", + ". 2022", + ". 2023", + ". 2024", + ". 2025", + ". 2026", + ". 2027", + ". 2028", + ". 2029", + "=2000.0 Winter", + "=2002.1 Spring", + "=2002.4 Winter", + "=2003.0 Winter", + "=2003.1 Spring", + "=2003.3 Fall", + "=2003.4 Winter", + "=2004.0 Winter", + "=2005.1 Spring", + "=2005.2 Summer", + "=2005.3 Fall", + "=2005.4 Winter", + "=2006.0 Winter", + "=2006.1 Spring", + "=2006.3 Fall", + "=2007.0 Winter", + "=2007.2 Summer Logan Michael", + "=2007.2 Summer", + "=2007.3 Fall Logan Michael", + "=2007.4 Winter Logan Michael", + "=2008.0 Winter Logan Michael", + "=2008.1 Spring Logan Michael", + "=2008.2 Summer Logan Michael", + "=2008.2 Summer", + "=2008.3 Fall Logan Michael", + "=2009.0 Winter Logan Michael", + "=2009.0 Winter", + "=2009.1 Spring Logan Michael", + "=2009.1 Spring", + "=2009.2 Summer Logan Michael", + "=2009.2 Summer", + "=2009.3 Fall Logan Michael", + "=2009.3 Fall", + "=2009.4 Winter Logan Michael", + "=2009.4 Winter", + "=2010.0 Winter Logan Michael", + "=2010.0 Winter", + "=2010.1 Spring Logan Michael", + "=2010.1 Spring", + "=2010.2 Summer", + "=2010.3 Fall Logan Michael", + "=2010.3 Fall", + "=2010.4 Winter", + "=2011.0 Winter", + "=2011.1 Spring", + "=2011.2 Summer", + "=2011.3 Fall", + "=2011.4 Winter", + "=2012.0 Winter Chelsea 2012", + "=2012.0 Winter Chelsea", + "=2012.0 Winter", + "=2012.1 Spring Chelsea", + "=2012.1 Spring", + "=2012.2 Summer Chelsea", + "=2012.2 Summer", + "=2012.3 Fall Chelsea", + "=2012.3 Fall", + "=2012.4 Winter Chelsea", + "=2012.4 Winter", + "=2013.0 Winter Chelsea 2013", + "=2013.0 Winter Chelsea", + "=2013.0 Winter", + "=2013.1 Spring", + "=2013.2 Summer Chelsea", + "=2013.2 Summer", + "=2013.3 Fall Chelsea", + "=2013.3 Fall", + "=2013.4 Winter", + "=2014.0 Winter", + "=2014.1 Spring", + "=2014.2 Summer", + "=2014.3 Fall", + "=2014.4 Winter", + "=2015.0 Winter", + "=2015.1 Spring", + "=2015.2 Summer", + "=2015.3 Fall", + "=2015.4 Winter", + "=2016.0 Winter", + "=2016.1 Spring", + "=2016.2 Summer", + "=2016.3 Fall", + "=2016.4 Winter", + "=2017.1 Spring", + "=2017.2 Summer", + "=2017.3 Fall", + "=2017.4 Winter", + "=2018.0 Winter", + "=2018.1 Spring", + "=2018.3 Fall", + "=2018.4 Winter", + "=2019.0 Winter", + "=2019.1 Spring", + "=2019.2 Summer", + "=2019.3 Fall", + "=2019.4 Winter", + "=2020.0 Winter", + "=2020.1 Spring", + "=2020.2 Summer", + "=2020.3 Fall", + "=2020.4 Winter", + "=2021.1 Spring", + "=2021.2 Summer", + "=2021.3 Fall", + "=2021.4 Winter", + "=2022.0 Winter", + "=2022.1 Spring", + "Anthem 2015", + "April 2010", + "April 2013", + "December 2006", + "December 2010", + "Fall 2005", + "Fall 2015", + "Fall 2016", + "Fall 2017", + "Fall 2018", + "Fall 2019", + "Fall 2020", + "Fall 2021", + "February 2010", + "January 2015", + "July 2010", + "June 2010", + "Kids 2005", + "March 2013", + "May 2010", + "May 2011", + "May 2013", + "October 2005", + "October 2014", + "Spring 2013", + "Spring 2014", + "Spring 2016", + "Spring 2018", + "Spring 2019", + "Spring 2020", + "Summer 2011", + "Summer 2012", + "Summer 2013", + "Summer 2014", + "Summer 2015", + "Summer 2016", + "Summer 2017", + "Summer 2018", + "Summer 2020", + "Summer 2021", + "Winter 2015", + "Winter 2016", + "Winter 2017", + "Winter 2018", + "Winter 2019-2020", + "Winter 2020", + "zzz =2005.0 Winter Tracy Pictures", + "zzz =2005.1 Spring Tracy Pictures", + "zzz =2005.2 Summer Tracy Pictures", + "zzz =2005.3 Fall Tracy Pictures", + "zzz =2005.4 Winter Tracy Pictures", + "zzz =2006.1 Spring Tracy Pictures", + "zzz =2007.0 Winter Tracy Pictures", + "zzz =2007.2 Summer Tracy Pictures", + "zzz =2008.0 Winter Tracy Pictures", + "zzz =2008.2 Summer Tracy Pictures", + "zzz =2009.0 Winter Tracy Pictures", + "zzz =2009.2 Summer Tracy Pictures", + "zzz =2009.3 Fall Tracy Pictures", + "zzz =2009.4 Winter Tracy Pictures", + "zzz =2010.0 Winter Tracy Pictures", + "zzz =2010.1 Spring Tracy Pictures", + "zzz =2010.2 Summer Tracy Pictures", + "zzz =2010.3 Fall Tracy Pictures", + "zzz =2011.0 Winter Tracy Pictures", + "zzz =2011.1 Spring Tracy Pictures", + "zzz =2011.2 Summer Tracy Pictures", + "zzz =2011.3 Fall Tracy Pictures", + "zzz =2011.4 Winter Tracy Pictures", + "zzz =2012.0 Winter Tracy Pictures", + "zzz =2012.1 Spring Tracy Pictures", + "zzz =2012.2 Summer Tracy Pictures", + "zzz =2012.3 Fall Tracy Pictures", + "zzz =2012.4 Winter Tracy Pictures", + "zzz =2013.0 Winter Tracy Pictures", + "zzz =2013.1 Spring Tracy Pictures", + "zzz =2013.2 Summer Tracy Pictures", + "zzz =2013.3 Fall Tracy Pictures", + "zzz =2013.4 Winter Tracy Pictures", + "zzz =2014.0 Winter Tracy Pictures", + "zzz =2014.1 Spring Tracy Pictures", + "zzz =2014.2 Summer Tracy Pictures", + "zzz =2014.3 Fall Tracy Pictures", + "zzz =2014.4 Winter Tracy Pictures", + "zzz =2015.0 Winter Tracy Pictures" + ] + } + } +} \ No newline at end of file diff --git a/Duplicate-Search/appsettings.json b/Duplicate-Search/appsettings.json new file mode 100644 index 0000000..69ad4a3 --- /dev/null +++ b/Duplicate-Search/appsettings.json @@ -0,0 +1,119 @@ +{ + "Company": "Mike Phares", + "IndexOnly": false, + "Linux": {}, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Log4netProvider": "Debug", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "MaxDegreeOfParallelism": 6, + "Reverse": false, + "SortContainers": true, + "Serilog": { + "Using": [ + "Serilog.Sinks.Console", + "Serilog.Sinks.File" + ], + "MinimumLevel": "Information", + "WriteTo": [ + { + "Name": "Debug", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "Console", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "%workingDirectory% - Log/log-.txt", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}", + "rollingInterval": "Hour" + } + } + ], + "Enrich": [ + "FromLogContext", + "WithMachineName", + "WithThreadId" + ], + "Properties": { + "Application": "Sample" + } + }, + "WorkingDirectoryName": "PharesApps", + "Windows": { + "Configuration": { + "DateGroup": "2022-11-12", + "DiffPropertyDirectory": "", + "FileNameDirectorySeparator": ".Z.", + "ForcePropertyLastWriteTimeToCreationTime": false, + "MaxImagesInDirectoryForTopLevelFirstPass": 10, + "OutputExtension": ".jpg", + "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", + "PopulatePropertyId": true, + "PropertiesChangedForProperty": false, + "ResultAllInOne": "_ _ _", + "ResultCollection": "[]", + "ResultContent": "()", + "ResultSingleton": "{}", + "RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8", + "WriteBitmapDataBytes": false, + "IgnoreExtensions": [ + ".gif", + ".GIF" + ], + "ValidImageFormatExtensions": [ + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".png", + ".PNG", + ".tiff", + ".TIFF" + ], + "ValidMetadataExtensions": [ + ".3gp", + ".3GP", + ".avi", + ".AVI", + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".ico", + ".ICO", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".m4v", + ".M4V", + ".mov", + ".MOV", + ".mp4", + ".MP4", + ".mta", + ".MTA", + ".png", + ".PNG", + ".tiff", + ".TIFF" + ] + } + } +} \ No newline at end of file diff --git a/Face/Face.csproj b/Face/Face.csproj index db03be4..4265158 100644 --- a/Face/Face.csproj +++ b/Face/Face.csproj @@ -35,7 +35,7 @@ - + diff --git a/Face/Models/_D_Face.cs b/Face/Models/_D_Face.cs index 9030e25..6ae740f 100644 --- a/Face/Models/_D_Face.cs +++ b/Face/Models/_D_Face.cs @@ -31,12 +31,9 @@ public class D_Face private readonly Model _Model; private readonly string _ArgZero; - private readonly int _NumberOfJitters; private readonly Serilog.ILogger? _Log; private readonly bool _OverrideForFaceImages; private readonly Configuration _Configuration; - private readonly int _NumberOfTimesToUpsample; - private readonly bool _RetryImagesWithoutAFace; private readonly ImageCodecInfo _ImageCodecInfo; private readonly ModelParameter _ModelParameter; private readonly PredictorModel _PredictorModel; @@ -46,6 +43,7 @@ public class D_Face private readonly int _FaceDistanceHiddenImageFactor; private readonly EncoderParameters _EncoderParameters; private readonly ImageCodecInfo _HiddenImageCodecInfo; + private readonly bool _RetryImagesWithoutAFaceLocation; private readonly bool _ForceFaceLastWriteTimeToCreationTime; private readonly EncoderParameters _HiddenEncoderParameters; private readonly JsonSerializerOptions _WriteIndentedAndWhenWritingNull; @@ -64,30 +62,26 @@ public class D_Face ImageCodecInfo imageCodecInfo, string modelDirectory, string modelName, - int numberOfJitters, - int numberOfTimesToUpsample, bool overrideForFaceImages, - bool retryImagesWithoutAFace, + bool retryImagesWithoutAFaceLocation, string predictorModelName, bool propertiesChangedForFaces) { _ArgZero = argZero; _Configuration = configuration; _ImageCodecInfo = imageCodecInfo; - _NumberOfJitters = numberOfJitters; _EncoderParameters = encoderParameters; _FileNameExtension = filenameExtension; _Log = Serilog.Log.ForContext(); AngleBracketCollection = new List(); _HiddenImageCodecInfo = hiddenImageCodecInfo; _OverrideForFaceImages = overrideForFaceImages; - _RetryImagesWithoutAFace = retryImagesWithoutAFace; _HiddenEncoderParameters = hiddenEncoderParameters; _HiddenFileNameExtension = hiddenFileNameExtension; - _NumberOfTimesToUpsample = numberOfTimesToUpsample; _CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates; _PropertiesChangedForFaces = propertiesChangedForFaces; _FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor; + _RetryImagesWithoutAFaceLocation = retryImagesWithoutAFaceLocation; _ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime; (Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(modelDirectory, modelName, predictorModelName); _Model = model; @@ -149,19 +143,10 @@ public class D_Face #pragma warning disable CA1416 - private static byte[] GetBytes(string value) - { - byte[] results = new byte[value.Length + 1]; - for (int i = 0; i < value.Length; i++) - results[i] = (byte)value[i]; - results[value.Length] = 0x00; - return results; - } - private PropertyItem GetPropertyItem(int id, string value) { PropertyItem result = (PropertyItem)_ConstructorInfo.Invoke(null); - byte[] bytes = GetBytes(value); + byte[] bytes = C_Resize.GetBytes(value); result.Id = id; result.Len = value.Length + 1; result.Type = 2; @@ -234,6 +219,10 @@ public class D_Face { if (_Log is null) throw new NullReferenceException(nameof(_Log)); + if (_Configuration.NumberOfJitters is null) + throw new NullReferenceException(nameof(_Configuration.NumberOfJitters)); + if (_Configuration.NumberOfTimesToUpsample is null) + throw new NullReferenceException(nameof(_Configuration.NumberOfTimesToUpsample)); List results = new(); FaceRecognitionDotNet.Image? unknownImage; if (!mappingFromItem.ResizedFileHolder.Exists) @@ -253,7 +242,7 @@ public class D_Face else { List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary? FaceParts)> collection; - FaceRecognition faceRecognition = new(_NumberOfTimesToUpsample, _NumberOfJitters, _PredictorModel, _Model, _ModelParameter); + FaceRecognition faceRecognition = new(_Configuration.NumberOfJitters.Value, _Configuration.NumberOfTimesToUpsample.Value, _Model, _ModelParameter, _PredictorModel); collection = faceRecognition.GetCollection(unknownImage, includeFaceEncoding: true, includeFaceParts: true); if (!collection.Any()) results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null)); @@ -306,9 +295,9 @@ public class D_Face throw new NullReferenceException(nameof(item.ImageFileHolder.DirectoryName)); SetAngleBracketCollection(dResultsFullGroupDirectory, item.ImageFileHolder.DirectoryName); } + result = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); if (!angleBracketCollectionAny) AngleBracketCollection.Clear(); - result = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); return result; } @@ -324,17 +313,6 @@ public class D_Face List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); string dCollectionFile = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.ResultAllInOne, $"{mappingFromItem.Id}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json"); FileInfo fileInfo = new(dCollectionFile); - if (!fileInfo.FullName.Contains(_Configuration.ResultAllInOne) && !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 (_ForceFaceLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) { File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); @@ -367,32 +345,148 @@ public class D_Face parseExceptions.Add(nameof(D_Face)); } } - if (results is null || (_RetryImagesWithoutAFace && results.Count == 1 && results[0].FaceEncoding is null)) + if (results is null || (_RetryImagesWithoutAFaceLocation && results.Count == 1 && results[0].Location is null)) { bool wasNull = results is null; results = GetFaces(property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); - if (wasNull || (!wasNull && results.Any(l => l.FaceEncoding is not null))) + if (wasNull || (!wasNull && results.Any(l => l.Location is not null))) { json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull); bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) - subFileTuples.Add(new Tuple(nameof(D_Face), DateTime.Now)); + { + if (!_ForceFaceLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime)) + subFileTuples.Add(new Tuple(nameof(D_Face), DateTime.Now)); + else + { + File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); + fileInfo.Refresh(); + subFileTuples.Add(new Tuple(nameof(D_Face), fileInfo.CreationTime)); + } + } } } - if (_ForceFaceLastWriteTimeToCreationTime) + return results; + } + + private void WriteAllText(Dictionary>? results, List dateTimes, FileInfo fileInfo) + { + string json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull); + bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; + DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); + if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) { - results = (from l in results select new Shared.Models.Face(ILocation.Digits, ILocation.Factor, results.Count, l)).ToList(); - json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull); - bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; - DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); - if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) + if (!_ForceFaceLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime)) + ; // subFileTuples.Add(new Tuple(nameof(D_Face), DateTime.Now)); + else { File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); fileInfo.Refresh(); - subFileTuples.Add(new Tuple(nameof(D_Face), fileInfo.CreationTime)); + // subFileTuples.Add(new Tuple(nameof(D_Face), fileInfo.CreationTime)); } } + } + + public Dictionary> GetRelativeLocations(string outputResolution, string dResultsDateGroupDirectory, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string original, Dictionary imageResizeKeyValuePairs, List faces) + { + Dictionary>? results; + if (string.IsNullOrEmpty(dResultsDateGroupDirectory)) + throw new NullReferenceException(nameof(dResultsDateGroupDirectory)); + if (!imageResizeKeyValuePairs.ContainsKey(original)) + throw new Exception(); + if (!imageResizeKeyValuePairs.ContainsKey(outputResolution)) + throw new Exception(); + string json; + decimal? h, l, t, w; + RelativeLocation relativeLocation; + List relativeLocations = new(); + int[] resize = imageResizeKeyValuePairs[outputResolution]; + string key = $"{resize[0].ToString().PadLeft(6, '0')}.{resize[1].ToString().PadLeft(6, '0')}"; + string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; + List dateTimes = (from d in subFileTuples where changesFrom.Contains(d.Item1) select d.Item2).ToList(); + string dCollectionDirectory = Path.Combine(dResultsDateGroupDirectory, "[]", _Configuration.ResultAllInOne); + string dCollectionFile = Path.Combine(dCollectionDirectory, $"{mappingFromItem.Id}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json"); + if (!Directory.Exists(dCollectionDirectory)) + _ = Directory.CreateDirectory(dCollectionDirectory); + FileInfo fileInfo = new(dCollectionFile); + if (_ForceFaceLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) + { + File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); + fileInfo.Refresh(); + } + if (_ForceFaceLastWriteTimeToCreationTime && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime) + { + File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); + fileInfo.Refresh(); + } + if (_PropertiesChangedForFaces) + results = null; + else if (!fileInfo.Exists) + results = null; + else if (_CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime) + results = null; + else + { + json = Shared.Models.Stateless.Methods.IFace.GetJson(fileInfo.FullName); + try + { + results = JsonSerializer.Deserialize>>(json); + if (results is null) + throw new NullReferenceException(nameof(results)); + bool added = false; + relativeLocations.Clear(); + foreach (KeyValuePair> keyValuePair in results) + relativeLocations.AddRange(keyValuePair.Value); + if (!results.ContainsKey(key)) + results.Add(key, new()); + foreach (Shared.Models.Face face in faces) + { + if (face.Location is null || face.OutputResolution is null) + continue; + (h, l, t, w) = Shared.Models.Stateless.Methods.ILocation.GetHeightLeftTopWidth(face.Location, face.OutputResolution); + if (h is null || l is null || t is null || w is null) + continue; + relativeLocation = new(face.Location.Confidence, h.Value.ToString(), l.Value.ToString(), t.Value.ToString(), w.Value.ToString()); + if (relativeLocations.Any(r => r.Match(h, l, t, w))) + continue; + if (!added) + added = true; + results[key].Add(relativeLocation); + } + if (added) + { + List<(string Key, List Value)> sort = new(); + foreach (KeyValuePair> keyValuePair in results) + sort.Add(new(keyValuePair.Key, keyValuePair.Value)); + results.Clear(); + foreach ((string k, List v) in sort.OrderBy(l => l.Key)) + results.Add(k, v.OrderByDescending(l => l.Confidence).ToList()); + WriteAllText(results, dateTimes, fileInfo); + } + // subFileTuples.Add(new Tuple(nameof(D_Face), fileInfo.LastWriteTime)); + } + catch (Exception) + { + results = null; + parseExceptions.Add(nameof(D_Face)); + } + } + if (results is null) + { + results = new() { { key, new() } }; + foreach (Shared.Models.Face face in faces) + { + if (face.Location is null || face.OutputResolution is null) + continue; + (h, l, t, w) = Shared.Models.Stateless.Methods.ILocation.GetHeightLeftTopWidth(face.Location, face.OutputResolution); + if (h is null || l is null || t is null || w is null) + continue; + relativeLocation = new(face.Location.Confidence, h.Value.ToString(), l.Value.ToString(), t.Value.ToString(), w.Value.ToString()); + results[key].Add(relativeLocation); + } + WriteAllText(results, dateTimes, fileInfo); + } return results; } @@ -400,7 +494,6 @@ public class D_Face { FileInfo fileInfo; bool result = false; - string parentCheck; string deterministicHashCodeKey; List<(Shared.Models.Face, FileInfo?, string)> collection = new(); string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; @@ -414,16 +507,8 @@ public class D_Face collection.Add(new(face, null, string.Empty)); continue; } - deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(mappingFromItem.Id, face.Location, ILocation.Digits, ILocation.Factor, face.OutputResolution); + deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(mappingFromItem.Id, face.Location, ILocation.Digits, face.OutputResolution); fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{_FileNameExtension}")); - if (!fileInfo.FullName.Contains(_Configuration.ResultAllInOne) && !fileInfo.Exists) - { - if (fileInfo.Directory?.Parent is null) - throw new Exception(); - parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name); - if (File.Exists(parentCheck)) - File.Delete(parentCheck); - } collection.Add(new(face, fileInfo, Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{_HiddenFileNameExtension}"))); if (_OverrideForFaceImages) result = true; diff --git a/FaceParts/FaceParts.csproj b/FaceParts/FaceParts.csproj index 5b9d33f..0da8379 100644 --- a/FaceParts/FaceParts.csproj +++ b/FaceParts/FaceParts.csproj @@ -35,7 +35,7 @@ - + diff --git a/FaceParts/Models/_D2_FaceParts.cs b/FaceParts/Models/_D2_FaceParts.cs index adab701..3887bfc 100644 --- a/FaceParts/Models/_D2_FaceParts.cs +++ b/FaceParts/Models/_D2_FaceParts.cs @@ -4,6 +4,7 @@ using System.Drawing.Imaging; using System.Text.Json; using View_by_Distance.Face.Models; using View_by_Distance.Metadata.Models; +using View_by_Distance.Property.Models.Stateless; using View_by_Distance.Resize.Models; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Properties; @@ -25,12 +26,14 @@ public class D2_FaceParts private readonly bool _CheckDFaceAndUpWriteDates; private readonly bool _OverrideForFaceLandmarkImages; private readonly EncoderParameters _EncoderParameters; + private readonly List _AngleBracketCollection; public D2_FaceParts(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension, bool checkDFaceAndUpWriteDates, bool overrideForFaceLandmarkImages) { _ImageCodecInfo = imageCodecInfo; _EncoderParameters = encoderParameters; _FileNameExtension = filenameExtension; + _AngleBracketCollection = new List(); _Log = Serilog.Log.ForContext(); _CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates; _OverrideForFaceLandmarkImages = overrideForFaceLandmarkImages; @@ -42,6 +45,34 @@ public class D2_FaceParts return result; } + public void SetAngleBracketCollection(Property.Models.Configuration configuration, string d2ResultsFullGroupDirectory, string sourceDirectory) + { + _AngleBracketCollection.Clear(); + _AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(configuration, + sourceDirectory, + d2ResultsFullGroupDirectory, + contentDescription: "n gif file(s) for each face found", + singletonDescription: string.Empty, + collectionDescription: string.Empty, + converted: true)); + } + + public string GetFacePartsDirectory(Property.Models.Configuration configuration, string dResultsFullGroupDirectory, Item item) + { + string result; + bool angleBracketCollectionAny = _AngleBracketCollection.Any(); + if (!angleBracketCollectionAny) + { + if (item.ImageFileHolder.DirectoryName is null) + throw new NullReferenceException(nameof(item.ImageFileHolder.DirectoryName)); + SetAngleBracketCollection(configuration, dResultsFullGroupDirectory, item.ImageFileHolder.DirectoryName); + } + result = Path.Combine(_AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); + if (!angleBracketCollectionAny) + _AngleBracketCollection.Clear(); + return result; + } + private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum) { xMinimum = points[0].X; @@ -166,7 +197,7 @@ public class D2_FaceParts { if (face.Location is null) continue; - graphic.DrawEllipse(Pens.GreenYellow, face.Location.Left + facePoint.X - pointSize, face.Location.Top + facePoint.Y - pointSize, pointSize * 2, pointSize * 2); + graphic.DrawEllipse(Pens.GreenYellow, facePoint.X - pointSize, facePoint.Y - pointSize, pointSize * 2, pointSize * 2); } if (facePart == FacePart.Chin) continue; @@ -176,7 +207,7 @@ public class D2_FaceParts y = (int)(from l in facePoints select l.Y).Average(); if (face.Location is null) continue; - graphic.DrawEllipse(Pens.Purple, face.Location.Left + x - pointSize, face.Location.Top + y - pointSize, pointSize * 2, pointSize * 2); + graphic.DrawEllipse(Pens.Purple, x - pointSize, y - pointSize, pointSize * 2, pointSize * 2); } } image.Save(fileName, _ImageCodecInfo, _EncoderParameters); @@ -201,11 +232,10 @@ public class D2_FaceParts #pragma warning restore CA1416 - public void SaveFaceLandmarkImages(Property.Models.Configuration configuration, string facesDirectory, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, List faceCollection, bool saveRotated) + public void SaveFaceLandmarkImages(Property.Models.Configuration configuration, string facePartsDirectory, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, List faces, bool saveRotated) { FileInfo fileInfo; bool check = false; - string parentCheck; const int pointSize = 2; FileInfo rotatedFileInfo; DateTime? dateTime = null; @@ -215,25 +245,17 @@ public class D2_FaceParts List<(Shared.Models.Face, string, string)> collection = new(); string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - if (!Directory.Exists(facesDirectory)) - _ = Directory.CreateDirectory(facesDirectory); - foreach (Shared.Models.Face face in faceCollection) + if (!Directory.Exists(facePartsDirectory)) + _ = Directory.CreateDirectory(facePartsDirectory); + foreach (Shared.Models.Face face in faces) { if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) { collection.Add(new(face, string.Empty, string.Empty)); continue; } - deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(mappingFromItem.Id, face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); - fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{_FileNameExtension}")); - if (!fileInfo.FullName.Contains(configuration.ResultAllInOne) && !fileInfo.Exists) - { - if (fileInfo.Directory?.Parent is null) - throw new Exception(); - parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name); - if (File.Exists(parentCheck)) - File.Delete(parentCheck); - } + deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(mappingFromItem.Id, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); + fileInfo = new FileInfo(Path.Combine(facePartsDirectory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{_FileNameExtension}")); if (string.IsNullOrEmpty(fileInfo.DirectoryName)) continue; rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKey} - R{mappingFromItem.ImageFileHolder.ExtensionLowered}{_FileNameExtension}")); diff --git a/FaceRecognitionDotNet/FaceRecognition.cs b/FaceRecognitionDotNet/FaceRecognition.cs index 60f4b5f..419ac16 100644 --- a/FaceRecognitionDotNet/FaceRecognition.cs +++ b/FaceRecognitionDotNet/FaceRecognition.cs @@ -26,7 +26,7 @@ public class FaceRecognition : DisposableObject private readonly ShapePredictor _PosePredictor5Point; private readonly ShapePredictor _PosePredictor68Point; - public FaceRecognition(int numberOfTimesToUpsample, int numberOfJitters, PredictorModel predictorModel, Model model, ModelParameter modelParameter) + public FaceRecognition(int numberOfJitters, int numberOfTimesToUpsample, Model model, ModelParameter modelParameter, PredictorModel predictorModel) { if (modelParameter is null) throw new NullReferenceException(nameof(modelParameter)); @@ -284,6 +284,23 @@ public class FaceRecognition : DisposableObject return new FaceEncoding(matrix); } + public static FaceEncoding LoadBFaceEncoding(double[] encoding) + { + if (encoding is null) + throw new NullReferenceException(nameof(encoding)); + if (encoding.Length != 512) + { + string message = $"{nameof(encoding)}.{nameof(encoding.Length)} must be 512."; + throw new ArgumentOutOfRangeException(message); + } +#pragma warning disable + Matrix? matrix = Matrix.CreateTemplateParameterizeMatrix(0, 1); +#pragma warning restore + matrix.SetSize(512); + matrix.Assign(encoding); + return new FaceEncoding(matrix); + } + public static Image LoadImageFile(string file, Mode mode = Mode.Rgb) { if (!File.Exists(file)) diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 48f6b2e..86b9f8e 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -47,7 +47,6 @@ public partial class DlibDotNet IConsole console) { _Console = console; - string argZero; string message; _AppSettings = appSettings; _IsEnvironment = isEnvironment; @@ -56,9 +55,9 @@ public partial class DlibDotNet PersonContainer[] personContainers; _Log = Serilog.Log.ForContext(); Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); + Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); _Log.Information(propertyConfiguration.RootDirectory); Property.Models.Configuration.Verify(propertyConfiguration, requireExist: false); - Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); Verify(configuration); VerifyExtra(args, propertyConfiguration, configuration); _Configuration = configuration; @@ -69,8 +68,13 @@ public partial class DlibDotNet throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(propertyConfiguration, nameof(A_Property), create: false); _PropertyRootExistedBefore = !Directory.Exists(propertyRoot); - argZero = args.Count > 0 ? Path.GetFullPath(args[0]) : Path.GetFullPath(propertyConfiguration.RootDirectory); + string argZero = args.Count > 0 ? Path.GetFullPath(args[0]) : Path.GetFullPath(propertyConfiguration.RootDirectory); _ArgZeroIsConfigurationRootDirectory = propertyConfiguration.RootDirectory == argZero; + if (!Directory.Exists(argZero)) + _ = Directory.CreateDirectory(argZero); + _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(argZero); + if (!Directory.Exists(argZero)) + _ = Directory.CreateDirectory(argZero); _Log.Information(configuration.ModelDirectory); { (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetPngLowQuality(); @@ -89,10 +93,8 @@ public partial class DlibDotNet imageCodecInfo, configuration.ModelDirectory, configuration.ModelName, - configuration.NumberOfJitters, - configuration.NumberOfTimesToUpsample, configuration.OverrideForFaceImages, - configuration.RetryImagesWithoutAFace, + configuration.RetryImagesWithoutAFaceLocation, configuration.PredictorModelName, configuration.PropertiesChangedForFaces); } @@ -102,7 +104,7 @@ public partial class DlibDotNet } _Metadata = new(configuration.ForceMetadataLastWriteTimeToCreationTime, configuration.PropertiesChangedForMetadata); _MapConfiguration = Get(configuration, _Faces.FileNameExtension, _Faces.HiddenFileNameExtension, _FaceParts.FileNameExtension); - _Distance = new(configuration.DistanceMoveUnableToMatch, configuration.DistancePixelDistanceTolerance, configuration.DistanceRenameToMatch, _Configuration.FaceConfidencePercent, configuration.RangeDistanceTolerance, configuration.RangeFaceConfidence); + _Distance = new(configuration.DistanceMoveUnableToMatch, configuration.DistanceRenameToMatch, _Configuration.FaceConfidencePercent, configuration.RangeDistanceTolerance, configuration.RangeFaceConfidence); if (_PropertyRootExistedBefore || !_ArgZeroIsConfigurationRootDirectory) personContainers = Array.Empty(); else @@ -268,6 +270,7 @@ public partial class DlibDotNet configuration.MappingDefaultName, configuration.PersonBirthdayFirstYear, configuration.PersonBirthdayFormat, + configuration.PhotoPrismDirectory, configuration.RangeDaysDeltaTolerance, configuration.RangeDistanceTolerance, configuration.SortingMaximumPerKey, @@ -278,7 +281,7 @@ public partial class DlibDotNet return result; } - private void FullParallelForWork(A_Property propertyLogic, Dictionary> idToMappedFaceFilesCollection, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string? eDistanceContentDirectory, List> sourceDirectoryChanges, List propertyFileHolderCollection, List propertyCollection, List>> metadataCollections, List> resizeKeyValuePairs, List> imageFaceCollections, Container container, int index, Item item) + private void FullParallelForWork(A_Property propertyLogic, Dictionary> idToMappedFaceFilesCollection, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsDateGroupDirectory, string dResultsFullGroupDirectory, string? eDistanceContentDirectory, List> sourceDirectoryChanges, List propertyFileHolderCollection, List propertyCollection, List>> metadataCollections, List> resizeKeyValuePairs, List> imageFaceCollections, Container container, int index, Item item, DateTime[] containerDateTimes) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); @@ -291,19 +294,18 @@ public partial class DlibDotNet Dictionary imageResizeKeyValuePairs; List> subFileTuples = new(); List> metadataCollection; - if (item.Property is null || item.Property.Id is null) + Dictionary> relativeLocations; + if (item.Property is not null && item.Property.Id is not null && !item.Any()) { - property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions); - item.Update(property); - if (subFileTuples.Any()) - { - lock (sourceDirectoryChanges) - sourceDirectoryChanges.Add(new Tuple(nameof(A_Property), (from l in subFileTuples select l.Item2).Max())); - } + property = item.Property; + if (item.SourceDirectoryFileHolder.LastWriteTime is not null) + subFileTuples.Add(new Tuple(nameof(A_Property), item.SourceDirectoryFileHolder.LastWriteTime.Value)); + else + subFileTuples.Add(new Tuple(nameof(A_Property), new FileInfo(item.SourceDirectoryFileHolder.FullName).LastWriteTime)); } else { - property = item.Property; + int? propertyHashCode = item.Property?.GetHashCode(); if (item.Abandoned.HasValue && item.Abandoned.Value) _Log.Information(string.Concat("Abandoned <", item.ImageFileHolder.FullName, '>')); else if (item.FileSizeChanged.HasValue && item.FileSizeChanged.Value) @@ -312,13 +314,26 @@ public partial class DlibDotNet _Log.Information(string.Concat("LastWriteTimeChanged <", item.ImageFileHolder.FullName, '>')); else if (item.Moved.HasValue && item.Moved.Value) _Log.Information(string.Concat("Moved <", item.ImageFileHolder.FullName, '>')); + property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions); + item.Update(property); + if (propertyHashCode is null) + { + lock (sourceDirectoryChanges) + sourceDirectoryChanges.Add(new Tuple(nameof(A_Property), DateTime.Now)); + } + else if (propertyHashCode.Value != property.GetHashCode()) + { + lock (sourceDirectoryChanges) + sourceDirectoryChanges.Add(new Tuple(nameof(A_Property), DateTime.Now)); + } } if (property is null || item.Property is null) throw new NullReferenceException(nameof(property)); FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(item); item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder); - string facesDirectory = _Faces.GetFacesDirectory(dResultsFullGroupDirectory, item); - MappingFromItem mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(item, resizedFileHolder); + string facesDirectory = _Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution) ? _Faces.GetFacesDirectory(dResultsFullGroupDirectory, item) : string.Empty; + string facePartsDirectory = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution) ? _FaceParts.GetFacePartsDirectory(_Configuration.PropertyConfiguration, dResultsFullGroupDirectory, item) : string.Empty; + MappingFromItem mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); (int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection)); @@ -343,28 +358,29 @@ public partial class DlibDotNet faces = new(); else { + List<(string, int)>? collection; int[] outputResolutionCollection = imageResizeKeyValuePairs[outputResolution]; int outputResolutionWidth = outputResolutionCollection[0]; int outputResolutionHeight = outputResolutionCollection[1]; int outputResolutionOrientation = outputResolutionCollection[2]; faces = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); + relativeLocations = _Faces.GetRelativeLocations(outputResolution, dResultsDateGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, original, imageResizeKeyValuePairs, faces); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.GetFaces)); bool anyFacesSaved = _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, facesDirectory, faces); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.SaveFaces)); - if (!anyFacesSaved && item.Property?.Id is not null - && idToMappedFaceFilesCollection.TryGetValue(item.Property.Id.Value, out List<(string, int)>? collection)) + if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) + && !anyFacesSaved && item.Property?.Id is not null + && idToMappedFaceFilesCollection.TryGetValue(item.Property.Id.Value, out collection)) _Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, eDistanceContentDirectory, mappingFromItem, faces, collection); if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) { - throw new NotImplementedException(); - // bool saveRotated = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution); - // string sourceDirectorySegment = Property.Models.Stateless.IResult.GetRelativePath(_Configuration.PropertyConfiguration, container.SourceDirectory); - // string facePartsDirectoryX = Path.GetFullPath(Path.Combine($"{Path.Combine(d2FacePartsContentDirectory, "()")}{sourceDirectorySegment}", item.ImageFileHolder.NameWithoutExtension)); - // _FaceParts.SaveFaceLandmarkImages(facesDirectory, subFileTuples, parseExceptions, item, faceCollection, saveRotated); - // if (_AppSettings.MaxDegreeOfParallelism < 2) - // ticks = LogDelta(ticks, nameof(D2_FaceParts.SaveFaceLandmarkImages)); + bool saveRotated = !_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution); + string sourceDirectorySegment = Property.Models.Stateless.IResult.GetRelativePath(_Configuration.PropertyConfiguration, container.SourceDirectory); + _FaceParts.SaveFaceLandmarkImages(_Configuration.PropertyConfiguration, facePartsDirectory, subFileTuples, parseExceptions, mappingFromItem, faces, saveRotated); + if (_AppSettings.MaxDegreeOfParallelism < 2) + ticks = LogDelta(ticks, nameof(D2_FaceParts.SaveFaceLandmarkImages)); } } lock (sourceDirectoryChanges) @@ -384,6 +400,7 @@ public partial class DlibDotNet string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, + string dResultsDateGroupDirectory, string dResultsFullGroupDirectory, string? eDistanceContentDirectory, List> sourceDirectoryChanges, @@ -415,6 +432,7 @@ public partial class DlibDotNet propertyFileHolderCollection.Add(null); } } + DateTime[] containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems); using ProgressBar progressBar = new(filteredItems.Length, message, options); _ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) => { @@ -426,6 +444,7 @@ public partial class DlibDotNet outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, + dResultsDateGroupDirectory, dResultsFullGroupDirectory, eDistanceContentDirectory, sourceDirectoryChanges, @@ -436,7 +455,8 @@ public partial class DlibDotNet imageFaceCollections, container, index: i, - filteredItems[i]); + filteredItems[i], + containerDateTimes); if (i == 0 || sourceDirectoryChanges.Any()) progressBar.Tick(); } @@ -559,7 +579,7 @@ public partial class DlibDotNet } } - private (string, string, string, string) GetResultsFullGroupDirectories(string outputResolution) + private (string, string, string, string, string) GetResultsFullGroupDirectories(string outputResolution) { string aResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( _Configuration.PropertyConfiguration, @@ -589,7 +609,14 @@ public partial class DlibDotNet includeResizeGroup: true, includeModel: true, includePredictorModel: true); - return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory); + string d2ResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( + _Configuration.PropertyConfiguration, + nameof(D2_FaceParts), + outputResolution, + includeResizeGroup: true, + includeModel: true, + includePredictorModel: true); + return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory); } private void SetAngleBracketCollections(A_Property propertyLogic, Container container, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory) @@ -599,20 +626,6 @@ public partial class DlibDotNet _Metadata.SetAngleBracketCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, container.SourceDirectory); } - private Item[] GetFilterItems(Container container) - { - List results = new(); - foreach (Item item in container.Items) - { - if (item.ImageFileHolder is not null - && (item.Abandoned is null || !item.Abandoned.Value) - && item.ValidImageFormatExtension - && !_Configuration.IgnoreExtensions.Contains(item.ImageFileHolder.ExtensionLowered)) - results.Add(item); - } - return results.ToArray(); - } - private void FullDoWork(string argZero, string propertyRoot, long ticks, A_Property propertyLogic, int t, Container[] containers, string? eDistanceContentDirectory, Dictionary> idToMappedFaceFilesCollection) { if (_Log is null) @@ -627,6 +640,7 @@ public partial class DlibDotNet string bResultsFullGroupDirectory; string cResultsFullGroupDirectory; string dResultsFullGroupDirectory; + string d2ResultsFullGroupDirectory; int containersLength = containers.Length; Shared.Models.Property[] propertyCollection; List propertyFileHolderCollection = new(); @@ -636,10 +650,12 @@ public partial class DlibDotNet int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism; List nullablePropertyCollection = new(); List>> metadataCollection = new(); + string dResultsDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D_Face)); foreach (string outputResolution in _Configuration.OutputResolutions) { total = 0; - (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution); + (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution); + // _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(dResultsFullGroupDirectory); for (int i = 0; i < containers.Length; i++) { container = containers[i]; @@ -647,7 +663,7 @@ public partial class DlibDotNet continue; if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) continue; - filteredItems = GetFilterItems(container); + filteredItems = Shared.Models.Stateless.Methods.IContainer.GetFilterItems(_Configuration.PropertyConfiguration, container); if (!filteredItems.Any()) continue; metadataCollection.Clear(); @@ -660,6 +676,8 @@ public partial class DlibDotNet message = $"{i + 1:000}.{container.G} [{filteredItems.Length:000} files] / {containersLength:000} - {total} / {t} total files - {totalSeconds} total second(s) - {outputResolution} - {container.SourceDirectory}"; if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) _Faces.SetAngleBracketCollection(dResultsFullGroupDirectory, container.SourceDirectory); + if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) + _FaceParts.SetAngleBracketCollection(_Configuration.PropertyConfiguration, d2ResultsFullGroupDirectory, container.SourceDirectory); SetAngleBracketCollections(propertyLogic, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory); exceptionCount = FullParallelWork( maxDegreeOfParallelism, @@ -668,6 +686,7 @@ public partial class DlibDotNet outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, + dResultsDateGroupDirectory, dResultsFullGroupDirectory, eDistanceContentDirectory, sourceDirectoryChanges, @@ -718,37 +737,56 @@ public partial class DlibDotNet } } - private bool IsIgnoreRelativePath(string directory) + private void SetMapping(string argZero, Container[] containers) { - bool result = false; - string? checkDirectory = Path.GetFullPath(directory); - for (int i = 0; i < int.MaxValue; i++) - { - if (_Configuration.IgnoreRelativePaths.Contains(Path.GetFileName(checkDirectory))) - { - result = true; - break; - } - checkDirectory = Path.GetDirectoryName(checkDirectory); - if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == _Configuration.PropertyConfiguration.RootDirectory) - break; - } - return result; - } - - private (List, Shared.Models.Face[]) SetMappingThenGetDistinctFilteredFacesWithMapping(string argZero, Container[] containers) - { - List items = new(); - Shared.Models.Face[] faces; Mapping mapping; int faceAreaPermille; Item[] filteredItems; int confidencePercent; - List distinct = new(); - int normalizedPixelPercentage; + int normalizedRectangle; + bool isIgnoreRelativePath; + DateTime[] containerDateTimes; string deterministicHashCodeKey; MappingFromItem mappingFromItem; MappingFromLocation mappingFromLocation; + foreach (Container container in containers) + { + if (!container.Items.Any()) + continue; + if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) + continue; + filteredItems = Shared.Models.Stateless.Methods.IContainer.GetFilterItems(_Configuration.PropertyConfiguration, container); + if (!filteredItems.Any()) + continue; + containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems); + isIgnoreRelativePath = _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory); + foreach (Item item in filteredItems) + { + if (item.Property?.Id is null || item.ResizedFileHolder is null) + continue; + mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item); + foreach (Shared.Models.Face face in item.Faces) + { + if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) + continue; + confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence); + faceAreaPermille = Shared.Models.Stateless.Methods.IMapping.GetAreaPermille(_Configuration.FaceAreaPermille, face.Location, face.OutputResolution); + normalizedRectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); + deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); + mappingFromLocation = new(faceAreaPermille, confidencePercent, deterministicHashCodeKey, normalizedRectangle); + mapping = new(mappingFromItem, mappingFromLocation); + face.SetMapping(mapping); + } + } + } + } + + private Shared.Models.Face[] GetFilteredDistinctFaces(string argZero, Container[] containers) + { + Shared.Models.Face[] results; + Item[] filteredItems; + bool isIgnoreRelativePath; + List distinct = new(); List collection = new(); foreach (Container container in containers) { @@ -756,11 +794,10 @@ public partial class DlibDotNet continue; if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) continue; - if (_Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && IsIgnoreRelativePath(container.SourceDirectory)) - continue; - filteredItems = GetFilterItems(container); + filteredItems = Shared.Models.Stateless.Methods.IContainer.GetFilterItems(_Configuration.PropertyConfiguration, container); if (!filteredItems.Any()) continue; + isIgnoreRelativePath = _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory); foreach (Item item in filteredItems) { if (item.Property?.Id is null || item.ResizedFileHolder is null) @@ -768,38 +805,55 @@ public partial class DlibDotNet if (distinct.Contains(item.Property.Id.Value)) continue; distinct.Add(item.Property.Id.Value); - if (!item.Faces.Any(l => l.FaceEncoding is not null && l.Location is not null && l.OutputResolution is not null)) - { - items.Add(item); + if (isIgnoreRelativePath) continue; - } - mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(item); foreach (Shared.Models.Face face in item.Faces) { if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) continue; - confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence); - faceAreaPermille = Shared.Models.Stateless.Methods.IMapping.GetAreaPermille(_Configuration.FaceAreaPermille, face.Location, face.OutputResolution); - normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); - deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); - mappingFromLocation = new(faceAreaPermille, confidencePercent, deterministicHashCodeKey, normalizedPixelPercentage); - mapping = new(mappingFromItem, mappingFromLocation); - face.SetMapping(mapping); collection.Add(face); } } } - faces = (from l in collection orderby l.Mapping?.MappingFromItem.Id select l).ToArray(); - return new(items, faces); + results = (from l in collection orderby l.Mapping?.MappingFromItem.Id select l).ToArray(); + return results; } - private void MapLogic(string argZero, long ticks, PersonContainer[] personContainers, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2FacePartsContentDirectory, string eDistanceContentDirectory, string outputResolution) + private List GetItems(string argZero, Container[] containers) + { + List items = new(); + Item[] filteredItems; + bool isIgnoreRelativePath; + List collection = new(); + foreach (Container container in containers) + { + if (!container.Items.Any()) + continue; + if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) + continue; + filteredItems = Shared.Models.Stateless.Methods.IContainer.GetFilterItems(_Configuration.PropertyConfiguration, container); + if (!filteredItems.Any()) + continue; + isIgnoreRelativePath = _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory); + foreach (Item item in filteredItems) + { + if (item.Property?.Id is null || item.ResizedFileHolder is null) + continue; + items.Add(item); + } + } + return items; + } + + private void MapLogic(string argZero, long ticks, PersonContainer[] personContainers, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string eDistanceContentDirectory, string outputResolution) { int? useFiltersCounter = null; SortingContainer[] sortingContainers; string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()"); - (List filteredItems, Shared.Models.Face[] distinctFilteredFaces) = SetMappingThenGetDistinctFilteredFacesWithMapping(argZero, containers); + string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, "()"); + Shared.Models.Face[] distinctFilteredFaces = GetFilteredDistinctFaces(argZero, containers); Mapping[] mappingCollection = MapLogicSupport.GetSelectedMappingCollection(distinctFilteredFaces); + string dFacesCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.PropertyConfiguration.ResultAllInOne); MapLogicSupport mapLogicSupport = new( _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, @@ -816,33 +870,50 @@ public partial class DlibDotNet eDistanceContentDirectory, mappingCollection, mapLogicSupport); - Dictionary> idToNormalizedPixelPercentageToMapping = MapLogicSupport.GetIdToNormalizedPixelPercentageToFace(mappingCollection); - mapLogic.CopyManualFiles(dFacesContentDirectory, idToNormalizedPixelPercentageToMapping); - if (_Configuration.SaveNotMappedForOutputResolutions.Contains(outputResolution)) - mapLogic.CopyNotMappedFaces(_Configuration.RangeFaceAreaPermilleTolerance, dFacesContentDirectory, idToNormalizedPixelPercentageToMapping); (Dictionary personKeyToCount, int totalNotMapped) = mapLogic.AddToMapping(mappingCollection); + if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution) || (!string.IsNullOrEmpty(_Configuration.PhotoPrismDirectory) && Directory.Exists(_Configuration.PhotoPrismDirectory))) + { + List filteredItems = GetItems(argZero, containers); + if (!string.IsNullOrEmpty(_Configuration.PhotoPrismDirectory)) + { + mapLogic.SaveMarkers(); + mapLogic.FindMatch(filteredItems); + mapLogic.LoadMatches(); + } + if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) + mapLogic.SaveShortcutsForOutputResolutions(filteredItems, mappingCollection, personKeyToCount); + } + Dictionary> idToNormalizedRectangleToMapping = MapLogicSupport.GetIdToNormalizedRectangleToFace(mappingCollection); + mapLogic.CopyManualFiles(dFacesContentDirectory, idToNormalizedRectangleToMapping); + if (_Configuration.SaveNotMappedForOutputResolutions.Contains(outputResolution)) + mapLogic.CopyNotMappedFaces(_Configuration.RangeFaceAreaPermilleTolerance, dFacesContentDirectory, idToNormalizedRectangleToMapping); if (_Configuration.SaveMappedForOutputResolutions.Contains(outputResolution)) - mapLogic.SaveMapped(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedPixelPercentageToMapping, personKeyToCount, totalNotMapped); - if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) - mapLogic.SaveShortcuts(a2PeopleSingletonDirectory, personContainers, filteredItems, mappingCollection, personKeyToCount); + mapLogic.SaveMapped(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedRectangleToMapping, personKeyToCount, totalNotMapped); if (_Configuration.SaveResizedImagesByPersonKeyFormattedForOutputResolutions.Contains(outputResolution)) mapLogic.SaveResizedImagesByPersonKeyFormatted(_Configuration.JLinks, a2PeopleSingletonDirectory, personContainers, mappingCollection, personKeyToCount, totalNotMapped); if (_Configuration.SaveFaceDistancesForOutputResolutions.Contains(outputResolution)) { MapLogicSupport.SetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, distinctFilteredFaces); - sortingContainers = mapLogicSupport.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, distinctFilteredFaces, useFiltersCounter); + Dictionary> missingIdThenNormalizedRectangleToPersonContainers = mapLogic.GetMissing(idToNormalizedRectangleToMapping); + List missingFaceDistanceContainers = _Distance.GetMissingFaceDistanceContainer(_AppSettings.MaxDegreeOfParallelism, ticks, dFacesCollectionDirectory, missingIdThenNormalizedRectangleToPersonContainers); + sortingContainers = mapLogicSupport.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, distinctFilteredFaces, missingFaceDistanceContainers, useFiltersCounter); if (!sortingContainers.Any()) { for (useFiltersCounter = 1; useFiltersCounter < 17; useFiltersCounter++) { - sortingContainers = mapLogicSupport.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, distinctFilteredFaces, useFiltersCounter); + sortingContainers = mapLogicSupport.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, distinctFilteredFaces, missingFaceDistanceContainers, useFiltersCounter); if (sortingContainers.Any()) break; } } MapLogicSupport.SaveFaceDistances(_Configuration.PropertyConfiguration, sortingContainers); if (totalNotMapped > 0) - mapLogic.UpdateFromSortingContainersThenSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedPixelPercentageToMapping, useFiltersCounter, sortingContainers, totalNotMapped); + { + bool saveNullPerson = !personKeyToCount.Any(); + int updated = mapLogic.UpdateFromSortingContainers(sortingContainers, saveNullPerson); + List saveContainers = mapLogic.GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedRectangleToMapping, useFiltersCounter, saveNullPerson); + mapLogic.SaveContainers(totalNotMapped, updated, saveContainers); + } } if (_Configuration.SaveNotMappedForOutputResolutions.Contains(outputResolution)) mapLogic.SaveNotMappedTicks(); @@ -886,6 +957,7 @@ public partial class DlibDotNet string fileName; Task task; string relativePath; + FileHolder fileHolder; string extensionLowered; string sourceDirectoryFile; int length = result.Length; @@ -907,7 +979,8 @@ public partial class DlibDotNet extensionLowered = Path.GetExtension(uri.LocalPath); relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFile, length, forceExtensionToLower: true); isValidImageFormatExtension = _Configuration.PropertyConfiguration.ValidImageFormatExtensions.Contains(extensionLowered); - item = new(sourceDirectoryFile, relativePath, isValidImageFormatExtension); + fileHolder = new(sourceDirectoryFile); + item = new(fileHolder, relativePath, isValidImageFormatExtension); container.Items.Add(item); } _Log.Information(". . ."); @@ -918,21 +991,23 @@ public partial class DlibDotNet { List results = new(); Item[] filteredItems; + DateTime[] containerDateTimes; MappingFromItem mappingFromItem; foreach (Container container in containers) { if (!container.Items.Any()) continue; - if (_Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && IsIgnoreRelativePath(container.SourceDirectory)) + if (_Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory)) continue; - filteredItems = GetFilterItems(container); + filteredItems = Shared.Models.Stateless.Methods.IContainer.GetFilterItems(_Configuration.PropertyConfiguration, container); if (!filteredItems.Any()) continue; + containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems); foreach (Item item in filteredItems) { if (item.Property?.Id is null) continue; - mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(item); + mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item); results.Add(mappingFromItem); } } @@ -951,8 +1026,8 @@ public partial class DlibDotNet string cResultsFullGroupDirectory; string dResultsFullGroupDirectory; string? eDistanceContentDirectory; + string d2ResultsFullGroupDirectory; string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "{}"); - string d2FacePartsContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D2_FaceParts), "()"); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") Building Container(s) - {totalSeconds} total second(s)"; A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse); @@ -970,24 +1045,29 @@ public partial class DlibDotNet } else { + string resultsGroupDirectory; a2PeopleContentDirectory = null; eDistanceContentDirectory = null; string? newRootDirectory = SaveUrlAndGetNewRootDirectory(container); for (int i = 1; i < 10; i++) - _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true)); + { + resultsGroupDirectory = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true); + _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(resultsGroupDirectory); + } argZero = newRootDirectory; _Configuration.PropertyConfiguration.ChangeRootDirectory(newRootDirectory); propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false); propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse); } Dictionary> idToMappedFaceFilesCollection = Map.Models.Stateless.Methods.IMapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(_MapConfiguration, ticks, a2PeopleContentDirectory, eDistanceContentDirectory, personContainers); + containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers); FullDoWork(argZero, propertyRoot, ticks, propertyLogic, t, containers, eDistanceContentDirectory, idToMappedFaceFilesCollection); _Distance.Clear(); foreach (string outputResolution in _Configuration.OutputResolutions) { if (_PropertyRootExistedBefore || container is not null) break; - (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution); + (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution); if (_Configuration.SaveResizedImagesByPersonKeyFormattedForOutputResolutions.Contains(outputResolution)) MapLogicSupport.BeforeSaveResizedImagesByPersonKeyFormatted(_Configuration.JLinks, a2PeopleSingletonDirectory); if (_ArgZeroIsConfigurationRootDirectory @@ -999,7 +1079,8 @@ public partial class DlibDotNet { if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any()) break; - MapLogic(argZero, ticks, personContainers, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2FacePartsContentDirectory, eDistanceContentDirectory, outputResolution); + SetMapping(argZero, containers); + MapLogic(argZero, ticks, personContainers, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eDistanceContentDirectory, outputResolution); if (_IsEnvironment.Development) continue; List mappingFromItemCollection = GetMappingFromItemCollection(containers); diff --git a/Instance/Instance.csproj b/Instance/Instance.csproj index 029048a..cdbea44 100644 --- a/Instance/Instance.csproj +++ b/Instance/Instance.csproj @@ -34,12 +34,12 @@ - + - + - + diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index a71d6d1..731bca2 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -50,6 +50,7 @@ public class Configuration [Display(Name = "Person Birthday First Year"), Required] public int? PersonBirthdayFirstYear { get; set; } [Display(Name = "Person Birthday Format"), Required] public string PersonBirthdayFormat { get; set; } [Display(Name = "PersonKey Format"), Required] public string PersonKeyFormat { get; set; } + [Display(Name = "Photo-Prism Directory"), Required] public string PhotoPrismDirectory { get; set; } [Display(Name = "Predictor Model Name"), Required] public string PredictorModelName { get; set; } [Display(Name = "Properties Changed For Distance"), Required] public bool? PropertiesChangedForDistance { get; set; } [Display(Name = "Properties Changed For Faces"), Required] public bool? PropertiesChangedForFaces { get; set; } @@ -58,10 +59,10 @@ public class Configuration [Display(Name = "Properties Changed For Resize"), Required] public bool? PropertiesChangedForResize { get; set; } [Display(Name = "Property Configuration"), Required] public Property.Models.Configuration PropertyConfiguration { get; set; } [Display(Name = "Sorting Days Delta Tolerance"), Required] public int[] RangeDaysDeltaTolerance { get; set; } + [Display(Name = "Face Distance Tolerance"), Required] public double[] RangeDistanceTolerance { get; set; } [Display(Name = "Face Area Permille Tolerance"), Required] public int[] RangeFaceAreaPermilleTolerance { get; set; } [Display(Name = "Location Minimum Confidence"), Required] public double[] RangeFaceConfidence { get; set; } - [Display(Name = "Face Distance Tolerance"), Required] public double[] RangeDistanceTolerance { get; set; } - [Display(Name = "Retry Images Without a Face"), Required] public bool? RetryImagesWithoutAFace { get; set; } + [Display(Name = "Retry Images Without a Face"), Required] public bool? RetryImagesWithoutAFaceLocation { get; set; } [Display(Name = "Reverse"), Required] public bool? Reverse { get; set; } [Display(Name = "Save Face Distances"), Required] public string[] SaveFaceDistancesForOutputResolutions { get; set; } [Display(Name = "Save Face Landmark For Output Resolutions"), Required] public string[] SaveFaceLandmarkForOutputResolutions { get; set; } @@ -159,6 +160,8 @@ public class Configuration throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat)); if (configuration.PersonKeyFormat is null) throw new NullReferenceException(nameof(configuration.PersonKeyFormat)); + if (configuration.PhotoPrismDirectory is null) + throw new NullReferenceException(nameof(configuration.PhotoPrismDirectory)); if (configuration.PropertiesChangedForDistance is null) throw new NullReferenceException(nameof(configuration.PropertiesChangedForDistance)); if (configuration.PropertiesChangedForFaces is null) @@ -177,8 +180,8 @@ public class Configuration throw new NullReferenceException(nameof(configuration.RangeFaceConfidence)); if (configuration.RangeDistanceTolerance is null || configuration.RangeDistanceTolerance.Length != 3) throw new NullReferenceException(nameof(configuration.RangeDistanceTolerance)); - if (configuration.RetryImagesWithoutAFace is null) - throw new NullReferenceException(nameof(configuration.RetryImagesWithoutAFace)); + if (configuration.RetryImagesWithoutAFaceLocation is null) + throw new NullReferenceException(nameof(configuration.RetryImagesWithoutAFaceLocation)); if (configuration.Reverse is null) throw new NullReferenceException(nameof(configuration.Reverse)); configuration.SaveFaceDistancesForOutputResolutions ??= Array.Empty(); @@ -235,8 +238,6 @@ public class Configuration configuration.MixedYearRelativePaths, configuration.ModelDirectory, configuration.ModelName, - configuration.NumberOfJitters.Value, - configuration.NumberOfTimesToUpsample.Value, configuration.OutputExtension, configuration.OutputQuality.Value, configuration.OutputResolutions, @@ -246,6 +247,7 @@ public class Configuration configuration.PersonBirthdayFirstYear.Value, configuration.PersonBirthdayFormat, configuration.PersonKeyFormat, + configuration.PhotoPrismDirectory, configuration.PredictorModelName, configuration.PropertiesChangedForDistance.Value, configuration.PropertiesChangedForFaces.Value, @@ -256,7 +258,7 @@ public class Configuration configuration.RangeFaceAreaPermilleTolerance, configuration.RangeFaceConfidence, configuration.RangeDistanceTolerance, - configuration.RetryImagesWithoutAFace.Value, + configuration.RetryImagesWithoutAFaceLocation.Value, configuration.Reverse.Value, configuration.SaveFaceDistancesForOutputResolutions, configuration.SaveFaceLandmarkForOutputResolutions, @@ -289,9 +291,7 @@ public class Configuration configuration = configurationSection.Get(); } result = Get(configuration); - if (configuration is null) - throw new NullReferenceException(nameof(configuration)); - result.SetAndUpdate(propertyConfiguration, configuration.NumberOfJitters, configuration.NumberOfTimesToUpsample, configuration.ModelName, configuration.PredictorModelName); + result.SetAndUpdate(propertyConfiguration, configuration?.NumberOfJitters, configuration?.NumberOfTimesToUpsample, configuration?.ModelName, configuration?.PredictorModelName); return result; } diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index bb3cf3e..e7da88a 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -38,8 +38,6 @@ public class Configuration public string[] MixedYearRelativePaths { init; get; } public string ModelDirectory { init; get; } public string ModelName { init; get; } - public int NumberOfJitters { init; get; } - public int NumberOfTimesToUpsample { init; get; } public string OutputExtension { init; get; } public int OutputQuality { init; get; } public string[] OutputResolutions { init; get; } @@ -49,6 +47,7 @@ public class Configuration public int PersonBirthdayFirstYear { init; get; } public string PersonBirthdayFormat { init; get; } public string PersonKeyFormat { init; get; } + public string PhotoPrismDirectory { init; get; } public string PredictorModelName { init; get; } public bool PropertiesChangedForDistance { init; get; } public bool PropertiesChangedForFaces { init; get; } @@ -59,7 +58,7 @@ public class Configuration public int[] RangeFaceAreaPermilleTolerance { init; get; } public double[] RangeFaceConfidence { init; get; } public double[] RangeDistanceTolerance { init; get; } - public bool RetryImagesWithoutAFace { init; get; } + public bool RetryImagesWithoutAFaceLocation { init; get; } public bool Reverse { init; get; } public string[] SaveFaceDistancesForOutputResolutions { init; get; } public string[] SaveFaceLandmarkForOutputResolutions { init; get; } @@ -107,8 +106,6 @@ public class Configuration string[] mixedYearRelativePaths, string modelDirectory, string modelName, - int numberOfJitters, - int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, @@ -118,6 +115,7 @@ public class Configuration int personBirthdayFirstYear, string personBirthdayFormat, string personKeyFormat, + string photoPrismDirectory, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, @@ -128,7 +126,7 @@ public class Configuration int[] rangeFaceAreaPermilleTolerance, double[] rangeFaceConfidence, double[] rangeDistanceTolerance, - bool retryImagesWithoutAFace, + bool retryImagesWithoutAFaceLocation, bool reverse, string[] saveFaceDistancesForOutputResolutions, string[] saveFaceLandmarkForOutputResolutions, @@ -175,8 +173,6 @@ public class Configuration MixedYearRelativePaths = mixedYearRelativePaths; ModelDirectory = modelDirectory; ModelName = modelName; - NumberOfJitters = numberOfJitters; - NumberOfTimesToUpsample = numberOfTimesToUpsample; OutputExtension = outputExtension; OutputQuality = outputQuality; OutputResolutions = outputResolutions; @@ -186,6 +182,7 @@ public class Configuration PersonBirthdayFirstYear = personBirthdayFirstYear; PersonBirthdayFormat = personBirthdayFormat; PersonKeyFormat = personKeyFormat; + PhotoPrismDirectory = photoPrismDirectory; PredictorModelName = predictorModelName; PropertiesChangedForDistance = propertiesChangedForDistance; PropertiesChangedForFaces = propertiesChangedForFaces; @@ -196,7 +193,7 @@ public class Configuration RangeFaceAreaPermilleTolerance = rangeFaceAreaPermilleTolerance; RangeFaceConfidence = rangeFaceConfidence; RangeDistanceTolerance = rangeDistanceTolerance; - RetryImagesWithoutAFace = retryImagesWithoutAFace; + RetryImagesWithoutAFaceLocation = retryImagesWithoutAFaceLocation; Reverse = reverse; SaveFaceDistancesForOutputResolutions = saveFaceDistancesForOutputResolutions; SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions; diff --git a/Instance/Models/_G_Index.cs b/Instance/Models/_G_Index.cs index 38ef6f5..a9e9bb1 100644 --- a/Instance/Models/_G_Index.cs +++ b/Instance/Models/_G_Index.cs @@ -145,7 +145,6 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex Dictionary>> filePropertiesKeyValuePairs = new(); FileInfo fileInfo; G_Index indexInfo; - string parentCheck; List indices = new(); Dictionary valuePairs; List directoryInfoCollection; @@ -170,14 +169,6 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex foreach (Tuple tuple in tuples.Value) { fileInfo = new FileInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "{}"), string.Concat(Path.GetFileNameWithoutExtension(tuple.Item1), ".json"))); - if (!fileInfo.FullName.Contains(configuration.ResultAllInOne) && !fileInfo.Exists) - { - if (fileInfo.Directory?.Parent is null) - throw new Exception(); - parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name); - if (File.Exists(parentCheck)) - File.Delete(parentCheck); - } if (_Configuration.PropertiesChangedForIndex) indexInfo = null; else if (!fileInfo.Exists) diff --git a/Instance/Program.cs b/Instance/Program.cs index b2edc0b..285e643 100644 --- a/Instance/Program.cs +++ b/Instance/Program.cs @@ -18,6 +18,7 @@ public class Program IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); IConfigurationRoot configurationRoot = configurationBuilder.Build(); AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); diff --git a/Instance/appsettings.Development.json b/Instance/appsettings.Development.json index 8dfd976..cc5c080 100644 --- a/Instance/appsettings.Development.json +++ b/Instance/appsettings.Development.json @@ -1,129 +1,23 @@ { - "Company": "Mike Phares", - "Linux": {}, "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Log4netProvider": "Debug", - "Microsoft.Hosting.Lifetime": "Information" + "Log4netProvider": "Debug" } }, "MaxDegreeOfParallelism": 6, "Serilog": { - "Using": [ - "Serilog.Sinks.Console", - "Serilog.Sinks.File" - ], - "MinimumLevel": "Debug", - "WriteTo": [ - { - "Name": "Debug", - "Args": { - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" - } - }, - { - "Name": "Console", - "Args": { - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" - } - }, - { - "Name": "File", - "Args": { - "path": "%workingDirectory% - Log/log-.txt", - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}", - "rollingInterval": "Hour" - } - } - ], - "Enrich": [ - "FromLogContext", - "WithMachineName", - "WithThreadId" - ], - "Properties": { - "Application": "Sample" - } + "MinimumLevel": "Debug" }, - "WorkingDirectoryName": "PharesApps", "Windows": { "Configuration": { - "CheckDFaceAndUpWriteDates": true, - "CheckJsonForDistanceResults": false, - "CrossDirectoryMaxItemsInDistanceCollection": 7, - "DateGroup": "2022-11-12", - "DistanceFactor": 8, - "DistanceMoveUnableToMatch": false, - "DistancePixelDistanceTolerance": 1, - "DistanceRenameToMatch": false, - "FaceAreaPermille": 1000, - "FaceDistanceHiddenImageFactor": 2, - "FaceConfidencePercent": 100, - "FaceDistancePermyriad": 10000, - "FileNameDirectorySeparator": ".Z.", - "ForceFaceLastWriteTimeToCreationTime": false, - "ForceMetadataLastWriteTimeToCreationTime": false, - "ForcePropertyLastWriteTimeToCreationTime": false, - "ForceResizeLastWriteTimeToCreationTime": false, - "LoadOrCreateThenSaveIndex": false, - "LocationDigits": 9, - "LocationFactor": 10000, - "MappedMaxIndex": 1034720, - "MappingDefaultName": "John Doe~25", - "MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping": false, - "MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping": false, - "MaxImagesInDirectoryForTopLevelFirstPass": 10, - "ModelDirectory": "C:/GitHub/dlib-models", - "ModelName": "Hog", - "NumberOfJitters": 0, - "NumberOfTimesToUpsample": 0, - "OutputExtension": ".jpg", - "OutputQuality": 95, - "OverrideForFaceImages": false, - "OverrideForFaceLandmarkImages": false, - "OverrideForResizeImages": false, - "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", - "PersonBirthdayFirstYear": 1500, - "PersonBirthdayFormat": "yyyy-MM-dd_HH", - "PersonKeyFormat": "yyyy-MM-dd_HH", - "PersonRequirePeopleFile": true, - "PopulatePropertyId": true, - "PredictorModelName": "Large", - "PropertiesChangedForDistance": false, - "PropertiesChangedForFaces": false, - "PropertiesChangedForIndex": false, - "PropertiesChangedForMetadata": false, - "PropertiesChangedForProperty": false, - "PropertiesChangedForResize": false, - "ResultAllInOne": "_ _ _", - "ResultCollection": "[]", - "ResultContent": "()", - "ResultSingleton": "{}", - "RetryImagesWithoutAFace": false, - "Reverse": false, + "PhotoPrismDirectory": "G:/photo-prism/Not-Copy-Copy-All/phpMyAdmin/export", "xRootDirectory": "C:/Tmp/phares/Pictures", - "RootDirectory": "F:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8 - III", - "xxRootDirectory": "F:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8 - III/Facebook/=2022.3 Facebook", - "SaveFullYearOfRandomFiles": true, - "SaveResizedSubFiles": true, - "SkipSearch": false, - "SortingMaximumPerFaceShouldBeHigh": 3000, - "SortingMaximumPerKey": 7, - "SortingMinimumToUseSigma": 10, - "TestDistanceResults": true, - "WriteBitmapDataBytes": false, - "IgnoreExtensions": [ - ".gif", - ".GIF" - ], + "xxRootDirectory": "F:/Tmp/Phares/Compare/Not-Copy-Copy-All", + "RootDirectory": "F:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8", + "xxxxRootDirectory": "F:/Tmp/Phares/Compare/Images 2022-11-12 - c6aa7e8/Facebook/=2022.3 Facebook", "JLinks": [ "Julie" ], - "LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions": [ - "7680 x 4320" - ], "LoadOrCreateThenSaveDistanceResultsForOutputResolutions": [ "7680 x 4320" ], @@ -136,17 +30,17 @@ "PropertyContentCollectionFiles": [], "RangeDaysDeltaTolerance": [ 0, - 700, + 2100, 123456 ], "RangeDistanceTolerance": [ 0, - 0.4, + 0.6, 0.6 ], "RangeFaceAreaPermilleTolerance": [ 0, - 10, + 3, 1000 ], "RangeFaceConfidence": [ @@ -154,72 +48,135 @@ 0.2, 100 ], - "SaveFaceLandmarkForOutputResolutions": [ - "176 x 176", - "256 x 256" + "SaveFaceDistancesForOutputResolutions": [ + "7680 x 4320" ], - "SaveFaceDistancesForOutputResolutions": [], + "SaveFaceLandmarkForOutputResolutions": [], "SaveMappedForOutputResolutions": [], "SaveNotMappedForOutputResolutions": [], "SaveResizedImagesByPersonKeyFormattedForOutputResolutions": [], - "SaveShortcutsForOutputResolutions": [ - "7680 x 4320" + "SaveShortcutsForOutputResolutions": [], + "IgnoreRelativePaths": [ + "3757 W Whitman 2017", + "501 Playful Meadows 2006", + "501 Playful Meadows 2007", + "501 Playful Meadows 2008", + "501 Playful Meadows 2009", + "501 Playful Meadows 2010", + "501 Playful Meadows 2013", + "501 Playful Meadows 2015", + "6309 Evesham 2003", + "6309 Evesham 2004", + "Crystal's Wedding 2003", + "Danny's Wedding 2009", + "Door images 2019", + "Family Pictures 2006", + "Family Pictures 2007", + "Family Pictures 2011", + "Family Pictures 2013", + "GrandPrix 2004", + "Kids School Pictures 2004", + "Kristy 2002", + "Kristy Parents Wedding 2005", + "Logan Ultrasound 2007", + "Mandy's Dogs 2008", + "Motorcycles 2010", + "Motorcycles 2013", + "Motorcycles 2014", + "Phares Slides", + "Portrait Innovations April 2008", + "Portrait Innovations December 2007", + "Portrait Innovations June 2008", + "Portrait Innovations March 2012", + "The guys house 2000", + "Tracy Pictures 2005", + "Tracy Pictures 2006", + "Tracy Pictures 2007", + "Tracy Pictures 2008", + "Tracy Pictures 2009", + "Tracy Pictures 2010", + "Tracy Pictures 2011", + "Tracy Pictures 2012", + "Tracy Pictures 2013 Jan-July", + "Tracy Pictures 2013 July- Dec", + "Tracy Pictures 2014", + "Tracy Pictures 2015", + "Tracy Took The Kids 2006", + "Tracy's Bday 2012", + "Tracy's Wedding 2002", + "Trip to Colorado 10 2002", + "Trip to Colorado June 2002", + "Tub 2002", + "Vericruz 2011", + "zzz =2005.1 Spring Tracy Pictures", + "zzz =2005.2 Summer Tracy Pictures", + "zzz =2005.3 Fall Tracy Pictures", + "zzz =2005.4 Winter Tracy Pictures", + "zzz =2006.1 Spring Tracy Pictures", + "zzz =2007.0 Winter Tracy Pictures", + "zzz =2007.2 Summer Tracy Pictures", + "zzz =2008.2 Summer Tracy Pictures", + "zzz =2009.0 Winter Tracy Pictures", + "zzz =2009.2 Summer Tracy Pictures", + "zzz =2009.3 Fall Tracy Pictures", + "zzz =2009.4 Winter Tracy Pictures", + "zzz =2010.0 Winter Tracy Pictures", + "zzz =2010.1 Spring Tracy Pictures", + "zzz =2010.2 Summer Tracy Pictures", + "zzz =2010.3 Fall Tracy Pictures", + "zzz =2011.0 Winter Tracy Pictures", + "zzz =2011.1 Spring Tracy Pictures", + "zzz =2011.2 Summer Tracy Pictures", + "zzz =2011.3 Fall Tracy Pictures", + "zzz =2011.4 Winter Tracy Pictures", + "zzz =2012.0 Winter Tracy Pictures", + "zzz =2012.1 Spring Tracy Pictures", + "zzz =2012.2 Summer Tracy Pictures", + "zzz =2012.3 Fall Tracy Pictures", + "zzz =2012.4 Winter Tracy Pictures", + "zzz =2013.0 Winter Tracy Pictures", + "zzz =2013.1 Spring Tracy Pictures", + "zzz =2013.2 Summer Tracy Pictures", + "zzz =2013.3 Fall Tracy Pictures", + "zzz =2013.4 Winter Tracy Pictures", + "zzz =2014.0 Winter Tracy Pictures", + "zzz =2014.1 Spring Tracy Pictures", + "zzz =2014.2 Summer Tracy Pictures", + "zzz =2014.3 Fall Tracy Pictures", + "zzz =2014.4 Winter Tracy Pictures", + "zzz =2015.0 Winter Tracy Pictures", + "zzz Family Pictures", + "zzz Family Pictures", + "zzz Family Pictures", + "zzz Family Pictures", + "zzz GrandPrix", + "zzz Motorcycles", + "zzz Motorcycles", + "zzz Motorcycles", + "zzz Parents Yard", + "zzz Phares Family Pictures", + "zzz Phares Slides ####", + "zzz Portrait Innovations April", + "zzz Portrait Innovations Files", + "zzz Portrait Innovations June", + "zzz Portrait Innovations March", + "zzz Rex Memorial ####", + "zzz Scanned Grandma's Quilt ####", + "zzz Scanned Pictures Of Kids ####", + "zzz Scanned Prints ####", + "zzz Slide in Name Order Originals (622) ####", + "zzz Tub", + "zzz Vericruz" ], - "ValidImageFormatExtensions": [ - ".bmp", - ".BMP", - ".gif", - ".GIF", - ".jpeg", - ".JPEG", - ".jpg", - ".JPG", - ".png", - ".PNG", - ".tiff", - ".TIFF" - ], - "ValidMetadataExtensions": [ - ".3gp", - ".3GP", - ".avi", - ".AVI", - ".bmp", - ".BMP", - ".gif", - ".GIF", - ".ico", - ".ICO", - ".jpeg", - ".JPEG", - ".jpg", - ".JPG", - ".m4v", - ".M4V", - ".mov", - ".MOV", - ".mp4", - ".MP4", - ".mta", - ".MTA", - ".png", - ".PNG", - ".tiff", - ".TIFF" - ], - "ValidResolutions": [ - "176 x 176", - "256 x 256", - "353 x 353", - "1024 x 768", - "1280 x 720", - "1280 x 800", - "1376 x 768", - "1600 x 1200", - "1920 x 1080", - "2256 x 1496", - "3840 x 2160", - "7680 x 4320" + "MixedYearRelativePaths": [ + "Edited", + "Phares Slides", + "Rex Memorial", + "Scanned Grandma's Quilt", + "Scanned Pictures Of Kids", + "Scanned Prints", + "Slide in Name Order Originals (622)", + "Slides Pictures" ], "VerifyToSeason": [ ". 2000", @@ -444,128 +401,6 @@ "zzz =2014.3 Fall Tracy Pictures", "zzz =2014.4 Winter Tracy Pictures", "zzz =2015.0 Winter Tracy Pictures" - ], - "MixedYearRelativePaths": [ - "Edited", - "Phares Slides", - "Rex Memorial", - "Scanned Grandma's Quilt", - "Scanned Pictures Of Kids", - "Scanned Prints", - "Slide in Name Order Originals (622)", - "Slides Pictures" - ], - "IgnoreRelativePaths": [ - "3757 W Whitman 2017", - "501 Playful Meadows 2006", - "501 Playful Meadows 2007", - "501 Playful Meadows 2008", - "501 Playful Meadows 2009", - "501 Playful Meadows 2010", - "501 Playful Meadows 2013", - "501 Playful Meadows 2015", - "6309 Evesham 2003", - "6309 Evesham 2004", - "Crystal's Wedding 2003", - "Danny's Wedding 2009", - "Door images 2019", - "Family Pictures 2006", - "Family Pictures 2007", - "Family Pictures 2011", - "Family Pictures 2013", - "GrandPrix 2004", - "Kids School Pictures 2004", - "Kristy 2002", - "Kristy Parents Wedding 2005", - "Logan Ultrasound 2007", - "Mandy's Dogs 2008", - "Motorcycles 2010", - "Motorcycles 2013", - "Motorcycles 2014", - "Phares Slides", - "Portrait Innovations April 2008", - "Portrait Innovations December 2007", - "Portrait Innovations June 2008", - "Portrait Innovations March 2012", - "The guys house 2000", - "Tracy Pictures 2005", - "Tracy Pictures 2006", - "Tracy Pictures 2007", - "Tracy Pictures 2008", - "Tracy Pictures 2009", - "Tracy Pictures 2010", - "Tracy Pictures 2011", - "Tracy Pictures 2012", - "Tracy Pictures 2013 Jan-July", - "Tracy Pictures 2013 July- Dec", - "Tracy Pictures 2014", - "Tracy Pictures 2015", - "Tracy Took The Kids 2006", - "Tracy's Bday 2012", - "Tracy's Wedding 2002", - "Trip to Colorado 10 2002", - "Trip to Colorado June 2002", - "Tub 2002", - "Vericruz 2011", - "zzz =2005.1 Spring Tracy Pictures", - "zzz =2005.2 Summer Tracy Pictures", - "zzz =2005.3 Fall Tracy Pictures", - "zzz =2005.4 Winter Tracy Pictures", - "zzz =2006.1 Spring Tracy Pictures", - "zzz =2007.0 Winter Tracy Pictures", - "zzz =2007.2 Summer Tracy Pictures", - "zzz =2008.2 Summer Tracy Pictures", - "zzz =2009.0 Winter Tracy Pictures", - "zzz =2009.2 Summer Tracy Pictures", - "zzz =2009.3 Fall Tracy Pictures", - "zzz =2009.4 Winter Tracy Pictures", - "zzz =2010.0 Winter Tracy Pictures", - "zzz =2010.1 Spring Tracy Pictures", - "zzz =2010.2 Summer Tracy Pictures", - "zzz =2010.3 Fall Tracy Pictures", - "zzz =2011.0 Winter Tracy Pictures", - "zzz =2011.1 Spring Tracy Pictures", - "zzz =2011.2 Summer Tracy Pictures", - "zzz =2011.3 Fall Tracy Pictures", - "zzz =2011.4 Winter Tracy Pictures", - "zzz =2012.0 Winter Tracy Pictures", - "zzz =2012.1 Spring Tracy Pictures", - "zzz =2012.2 Summer Tracy Pictures", - "zzz =2012.3 Fall Tracy Pictures", - "zzz =2012.4 Winter Tracy Pictures", - "zzz =2013.0 Winter Tracy Pictures", - "zzz =2013.1 Spring Tracy Pictures", - "zzz =2013.2 Summer Tracy Pictures", - "zzz =2013.3 Fall Tracy Pictures", - "zzz =2013.4 Winter Tracy Pictures", - "zzz =2014.0 Winter Tracy Pictures", - "zzz =2014.1 Spring Tracy Pictures", - "zzz =2014.2 Summer Tracy Pictures", - "zzz =2014.3 Fall Tracy Pictures", - "zzz =2014.4 Winter Tracy Pictures", - "zzz =2015.0 Winter Tracy Pictures", - "zzz Family Pictures", - "zzz Family Pictures", - "zzz Family Pictures", - "zzz Family Pictures", - "zzz GrandPrix", - "zzz Motorcycles", - "zzz Motorcycles", - "zzz Motorcycles", - "zzz Parents Yard", - "zzz Phares Family Pictures", - "zzz Phares Slides ####", - "zzz Portrait Innovations April", - "zzz Portrait Innovations Files", - "zzz Portrait Innovations June", - "zzz Portrait Innovations March", - "zzz Rex Memorial ####", - "zzz Scanned Grandma's Quilt ####", - "zzz Scanned Pictures Of Kids ####", - "zzz Scanned Prints ####", - "zzz Slide in Name Order Originals (622) ####", - "zzz Tub", - "zzz Vericruz" ] } } diff --git a/Instance/appsettings.Staging.json b/Instance/appsettings.Staging.json index 9bfac95..9e26dfe 100644 --- a/Instance/appsettings.Staging.json +++ b/Instance/appsettings.Staging.json @@ -1,505 +1 @@ -{ - "Company": "Mike Phares", - "Linux": {}, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Log4netProvider": "Information", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "MaxDegreeOfParallelism": 12, - "Serilog": { - "Using": [ - "Serilog.Sinks.Console", - "Serilog.Sinks.File" - ], - "MinimumLevel": "Debug", - "WriteTo": [ - { - "Name": "Debug", - "Args": { - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" - } - }, - { - "Name": "Console", - "Args": { - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" - } - }, - { - "Name": "File", - "Args": { - "path": "%workingDirectory% - Log/log-.txt", - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}", - "rollingInterval": "Hour" - } - } - ], - "Enrich": [ - "FromLogContext", - "WithMachineName", - "WithThreadId" - ], - "Properties": { - "Application": "Sample" - } - }, - "WorkingDirectoryName": "PharesApps", - "Windows": { - "Configuration": { - "CheckDFaceAndUpWriteDates": true, - "CheckJsonForDistanceResults": false, - "CrossDirectoryMaxItemsInDistanceCollection": 7, - "DateGroup": "2022-11-12", - "DistanceFactor": 8, - "DistanceMoveUnableToMatch": false, - "DistancePixelDistanceTolerance": 1, - "DistanceRenameToMatch": false, - "FaceAreaPermille": 1000, - "FaceDistanceHiddenImageFactor": 2, - "FaceConfidencePercent": 100, - "FaceDistancePermyriad": 10000, - "FileNameDirectorySeparator": ".Z.", - "ForceFaceLastWriteTimeToCreationTime": false, - "ForceMetadataLastWriteTimeToCreationTime": false, - "ForcePropertyLastWriteTimeToCreationTime": false, - "ForceResizeLastWriteTimeToCreationTime": false, - "LoadOrCreateThenSaveIndex": false, - "LocationDigits": 9, - "LocationFactor": 10000, - "MappedMaxIndex": 1034720, - "MappingDefaultName": "John Doe~25", - "MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping": false, - "MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping": false, - "MaxImagesInDirectoryForTopLevelFirstPass": 10, - "ModelDirectory": "L:/GitHub/dlib-models", - "ModelName": "Hog", - "NumberOfJitters": 0, - "NumberOfTimesToUpsample": 0, - "OutputExtension": ".jpg", - "OutputQuality": 95, - "OverrideForFaceImages": false, - "OverrideForFaceLandmarkImages": false, - "OverrideForResizeImages": false, - "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", - "PersonBirthdayFirstYear": 1500, - "PersonBirthdayFormat": "yyyy-MM-dd_HH", - "PersonKeyFormat": "yyyy-MM-dd_HH", - "PersonRequirePeopleFile": false, - "PopulatePropertyId": true, - "PredictorModelName": "Large", - "PropertiesChangedForDistance": false, - "PropertiesChangedForFaces": false, - "PropertiesChangedForIndex": false, - "PropertiesChangedForMetadata": false, - "PropertiesChangedForProperty": false, - "PropertiesChangedForResize": false, - "ResultAllInOne": "_ _ _", - "ResultCollection": "[]", - "ResultContent": "()", - "ResultSingleton": "{}", - "RetryImagesWithoutAFace": false, - "Reverse": false, - "RootDirectory": "E:/Images", - "SaveFullYearOfRandomFiles": true, - "SaveResizedSubFiles": true, - "SkipSearch": false, - "SortingMaximumPerFaceShouldBeHigh": 3000, - "SortingMaximumPerKey": 7, - "SortingMinimumToUseSigma": 10, - "TestDistanceResults": true, - "WriteBitmapDataBytes": false, - "IgnoreExtensions": [ - ".gif", - ".GIF" - ], - "OutputResolutions": [ - "176 x 176", - "256 x 256", - "353 x 353", - "1024 x 768", - "1920 x 1080" - ], - "PropertyContentCollectionFiles": [], - "RangeDaysDeltaTolerance": [ - 0, - 700, - 123456 - ], - "RangeDistanceTolerance": [ - 0, - 0.4, - 0.6 - ], - "RangeFaceAreaPermilleTolerance": [ - 0, - 10, - 1000 - ], - "RangeFaceConfidence": [ - 0.8, - 0.2, - 100 - ], - "SaveFaceDistancesForOutputResolutions": [], - "SaveFaceLandmarkForOutputResolutions": [ - "176 x 176", - "256 x 256" - ], - "SaveMappedForOutputResolutions": [], - "SaveNotMappedForOutputResolutions": [], - "SaveResizedImagesByPersonKeyFormattedForOutputResolutions": [ - "1920 x 1080" - ], - "SaveShortcutsForOutputResolutions": [ - "1920 x 1080" - ], - "ValidImageFormatExtensions": [ - ".bmp", - ".BMP", - ".gif", - ".GIF", - ".jpeg", - ".JPEG", - ".jpg", - ".JPG", - ".png", - ".PNG", - ".tiff", - ".TIFF" - ], - "ValidMetadataExtensions": [ - ".3gp", - ".3GP", - ".avi", - ".AVI", - ".bmp", - ".BMP", - ".gif", - ".GIF", - ".ico", - ".ICO", - ".jpeg", - ".JPEG", - ".jpg", - ".JPG", - ".m4v", - ".M4V", - ".mov", - ".MOV", - ".mp4", - ".MP4", - ".mta", - ".MTA", - ".png", - ".PNG", - ".tiff", - ".TIFF" - ], - "ValidResolutions": [ - "176 x 176", - "256 x 256", - "353 x 353", - "1024 x 768", - "1280 x 720", - "1280 x 800", - "1376 x 768", - "1600 x 1200", - "1920 x 1080", - "2256 x 1496", - "3840 x 2160", - "7680 x 4320" - ], - "VerifyToSeason": [ - ". 2000", - ". 2001", - ". 2002", - ". 2003", - ". 2004", - ". 2005", - ". 2006", - ". 2007", - ". 2008", - ". 2009", - ". 2010", - ". 2011", - ". 2012", - ". 2013", - ". 2014", - ". 2015", - ". 2016", - ". 2017", - ". 2018", - ". 2019", - ". 2020", - ". 2021", - ". 2022", - ". 2023", - ". 2024", - ". 2025", - ". 2026", - ". 2027", - ". 2028", - ". 2029", - "=2000.0 Winter", - "=2002.1 Spring", - "=2002.4 Winter", - "=2003.0 Winter", - "=2003.1 Spring", - "=2003.3 Fall", - "=2003.4 Winter", - "=2004.0 Winter", - "=2005.1 Spring", - "=2005.2 Summer", - "=2005.3 Fall", - "=2005.4 Winter", - "=2006.0 Winter", - "=2006.1 Spring", - "=2006.3 Fall", - "=2007.0 Winter", - "=2007.2 Summer Logan Michael", - "=2007.2 Summer", - "=2007.3 Fall Logan Michael", - "=2007.4 Winter Logan Michael", - "=2008.0 Winter Logan Michael", - "=2008.1 Spring Logan Michael", - "=2008.2 Summer Logan Michael", - "=2008.2 Summer", - "=2008.3 Fall Logan Michael", - "=2009.0 Winter Logan Michael", - "=2009.0 Winter", - "=2009.1 Spring Logan Michael", - "=2009.1 Spring", - "=2009.2 Summer Logan Michael", - "=2009.2 Summer", - "=2009.3 Fall Logan Michael", - "=2009.3 Fall", - "=2009.4 Winter Logan Michael", - "=2009.4 Winter", - "=2010.0 Winter Logan Michael", - "=2010.0 Winter", - "=2010.1 Spring Logan Michael", - "=2010.1 Spring", - "=2010.2 Summer", - "=2010.3 Fall Logan Michael", - "=2010.3 Fall", - "=2010.4 Winter", - "=2011.0 Winter", - "=2011.1 Spring", - "=2011.2 Summer", - "=2011.3 Fall", - "=2011.4 Winter", - "=2012.0 Winter Chelsea 2012", - "=2012.0 Winter Chelsea", - "=2012.0 Winter", - "=2012.1 Spring Chelsea", - "=2012.1 Spring", - "=2012.2 Summer Chelsea", - "=2012.2 Summer", - "=2012.3 Fall Chelsea", - "=2012.3 Fall", - "=2012.4 Winter Chelsea", - "=2012.4 Winter", - "=2013.0 Winter Chelsea 2013", - "=2013.0 Winter Chelsea", - "=2013.0 Winter", - "=2013.1 Spring", - "=2013.2 Summer Chelsea", - "=2013.2 Summer", - "=2013.3 Fall Chelsea", - "=2013.3 Fall", - "=2013.4 Winter", - "=2014.0 Winter", - "=2014.1 Spring", - "=2014.2 Summer", - "=2014.3 Fall", - "=2014.4 Winter", - "=2015.0 Winter", - "=2015.1 Spring", - "=2015.2 Summer", - "=2015.3 Fall", - "=2015.4 Winter", - "=2016.0 Winter", - "=2016.1 Spring", - "=2016.2 Summer", - "=2016.3 Fall", - "=2016.4 Winter", - "=2017.1 Spring", - "=2017.2 Summer", - "=2017.3 Fall", - "=2017.4 Winter", - "=2018.0 Winter", - "=2018.1 Spring", - "=2018.3 Fall", - "=2018.4 Winter", - "=2019.0 Winter", - "=2019.1 Spring", - "=2019.2 Summer", - "=2019.3 Fall", - "=2019.4 Winter", - "=2020.0 Winter", - "=2020.1 Spring", - "=2020.2 Summer", - "=2020.3 Fall", - "=2020.4 Winter", - "=2021.1 Spring", - "=2021.2 Summer", - "=2021.3 Fall", - "=2021.4 Winter", - "=2022.0 Winter", - "=2022.1 Spring", - "Anthem 2015", - "April 2010", - "April 2013", - "December 2006", - "December 2010", - "Fall 2005", - "Fall 2015", - "Fall 2016", - "Fall 2017", - "Fall 2018", - "Fall 2019", - "Fall 2020", - "Fall 2021", - "February 2010", - "January 2015", - "July 2010", - "June 2010", - "Kids 2005", - "March 2013", - "May 2010", - "May 2011", - "May 2013", - "October 2005", - "October 2014", - "Spring 2013", - "Spring 2014", - "Spring 2016", - "Spring 2018", - "Spring 2019", - "Spring 2020", - "Summer 2011", - "Summer 2012", - "Summer 2013", - "Summer 2014", - "Summer 2015", - "Summer 2016", - "Summer 2017", - "Summer 2018", - "Summer 2020", - "Summer 2021", - "Winter 2015", - "Winter 2016", - "Winter 2017", - "Winter 2018", - "Winter 2019-2020", - "Winter 2020", - "zzz =2005.0 Winter Tracy Pictures", - "zzz =2005.1 Spring Tracy Pictures", - "zzz =2005.2 Summer Tracy Pictures", - "zzz =2005.3 Fall Tracy Pictures", - "zzz =2005.4 Winter Tracy Pictures", - "zzz =2006.1 Spring Tracy Pictures", - "zzz =2007.0 Winter Tracy Pictures", - "zzz =2007.2 Summer Tracy Pictures", - "zzz =2008.0 Winter Tracy Pictures", - "zzz =2008.2 Summer Tracy Pictures", - "zzz =2009.0 Winter Tracy Pictures", - "zzz =2009.2 Summer Tracy Pictures", - "zzz =2009.3 Fall Tracy Pictures", - "zzz =2009.4 Winter Tracy Pictures", - "zzz =2010.0 Winter Tracy Pictures", - "zzz =2010.1 Spring Tracy Pictures", - "zzz =2010.2 Summer Tracy Pictures", - "zzz =2010.3 Fall Tracy Pictures", - "zzz =2011.0 Winter Tracy Pictures", - "zzz =2011.1 Spring Tracy Pictures", - "zzz =2011.2 Summer Tracy Pictures", - "zzz =2011.3 Fall Tracy Pictures", - "zzz =2011.4 Winter Tracy Pictures", - "zzz =2012.0 Winter Tracy Pictures", - "zzz =2012.1 Spring Tracy Pictures", - "zzz =2012.2 Summer Tracy Pictures", - "zzz =2012.3 Fall Tracy Pictures", - "zzz =2012.4 Winter Tracy Pictures", - "zzz =2013.0 Winter Tracy Pictures", - "zzz =2013.1 Spring Tracy Pictures", - "zzz =2013.2 Summer Tracy Pictures", - "zzz =2013.3 Fall Tracy Pictures", - "zzz =2013.4 Winter Tracy Pictures", - "zzz =2014.0 Winter Tracy Pictures", - "zzz =2014.1 Spring Tracy Pictures", - "zzz =2014.2 Summer Tracy Pictures", - "zzz =2014.3 Fall Tracy Pictures", - "zzz =2014.4 Winter Tracy Pictures", - "zzz =2015.0 Winter Tracy Pictures" - ], - "MixedYearRelativePaths": [ - "Edited", - "Phares Slides", - "Rex Memorial", - "Scanned Grandma's Quilt", - "Scanned Pictures Of Kids", - "Scanned Prints", - "Slide in Name Order Originals (622)", - "Slides Pictures" - ], - "IgnoreRelativePaths": [ - "3757 W Whitman 2017", - "501 Playful Meadows 2006", - "501 Playful Meadows 2007", - "501 Playful Meadows 2008", - "501 Playful Meadows 2009", - "501 Playful Meadows 2010", - "501 Playful Meadows 2013", - "501 Playful Meadows 2015", - "6309 Evesham 2003", - "6309 Evesham 2004", - "Crystal's Wedding 2003", - "Danny's Wedding 2009", - "Door images 2019", - "Family Pictures 2006", - "Family Pictures 2007", - "Family Pictures 2011", - "Family Pictures 2013", - "GrandPrix 2004", - "Kids School Pictures 2004", - "Kristy 2002", - "Kristy Parents Wedding 2005", - "Logan Ultrasound 2007", - "Mandy's Dogs 2008", - "Motorcycles 2010", - "Motorcycles 2013", - "Motorcycles 2014", - "Phares Slides", - "Portrait Innovations April 2008", - "Portrait Innovations December 2007", - "Portrait Innovations June 2008", - "Portrait Innovations March 2012", - "The guys house 2000", - "Tracy Pictures 2005", - "Tracy Pictures 2006", - "Tracy Pictures 2007", - "Tracy Pictures 2008", - "Tracy Pictures 2009", - "Tracy Pictures 2010", - "Tracy Pictures 2011", - "Tracy Pictures 2012", - "Tracy Pictures 2013 Jan-July", - "Tracy Pictures 2013 July- Dec", - "Tracy Pictures 2014", - "Tracy Pictures 2015", - "Tracy Took The Kids 2006", - "Tracy's Bday 2012", - "Tracy's Wedding 2002", - "Trip to Colorado 10 2002", - "Trip to Colorado June 2002", - "Tub 2002", - "Vericruz 2011" - ] - } - } -} \ No newline at end of file +{} \ No newline at end of file diff --git a/Instance/appsettings.json b/Instance/appsettings.json index 939c88c..9d152dc 100644 --- a/Instance/appsettings.json +++ b/Instance/appsettings.json @@ -50,7 +50,7 @@ "WorkingDirectoryName": "PharesApps", "Windows": { "Configuration": { - "CheckDFaceAndUpWriteDates": true, + "CheckDFaceAndUpWriteDates": false, "CheckJsonForDistanceResults": false, "CrossDirectoryMaxItemsInDistanceCollection": 7, "DateGroup": "2022-11-12", @@ -88,7 +88,7 @@ "PersonBirthdayFirstYear": 1500, "PersonBirthdayFormat": "yyyy-MM-dd_HH", "PersonKeyFormat": "yyyy-MM-dd_HH", - "PersonRequirePeopleFile": false, + "PhotoPrismDirectory": "", "PopulatePropertyId": true, "PredictorModelName": "Large", "PropertiesChangedForDistance": false, @@ -101,7 +101,7 @@ "ResultCollection": "[]", "ResultContent": "()", "ResultSingleton": "{}", - "RetryImagesWithoutAFace": false, + "RetryImagesWithoutAFaceLocation": false, "Reverse": false, "RootDirectory": "D:/Images", "SaveFullYearOfRandomFiles": true, @@ -114,24 +114,18 @@ "WriteBitmapDataBytes": false, "IgnoreExtensions": [ ".gif", - ".GIF" - ], - "JLinks": [ - "Julie" - ], - "LoadOrCreateThenSaveDistanceResultsForOutputResolutions": [ - "1920 x 1080" - ], - "LoadOrCreateThenSaveImageFacesResultsForOutputResolutions": [ - "1920 x 1080" - ], - "OutputResolutions": [ - "176 x 176", - "256 x 256", - "353 x 353", - "1024 x 768", - "1920 x 1080" + ".GIF", + ".json", + ".JOSN", + ".txt", + ".TXT", + ".ico", + ".ICO" ], + "JLinks": [], + "LoadOrCreateThenSaveDistanceResultsForOutputResolutions": [], + "LoadOrCreateThenSaveImageFacesResultsForOutputResolutions": [], + "OutputResolutions": [], "PropertyContentCollectionFiles": [], "RangeDaysDeltaTolerance": [ 0, @@ -154,18 +148,14 @@ 100 ], "SaveFaceDistancesForOutputResolutions": [], - "SaveFaceLandmarkForOutputResolutions": [ - "176 x 176", - "256 x 256" - ], + "SaveFaceLandmarkForOutputResolutions": [], "SaveMappedForOutputResolutions": [], "SaveNotMappedForOutputResolutions": [], - "SaveResizedImagesByPersonKeyFormattedForOutputResolutions": [ - "1920 x 1080" - ], - "SaveShortcutsForOutputResolutions": [ - "1920 x 1080" - ], + "SaveResizedImagesByPersonKeyFormattedForOutputResolutions": [], + "SaveShortcutsForOutputResolutions": [], + "IgnoreRelativePaths": [], + "MixedYearRelativePaths": [], + "VerifyToSeason": [], "ValidImageFormatExtensions": [ ".bmp", ".BMP", @@ -221,293 +211,6 @@ "2256 x 1496", "3840 x 2160", "7680 x 4320" - ], - "VerifyToSeason": [ - ". 2000", - ". 2001", - ". 2002", - ". 2003", - ". 2004", - ". 2005", - ". 2006", - ". 2007", - ". 2008", - ". 2009", - ". 2010", - ". 2011", - ". 2012", - ". 2013", - ". 2014", - ". 2015", - ". 2016", - ". 2017", - ". 2018", - ". 2019", - ". 2020", - ". 2021", - ". 2022", - ". 2023", - ". 2024", - ". 2025", - ". 2026", - ". 2027", - ". 2028", - ". 2029", - "=2000.0 Winter", - "=2002.1 Spring", - "=2002.4 Winter", - "=2003.0 Winter", - "=2003.1 Spring", - "=2003.3 Fall", - "=2003.4 Winter", - "=2004.0 Winter", - "=2005.1 Spring", - "=2005.2 Summer", - "=2005.3 Fall", - "=2005.4 Winter", - "=2006.0 Winter", - "=2006.1 Spring", - "=2006.3 Fall", - "=2007.0 Winter", - "=2007.2 Summer Logan Michael", - "=2007.2 Summer", - "=2007.3 Fall Logan Michael", - "=2007.4 Winter Logan Michael", - "=2008.0 Winter Logan Michael", - "=2008.1 Spring Logan Michael", - "=2008.2 Summer Logan Michael", - "=2008.2 Summer", - "=2008.3 Fall Logan Michael", - "=2009.0 Winter Logan Michael", - "=2009.0 Winter", - "=2009.1 Spring Logan Michael", - "=2009.1 Spring", - "=2009.2 Summer Logan Michael", - "=2009.2 Summer", - "=2009.3 Fall Logan Michael", - "=2009.3 Fall", - "=2009.4 Winter Logan Michael", - "=2009.4 Winter", - "=2010.0 Winter Logan Michael", - "=2010.0 Winter", - "=2010.1 Spring Logan Michael", - "=2010.1 Spring", - "=2010.2 Summer", - "=2010.3 Fall Logan Michael", - "=2010.3 Fall", - "=2010.4 Winter", - "=2011.0 Winter", - "=2011.1 Spring", - "=2011.2 Summer", - "=2011.3 Fall", - "=2011.4 Winter", - "=2012.0 Winter Chelsea 2012", - "=2012.0 Winter Chelsea", - "=2012.0 Winter", - "=2012.1 Spring Chelsea", - "=2012.1 Spring", - "=2012.2 Summer Chelsea", - "=2012.2 Summer", - "=2012.3 Fall Chelsea", - "=2012.3 Fall", - "=2012.4 Winter Chelsea", - "=2012.4 Winter", - "=2013.0 Winter Chelsea 2013", - "=2013.0 Winter Chelsea", - "=2013.0 Winter", - "=2013.1 Spring", - "=2013.2 Summer Chelsea", - "=2013.2 Summer", - "=2013.3 Fall Chelsea", - "=2013.3 Fall", - "=2013.4 Winter", - "=2014.0 Winter", - "=2014.1 Spring", - "=2014.2 Summer", - "=2014.3 Fall", - "=2014.4 Winter", - "=2015.0 Winter", - "=2015.1 Spring", - "=2015.2 Summer", - "=2015.3 Fall", - "=2015.4 Winter", - "=2016.0 Winter", - "=2016.1 Spring", - "=2016.2 Summer", - "=2016.3 Fall", - "=2016.4 Winter", - "=2017.1 Spring", - "=2017.2 Summer", - "=2017.3 Fall", - "=2017.4 Winter", - "=2018.0 Winter", - "=2018.1 Spring", - "=2018.3 Fall", - "=2018.4 Winter", - "=2019.0 Winter", - "=2019.1 Spring", - "=2019.2 Summer", - "=2019.3 Fall", - "=2019.4 Winter", - "=2020.0 Winter", - "=2020.1 Spring", - "=2020.2 Summer", - "=2020.3 Fall", - "=2020.4 Winter", - "=2021.1 Spring", - "=2021.2 Summer", - "=2021.3 Fall", - "=2021.4 Winter", - "=2022.0 Winter", - "=2022.1 Spring", - "Anthem 2015", - "April 2010", - "April 2013", - "December 2006", - "December 2010", - "Fall 2005", - "Fall 2015", - "Fall 2016", - "Fall 2017", - "Fall 2018", - "Fall 2019", - "Fall 2020", - "Fall 2021", - "February 2010", - "January 2015", - "July 2010", - "June 2010", - "Kids 2005", - "March 2013", - "May 2010", - "May 2011", - "May 2013", - "October 2005", - "October 2014", - "Spring 2013", - "Spring 2014", - "Spring 2016", - "Spring 2018", - "Spring 2019", - "Spring 2020", - "Summer 2011", - "Summer 2012", - "Summer 2013", - "Summer 2014", - "Summer 2015", - "Summer 2016", - "Summer 2017", - "Summer 2018", - "Summer 2020", - "Summer 2021", - "Winter 2015", - "Winter 2016", - "Winter 2017", - "Winter 2018", - "Winter 2019-2020", - "Winter 2020", - "zzz =2005.0 Winter Tracy Pictures", - "zzz =2005.1 Spring Tracy Pictures", - "zzz =2005.2 Summer Tracy Pictures", - "zzz =2005.3 Fall Tracy Pictures", - "zzz =2005.4 Winter Tracy Pictures", - "zzz =2006.1 Spring Tracy Pictures", - "zzz =2007.0 Winter Tracy Pictures", - "zzz =2007.2 Summer Tracy Pictures", - "zzz =2008.0 Winter Tracy Pictures", - "zzz =2008.2 Summer Tracy Pictures", - "zzz =2009.0 Winter Tracy Pictures", - "zzz =2009.2 Summer Tracy Pictures", - "zzz =2009.3 Fall Tracy Pictures", - "zzz =2009.4 Winter Tracy Pictures", - "zzz =2010.0 Winter Tracy Pictures", - "zzz =2010.1 Spring Tracy Pictures", - "zzz =2010.2 Summer Tracy Pictures", - "zzz =2010.3 Fall Tracy Pictures", - "zzz =2011.0 Winter Tracy Pictures", - "zzz =2011.1 Spring Tracy Pictures", - "zzz =2011.2 Summer Tracy Pictures", - "zzz =2011.3 Fall Tracy Pictures", - "zzz =2011.4 Winter Tracy Pictures", - "zzz =2012.0 Winter Tracy Pictures", - "zzz =2012.1 Spring Tracy Pictures", - "zzz =2012.2 Summer Tracy Pictures", - "zzz =2012.3 Fall Tracy Pictures", - "zzz =2012.4 Winter Tracy Pictures", - "zzz =2013.0 Winter Tracy Pictures", - "zzz =2013.1 Spring Tracy Pictures", - "zzz =2013.2 Summer Tracy Pictures", - "zzz =2013.3 Fall Tracy Pictures", - "zzz =2013.4 Winter Tracy Pictures", - "zzz =2014.0 Winter Tracy Pictures", - "zzz =2014.1 Spring Tracy Pictures", - "zzz =2014.2 Summer Tracy Pictures", - "zzz =2014.3 Fall Tracy Pictures", - "zzz =2014.4 Winter Tracy Pictures", - "zzz =2015.0 Winter Tracy Pictures" - ], - "MixedYearRelativePaths": [ - "Edited", - "Phares Slides", - "Rex Memorial", - "Scanned Grandma's Quilt", - "Scanned Pictures Of Kids", - "Scanned Prints", - "Slide in Name Order Originals (622)", - "Slides Pictures" - ], - "IgnoreRelativePaths": [ - "3757 W Whitman 2017", - "501 Playful Meadows 2006", - "501 Playful Meadows 2007", - "501 Playful Meadows 2008", - "501 Playful Meadows 2009", - "501 Playful Meadows 2010", - "501 Playful Meadows 2013", - "501 Playful Meadows 2015", - "6309 Evesham 2003", - "6309 Evesham 2004", - "Crystal's Wedding 2003", - "Danny's Wedding 2009", - "Door images 2019", - "Family Pictures 2006", - "Family Pictures 2007", - "Family Pictures 2011", - "Family Pictures 2013", - "GrandPrix 2004", - "Kids School Pictures 2004", - "Kristy 2002", - "Kristy Parents Wedding 2005", - "Logan Ultrasound 2007", - "Mandy's Dogs 2008", - "Motorcycles 2010", - "Motorcycles 2013", - "Motorcycles 2014", - "Phares Slides", - "Portrait Innovations April 2008", - "Portrait Innovations December 2007", - "Portrait Innovations June 2008", - "Portrait Innovations March 2012", - "The guys house 2000", - "Tracy Pictures 2005", - "Tracy Pictures 2006", - "Tracy Pictures 2007", - "Tracy Pictures 2008", - "Tracy Pictures 2009", - "Tracy Pictures 2010", - "Tracy Pictures 2011", - "Tracy Pictures 2012", - "Tracy Pictures 2013 Jan-July", - "Tracy Pictures 2013 July- Dec", - "Tracy Pictures 2014", - "Tracy Pictures 2015", - "Tracy Took The Kids 2006", - "Tracy's Bday 2012", - "Tracy's Wedding 2002", - "Trip to Colorado 10 2002", - "Trip to Colorado June 2002", - "Tub 2002", - "Vericruz 2011" ] } } diff --git a/Map/Map.csproj b/Map/Map.csproj index c7bf828..cfed8f3 100644 --- a/Map/Map.csproj +++ b/Map/Map.csproj @@ -39,7 +39,7 @@ - + diff --git a/Map/Models/Configuration.cs b/Map/Models/Configuration.cs index fdf9c71..f138c2d 100644 --- a/Map/Models/Configuration.cs +++ b/Map/Models/Configuration.cs @@ -14,6 +14,7 @@ public class Configuration public string MappingDefaultName { init; get; } public int PersonBirthdayFirstYear { init; get; } public string PersonBirthdayFormat { init; get; } + public string PhotoPrismDirectory { init; get; } public int RangeDaysDeltaTolerance { init; get; } public double RangeDistanceTolerance { init; get; } public int SortingMaximumPerKey { init; get; } @@ -25,6 +26,7 @@ public class Configuration string mappingDefaultName, int personBirthdayFirstYear, string personBirthdayFormat, + string photoPrismDirectory, int[] rangeDaysDeltaTolerance, double[] rangeDistanceTolerance, int sortingMaximumPerKey, @@ -34,6 +36,7 @@ public class Configuration string facePartsFileNameExtension) { MappingDefaultName = mappingDefaultName; + PhotoPrismDirectory = photoPrismDirectory; PersonBirthdayFormat = personBirthdayFormat; SortingMaximumPerKey = sortingMaximumPerKey; FaceConfidencePercent = faceConfidencePercent; diff --git a/Map/Models/DatabaseFile.cs b/Map/Models/DatabaseFile.cs new file mode 100644 index 0000000..1735503 --- /dev/null +++ b/Map/Models/DatabaseFile.cs @@ -0,0 +1,54 @@ +using System.Text.Json.Serialization; + +namespace View_by_Distance.Map.Models; + +public record DatabaseFile( + [property: JsonPropertyName("id")] int Id, + [property: JsonPropertyName("photo_id")] int PhotoId, + [property: JsonPropertyName("photo_uid")] string PhotoUid, + [property: JsonPropertyName("photo_taken_at")] string PhotoTakenAt, + [property: JsonPropertyName("time_index")] string TimeIndex, + [property: JsonPropertyName("media_id")] string MediaId, + [property: JsonPropertyName("media_utc")] object MediaUtc, + [property: JsonPropertyName("instance_id")] string InstanceId, + [property: JsonPropertyName("file_uid")] string FileUid, + [property: JsonPropertyName("file_name")] string FileName, + [property: JsonPropertyName("file_root")] string FileRoot, + [property: JsonPropertyName("original_name")] string OriginalName, + [property: JsonPropertyName("file_hash")] string FileHash, + [property: JsonPropertyName("file_size")] int FileSize, + [property: JsonPropertyName("file_codec")] string FileCodec, + [property: JsonPropertyName("file_type")] string FileType, + [property: JsonPropertyName("media_type")] string MediaType, + [property: JsonPropertyName("file_mime")] string FileMime, + [property: JsonPropertyName("file_primary")] long FilePrimary, + [property: JsonPropertyName("file_sidecar")] long FileSidecar, + [property: JsonPropertyName("file_missing")] long FileMissing, + [property: JsonPropertyName("file_portrait")] long FilePortrait, + [property: JsonPropertyName("file_video")] long FileVideo, + [property: JsonPropertyName("file_duration")] long FileDuration, + [property: JsonPropertyName("file_fps")] object FileFps, + [property: JsonPropertyName("file_frames")] object FileFrames, + [property: JsonPropertyName("file_width")] int FileWidth, + [property: JsonPropertyName("file_height")] int FileHeight, + [property: JsonPropertyName("file_orientation")] int FileOrientation, + [property: JsonPropertyName("file_projection")] string FileProjection, + [property: JsonPropertyName("file_aspect_ratio")] double FileAspectRatio, + [property: JsonPropertyName("file_hdr")] long FileHdr, + [property: JsonPropertyName("file_watermark")] long FileWatermark, + [property: JsonPropertyName("file_color_profile")] string FileColorProfile, + [property: JsonPropertyName("file_main_color")] string FileMainColor, + [property: JsonPropertyName("file_colors")] string FileColors, + [property: JsonPropertyName("file_luminance")] string FileLuminance, + [property: JsonPropertyName("file_diff")] long FileDiff, + [property: JsonPropertyName("file_chroma")] long FileChroma, + [property: JsonPropertyName("file_software")] string FileSoftware, + [property: JsonPropertyName("file_error")] string FileError, + [property: JsonPropertyName("mod_time")] long ModTime, + [property: JsonPropertyName("created_at")] string CreatedAt, + [property: JsonPropertyName("created_in")] long CreatedIn, + [property: JsonPropertyName("updated_at")] string UpdatedAt, + [property: JsonPropertyName("updated_in")] long UpdatedIn, + [property: JsonPropertyName("published_at")] object PublishedAt, + [property: JsonPropertyName("deleted_at")] object DeletedAt + ); \ No newline at end of file diff --git a/Map/Models/DatabaseFileRoot.cs b/Map/Models/DatabaseFileRoot.cs new file mode 100644 index 0000000..01e31b4 --- /dev/null +++ b/Map/Models/DatabaseFileRoot.cs @@ -0,0 +1,8 @@ +using System.Text.Json.Serialization; + +namespace View_by_Distance.Map.Models; + +public record DatabaseFileRoot( + [property: JsonPropertyName("table")] string Table, + [property: JsonPropertyName("rows")] IReadOnlyList Files + ); \ No newline at end of file diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index 043b877..385cf93 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -1,5 +1,6 @@ using Humanizer; using ShellProgressBar; +using System.Text; using System.Text.Json; using View_by_Distance.Map.Models.Stateless; using View_by_Distance.Shared.Models; @@ -15,7 +16,7 @@ public class MapLogic protected readonly List _NotMappedPersonContainers; protected readonly Dictionary _PersonKeyToPersonContainer; protected readonly Dictionary _PersonKeyToRanges; - protected readonly Dictionary> _IdThenNormalizedPixelPercentageToPersonContainers; + protected readonly Dictionary> _IdThenNormalizedRectangleToPersonContainers; public Dictionary KeyValuePairs => throw new NotImplementedException(); public Dictionary IndicesFromNew => throw new NotImplementedException(); @@ -51,7 +52,7 @@ public class MapLogic string? rootDirectoryParent = Path.GetDirectoryName(propertyConfiguration.RootDirectory); Dictionary personKeyToRanges = new(); string eDistanceContentTicksDirectory = Path.Combine(eDistanceContentDirectory, $"({ticks})"); - Dictionary> idThenNormalizedPixelPercentageToPersonContainers = new(); + Dictionary> idThenNormalizedRectangleToPersonContainers = new(); for (int i = 1; i < 5; i++) _ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory); _ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory); @@ -76,7 +77,7 @@ public class MapLogic personKeyToRanges, notMappedPersonContainers, skipCollection, - idThenNormalizedPixelPercentageToPersonContainers); + idThenNormalizedRectangleToPersonContainers); if (personContainerCollection.Count == personContainers.Length) throw new NotSupportedException(); } @@ -97,7 +98,7 @@ public class MapLogic _NotMappedPersonContainers = notMappedPersonContainers; _PersonKeyToPersonContainer = personKeyToPersonContainer; _EDistanceContentTicksDirectory = eDistanceContentTicksDirectory; - _IdThenNormalizedPixelPercentageToPersonContainers = idThenNormalizedPixelPercentageToPersonContainers; + _IdThenNormalizedRectangleToPersonContainers = idThenNormalizedRectangleToPersonContainers; } public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, long ticks, PersonContainer[] personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) : @@ -123,15 +124,15 @@ public class MapLogic PersonContainer[]? collection; List personContainers = new(); Dictionary personKeyToCount = new(); - Dictionary? normalizedPixelPercentageToPersonContainers; + Dictionary? normalizedRectangleToPersonContainers; foreach (Mapping mapping in mappingCollection) { personContainers.Clear(); - if (!_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(mapping.MappingFromItem.Id, out normalizedPixelPercentageToPersonContainers)) + if (!_IdThenNormalizedRectangleToPersonContainers.TryGetValue(mapping.MappingFromItem.Id, out normalizedRectangleToPersonContainers)) result += 1; else { - if (!normalizedPixelPercentageToPersonContainers.TryGetValue(mapping.MappingFromLocation.NormalizedPixelPercentage, out collection)) + if (!normalizedRectangleToPersonContainers.TryGetValue(mapping.MappingFromLocation.NormalizedRectangle, out collection)) result += 1; else personContainers.AddRange(collection); @@ -152,7 +153,7 @@ public class MapLogic return new(personKeyToCount, result); } - private void SaveContainers(int totalNotMapped, int? updated, List saveContainers) + public void SaveContainers(int totalNotMapped, int? updated, List saveContainers) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -342,7 +343,7 @@ public class MapLogic string personKeyFormatted; PersonBirthday personBirthday; PersonContainer personContainer; - result = Path.Combine(_EDistanceContentTicksDirectory, by, sortingContainer.Sorting.Id.ToString(), sortingContainer.Sorting.NormalizedPixelPercentage.ToString()); + result = Path.Combine(_EDistanceContentTicksDirectory, by, sortingContainer.Sorting.Id.ToString(), sortingContainer.Sorting.NormalizedRectangle.ToString()); for (int i = 0; i < _NotMappedPersonContainers.Count; i++) { personContainer = _NotMappedPersonContainers[i]; @@ -358,7 +359,7 @@ public class MapLogic return result; } - private List GetSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, Mapping[] mappingCollection, Dictionary> idToNormalizedPixelPercentageToMapping, Dictionary personKeyToCount, int? useFiltersCounter, bool saveMapped) + private List GetSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, Mapping[] mappingCollection, Dictionary> idToNormalizedRectangleToMapping, Dictionary personKeyToCount, int? useFiltersCounter, bool saveNullPerson, bool saveMapped) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -379,7 +380,7 @@ public class MapLogic SaveContainer? saveContainer; FileHolder facePartsFileHolder; FileHolder hiddenFaceFileHolder; - Dictionary? normalizedPixelPercentageToMapping; + Dictionary? normalizedRectangleToMapping; string forceSingleImageHumanized = nameof(IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title); foreach (Mapping mapping in mappingCollection) { @@ -391,6 +392,8 @@ public class MapLogic continue; if (mapping.MappingFromPerson is null) { + if (!saveNullPerson) + continue; if (mapping.SortingContainer is null) continue; directory = GetDirectory(by, mapping.MappingFromItem, mapping.SortingContainer); @@ -404,7 +407,10 @@ public class MapLogic throw new NotSupportedException(); personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks; personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday); - directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, mapping.MappingFromPerson.SegmentB); + if (string.IsNullOrEmpty(mapping.SegmentC)) + directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, mapping.MappingFromPerson.SegmentB); + else + directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, mapping.MappingFromPerson.SegmentB, mapping.SegmentC); if (isByMapping) personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName); else if (mapping.By is not null) @@ -435,7 +441,10 @@ public class MapLogic facePartsDirectory = GetFacePartsDirectory(d2FacePartsContentDirectory, mapping.MappingFromItem); if (facePartsDirectory is null) continue; - checkFile = Path.Combine(directory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}"); + if (!isBySorting || mapping.MappingFromPerson is not null) + checkFile = Path.Combine(directory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}"); + else + checkFile = Path.Combine(directory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}-Source{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}"); shortcutFile = Path.Combine(personDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}.lnk"); hiddenFaceFileHolder = new(Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesHiddenFileNameExtension}")); facePartsFileHolder = new(Path.Combine(facePartsDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacePartsFileNameExtension}")); @@ -444,43 +453,43 @@ public class MapLogic results.Add(saveContainer); if (!isBySorting || mapping.SortingContainer is null) continue; - if (!idToNormalizedPixelPercentageToMapping.TryGetValue(mapping.SortingContainer.Sorting.Id, out normalizedPixelPercentageToMapping)) + if (!idToNormalizedRectangleToMapping.TryGetValue(mapping.SortingContainer.Sorting.Id, out normalizedRectangleToMapping)) continue; - if (!normalizedPixelPercentageToMapping.ContainsKey(mapping.SortingContainer.Sorting.NormalizedPixelPercentage)) + if (!normalizedRectangleToMapping.ContainsKey(mapping.SortingContainer.Sorting.NormalizedRectangle)) continue; if (isBySorting && mapping.MappingFromPerson is null) { - saveContainer = GetMatchSaveContainer(dFacesContentDirectory, d2FacePartsContentDirectory, directory, normalizedPixelPercentageToMapping[mapping.SortingContainer.Sorting.NormalizedPixelPercentage]); + saveContainer = GetMatchSaveContainer(dFacesContentDirectory, d2FacePartsContentDirectory, directory, normalizedRectangleToMapping[mapping.SortingContainer.Sorting.NormalizedRectangle]); if (saveContainer is not null) results.Add(saveContainer); } - saveContainer = Stateless.MapLogic.GetDebugSaveContainer(directory, mapping.SortingContainer, normalizedPixelPercentageToMapping[mapping.SortingContainer.Sorting.NormalizedPixelPercentage]); + saveContainer = Stateless.MapLogic.GetDebugSaveContainer(directory, mapping.SortingContainer, normalizedRectangleToMapping[mapping.SortingContainer.Sorting.NormalizedRectangle]); results.Add(saveContainer); } return results; } - public void UpdateFromSortingContainersThenSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, Mapping[] mappingCollection, Dictionary> idToNormalizedPixelPercentageToMapping, int? useFiltersCounter, SortingContainer[] sortingContainers, int totalNotMapped) + public List GetSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, Mapping[] mappingCollection, Dictionary> idToNormalizedRectangleToMapping, int? useFiltersCounter, bool saveNullPerson) { - if (_MapLogicSupport is not null) - { - string counts = _MapLogicSupport.GetCounts(); - _ = Directory.CreateDirectory(Path.Combine(_EDistanceContentTicksDirectory, counts)); - } + if (_Configuration is null) + throw new NullReferenceException(nameof(_Configuration)); + List results; + bool saveMapped = false; Dictionary personKeyToCount = new(); - int updated = UpdateFromSortingContainers(sortingContainers); - List saveContainers = GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedPixelPercentageToMapping, personKeyToCount, useFiltersCounter, saveMapped: false); - SaveContainers(totalNotMapped, updated, saveContainers); + results = GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedRectangleToMapping, personKeyToCount, useFiltersCounter, saveNullPerson, saveMapped); + return results; } - public void SaveMapped(string dFacesContentDirectory, string d2FacePartsContentDirectory, Mapping[] mappingCollection, Dictionary> idToNormalizedPixelPercentageToMapping, Dictionary personKeyToCount, int totalNotMapped) + public void SaveMapped(string dFacesContentDirectory, string d2FacePartsContentDirectory, Mapping[] mappingCollection, Dictionary> idToNormalizedRectangleToMapping, Dictionary personKeyToCount, int totalNotMapped) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); int? updated = null; + bool saveMapped = true; + bool saveNullPerson = false; int? useFiltersCounter = null; string mappingDirectory = Path.Combine(_EDistanceContentTicksDirectory, nameof(IMapLogic.Mapping)); - List saveContainers = GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedPixelPercentageToMapping, personKeyToCount, useFiltersCounter, saveMapped: true); + List saveContainers = GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedRectangleToMapping, personKeyToCount, useFiltersCounter, saveNullPerson, saveMapped); SaveContainers(totalNotMapped, updated, saveContainers); if (!string.IsNullOrEmpty(_EDistanceContentTicksDirectory) && Directory.Exists(mappingDirectory)) Stateless.MapLogic.SaveMappingShortcuts(mappingDirectory); @@ -504,18 +513,18 @@ public class MapLogic public bool Used(FaceDistance faceDistanceEncoding) { bool result = false; - if (faceDistanceEncoding.NormalizedPixelPercentage is null) + if (faceDistanceEncoding.NormalizedRectangle is null) throw new NotSupportedException(); - List? normalizedPixelPercentages; - Dictionary? normalizedPixelPercentageToPersonContainers; - if (_SkipCollection.TryGetValue(faceDistanceEncoding.Id, out normalizedPixelPercentages)) + List? normalizedRectangles; + Dictionary? normalizedRectangleToPersonContainers; + if (_SkipCollection.TryGetValue(faceDistanceEncoding.Id, out normalizedRectangles)) { - if (normalizedPixelPercentages.Contains(faceDistanceEncoding.NormalizedPixelPercentage.Value)) + if (normalizedRectangles.Contains(faceDistanceEncoding.NormalizedRectangle.Value)) result = true; } - if (!result && _IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(faceDistanceEncoding.Id, out normalizedPixelPercentageToPersonContainers)) + if (!result && _IdThenNormalizedRectangleToPersonContainers.TryGetValue(faceDistanceEncoding.Id, out normalizedRectangleToPersonContainers)) { - if (normalizedPixelPercentageToPersonContainers.ContainsKey(faceDistanceEncoding.NormalizedPixelPercentage.Value)) + if (normalizedRectangleToPersonContainers.ContainsKey(faceDistanceEncoding.NormalizedRectangle.Value)) result = true; } return result; @@ -528,45 +537,45 @@ public class MapLogic List results = new(); Sorting sorting; FaceDistance faceDistanceLength; - List? normalizedPixelPercentages; - Dictionary? normalizedPixelPercentageToPersonContainers; + List? normalizedRectangles; + Dictionary? normalizedRectangleToPersonContainers; List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection; for (int j = 0; j < faceDistanceLengths.Count; j++) { - if (faceDistanceEncoding.NormalizedPixelPercentage is null) + if (faceDistanceEncoding.NormalizedRectangle is null) throw new NotSupportedException(); if (j == i) continue; - if (_SkipCollection.TryGetValue(faceDistanceEncoding.Id, out normalizedPixelPercentages)) + if (_SkipCollection.TryGetValue(faceDistanceEncoding.Id, out normalizedRectangles)) { - if (normalizedPixelPercentages.Contains(faceDistanceEncoding.NormalizedPixelPercentage.Value)) + if (normalizedRectangles.Contains(faceDistanceEncoding.NormalizedRectangle.Value)) continue; } - if (_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(faceDistanceEncoding.Id, out normalizedPixelPercentageToPersonContainers)) + if (_IdThenNormalizedRectangleToPersonContainers.TryGetValue(faceDistanceEncoding.Id, out normalizedRectangleToPersonContainers)) { - if (normalizedPixelPercentageToPersonContainers.ContainsKey(faceDistanceEncoding.NormalizedPixelPercentage.Value)) + if (normalizedRectangleToPersonContainers.ContainsKey(faceDistanceEncoding.NormalizedRectangle.Value)) continue; } faceDistanceLength = faceDistanceLengths[j]; - if (faceDistanceLength.NormalizedPixelPercentage is null || faceDistanceLength.Length is null) + if (faceDistanceLength.NormalizedRectangle is null || faceDistanceLength.Length is null) throw new NotSupportedException(); if (faceDistanceLength.Length == 0) continue; - if (!_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(faceDistanceLength.Id, out normalizedPixelPercentageToPersonContainers)) + if (!_IdThenNormalizedRectangleToPersonContainers.TryGetValue(faceDistanceLength.Id, out normalizedRectangleToPersonContainers)) personKeysRangesCollection = new(); else { - if (!normalizedPixelPercentageToPersonContainers.ContainsKey(faceDistanceLength.NormalizedPixelPercentage.Value)) + if (!normalizedRectangleToPersonContainers.ContainsKey(faceDistanceLength.NormalizedRectangle.Value)) personKeysRangesCollection = new(); else - personKeysRangesCollection = GetPersonKeysRangesCollection(normalizedPixelPercentageToPersonContainers[faceDistanceLength.NormalizedPixelPercentage.Value]); + personKeysRangesCollection = GetPersonKeysRangesCollection(normalizedRectangleToPersonContainers[faceDistanceLength.NormalizedRectangle.Value]); } sorting = ISorting.Get(_Configuration.FaceDistancePermyriad, _Configuration.RangeDistanceTolerance, faceDistanceEncoding, faceDistanceLength, personKeysRangesCollection); if (sorting.DistancePermyriad == 0) continue; if (sorting.Id == faceDistanceEncoding.Id) { - if (sorting.NormalizedPixelPercentage == faceDistanceEncoding.NormalizedPixelPercentage.Value) + if (sorting.NormalizedRectangle == faceDistanceEncoding.NormalizedRectangle.Value) throw new NotSupportedException(); continue; } @@ -575,10 +584,15 @@ public class MapLogic return results; } - public int UpdateFromSortingContainers(SortingContainer[] sortingContainers) + public int UpdateFromSortingContainers(SortingContainer[] sortingContainers, bool saveNullPerson) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); + if (_MapLogicSupport is not null) + { + string counts = _MapLogicSupport.GetCounts(); + _ = Directory.CreateDirectory(Path.Combine(_EDistanceContentTicksDirectory, counts)); + } int result = 0; string key; const int zero = 0; @@ -587,12 +601,13 @@ public class MapLogic PersonBirthday personBirthday; const int by = IMapLogic.Sorting; PersonContainer[] personContainers; - List normalizedPixelPercentageCollectionForA; - List normalizedPixelPercentageCollectionForB; - Dictionary checkKeyValuePairs = new(); - Dictionary> idToNormalizedPixelPercentageCollectionForA = new(); - Dictionary> idToNormalizedPixelPercentageCollectionForB = new(); - Dictionary? normalizedPixelPercentageToPersonContainers; + Dictionary keyToCount = new(); + Dictionary keyToSegmentC = new(); + List normalizedRectangleCollectionForA; + List normalizedRectangleCollectionForB; + Dictionary> idToNormalizedRectangleCollectionForA = new(); + Dictionary> idToNormalizedRectangleCollectionForB = new(); + Dictionary? normalizedRectangleToPersonContainers; int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - _Ticks).TotalSeconds); string message = $") {sortingContainers.Length:000} Update From Sorting Container(s) - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; @@ -602,35 +617,39 @@ public class MapLogic progressBar.Tick(); if (sortingContainer.Mapping is null) throw new NotSupportedException(); - if (!idToNormalizedPixelPercentageCollectionForA.ContainsKey(sortingContainer.Mapping.MappingFromItem.Id)) - idToNormalizedPixelPercentageCollectionForA.Add(sortingContainer.Mapping.MappingFromItem.Id, new()); - normalizedPixelPercentageCollectionForA = idToNormalizedPixelPercentageCollectionForA[sortingContainer.Mapping.MappingFromItem.Id]; - if (!idToNormalizedPixelPercentageCollectionForB.ContainsKey(sortingContainer.Mapping.MappingFromItem.Id)) - idToNormalizedPixelPercentageCollectionForB.Add(sortingContainer.Mapping.MappingFromItem.Id, new()); - normalizedPixelPercentageCollectionForB = idToNormalizedPixelPercentageCollectionForB[sortingContainer.Mapping.MappingFromItem.Id]; - if (!_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(sortingContainer.Sorting.Id, out normalizedPixelPercentageToPersonContainers)) + if (!idToNormalizedRectangleCollectionForA.ContainsKey(sortingContainer.Mapping.MappingFromItem.Id)) + idToNormalizedRectangleCollectionForA.Add(sortingContainer.Mapping.MappingFromItem.Id, new()); + normalizedRectangleCollectionForA = idToNormalizedRectangleCollectionForA[sortingContainer.Mapping.MappingFromItem.Id]; + if (!idToNormalizedRectangleCollectionForB.ContainsKey(sortingContainer.Mapping.MappingFromItem.Id)) + idToNormalizedRectangleCollectionForB.Add(sortingContainer.Mapping.MappingFromItem.Id, new()); + normalizedRectangleCollectionForB = idToNormalizedRectangleCollectionForB[sortingContainer.Mapping.MappingFromItem.Id]; + if (!_IdThenNormalizedRectangleToPersonContainers.TryGetValue(sortingContainer.Sorting.Id, out normalizedRectangleToPersonContainers)) { - personContainers = Array.Empty(); - if (normalizedPixelPercentageCollectionForA.Contains(sortingContainer.Mapping.MappingFromLocation.NormalizedPixelPercentage)) + if (!saveNullPerson) continue; - key = string.Concat(sortingContainer.Mapping.MappingFromItem.Id, '\t', sortingContainer.Mapping.MappingFromLocation.NormalizedPixelPercentage); - if (!checkKeyValuePairs.ContainsKey(key)) - checkKeyValuePairs.Add(key, new()); - checkKeyValuePairs[key]++; - if (checkKeyValuePairs[key] > _Configuration.SortingMaximumPerKey) + personContainers = Array.Empty(); + if (normalizedRectangleCollectionForA.Contains(sortingContainer.Mapping.MappingFromLocation.NormalizedRectangle)) + continue; + key = string.Concat(sortingContainer.Mapping.MappingFromItem.Id, '\t', sortingContainer.Mapping.MappingFromLocation.NormalizedRectangle); + if (!keyToCount.ContainsKey(key)) + keyToCount.Add(key, 0); + if (!keyToSegmentC.ContainsKey(key)) + keyToSegmentC.Add(key, string.Empty); + keyToCount[key]++; + if (keyToCount[key] > _Configuration.SortingMaximumPerKey) continue; sortingContainer.Mapping.UpdateMappingFromUnknownPerson(by, sortingContainer); - normalizedPixelPercentageCollectionForA.Add(sortingContainer.Mapping.MappingFromLocation.NormalizedPixelPercentage); + normalizedRectangleCollectionForA.Add(sortingContainer.Mapping.MappingFromLocation.NormalizedRectangle); result += 1; } else { - if (normalizedPixelPercentageCollectionForB.Contains(sortingContainer.Mapping.MappingFromLocation.NormalizedPixelPercentage)) + if (normalizedRectangleCollectionForB.Contains(sortingContainer.Mapping.MappingFromLocation.NormalizedRectangle)) continue; - if (!normalizedPixelPercentageToPersonContainers.ContainsKey(sortingContainer.Sorting.NormalizedPixelPercentage)) + if (!normalizedRectangleToPersonContainers.ContainsKey(sortingContainer.Sorting.NormalizedRectangle)) personContainers = Array.Empty(); else - personContainers = normalizedPixelPercentageToPersonContainers[sortingContainer.Sorting.NormalizedPixelPercentage]; + personContainers = normalizedRectangleToPersonContainers[sortingContainer.Sorting.NormalizedRectangle]; foreach (PersonContainer personContainer in personContainers) { if (personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) @@ -639,13 +658,20 @@ public class MapLogic personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personBirthday); mappingSegmentB = Stateless.MapLogic.GetMappingSegmentB(_Ticks, personBirthday, personContainer.ApproximateYears, sortingContainer.Mapping.MappingFromItem); key = string.Concat(personKeyFormatted, '\t', mappingSegmentB); - if (!checkKeyValuePairs.ContainsKey(key)) - checkKeyValuePairs.Add(key, new()); - checkKeyValuePairs[key]++; - if (checkKeyValuePairs[key] > _Configuration.SortingMaximumPerKey) - continue; - sortingContainer.Mapping.UpdateMappingFromPerson(personContainer.ApproximateYears, by, personContainer.DisplayDirectoryName, personBirthday, mappingSegmentB, sortingContainer); - normalizedPixelPercentageCollectionForB.Add(sortingContainer.Mapping.MappingFromLocation.NormalizedPixelPercentage); + if (!keyToCount.ContainsKey(key)) + keyToCount.Add(key, new()); + if (!keyToCount.ContainsKey(key)) + keyToCount.Add(key, 0); + if (!keyToSegmentC.ContainsKey(key)) + keyToSegmentC.Add(key, string.Empty); + keyToCount[key]++; + if (keyToCount[key] > _Configuration.SortingMaximumPerKey) + { + keyToCount[key] = 0; + keyToSegmentC[key] = sortingContainer.Sorting.DistancePermyriad.ToString(); + } + sortingContainer.Mapping.UpdateMappingFromPerson(personContainer.ApproximateYears, by, personContainer.DisplayDirectoryName, personBirthday, mappingSegmentB, keyToSegmentC[key], sortingContainer); + normalizedRectangleCollectionForB.Add(sortingContainer.Mapping.MappingFromLocation.NormalizedRectangle); result += 1; break; } @@ -654,7 +680,7 @@ public class MapLogic return result; } - public void CopyManualFiles(string dFacesContentDirectory, Dictionary> idToNormalizedPixelPercentageToMapping) + public void CopyManualFiles(string dFacesContentDirectory, Dictionary> idToNormalizedRectangleToMapping) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -675,11 +701,11 @@ public class MapLogic string personDisplayFileName; PersonBirthday personBirthday; string? personDisplayDirectory; - int? normalizedPixelPercentage; + int? normalizedRectangle; WindowsShortcut windowsShortcut; string by = nameof(IMapLogic.ManualCopy); - Dictionary? normalizedPixelPercentageToMapping; - Dictionary? normalizedPixelPercentageToPeronContainerCollection; + Dictionary? normalizedRectangleToMapping; + Dictionary? normalizedRectangleToPeronContainerCollection; string successfull = $"_ {nameof(IMapLogic.ManualCopy).Humanize(LetterCasing.Title)} Successfull"; foreach (KeyValuePair keyValuePair in _PersonKeyToPersonContainer) { @@ -692,8 +718,8 @@ public class MapLogic continue; if (!personDisplayDirectoryAllFile.EndsWith(_Configuration.FacesFileNameExtension)) continue; - (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(_Configuration.FacesFileNameExtension, personDisplayDirectoryAllFile); - if (id is null || normalizedPixelPercentage is null) + (id, normalizedRectangle, _) = IMapping.GetConverted(_Configuration.FacesFileNameExtension, personDisplayDirectoryAllFile); + if (id is null || normalizedRectangle is null) continue; fileInfo = new(personDisplayDirectoryAllFile); if (!fileInfo.Exists) @@ -704,11 +730,11 @@ public class MapLogic mappingSegmentB = Stateless.MapLogic.GetMappingSegmentB(_Ticks, personBirthday, keyValuePair.Value.ApproximateYears, fileInfo.CreationTime, isWrongYear: null); directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, mappingSegmentB); personDirectory = Path.Combine(directory, keyValuePair.Value.DisplayDirectoryName, "lnk"); - if (!idToNormalizedPixelPercentageToMapping.TryGetValue(id.Value, out normalizedPixelPercentageToMapping)) + if (!idToNormalizedRectangleToMapping.TryGetValue(id.Value, out normalizedRectangleToMapping)) continue; - if (!normalizedPixelPercentageToMapping.ContainsKey(normalizedPixelPercentage.Value)) + if (!normalizedRectangleToMapping.ContainsKey(normalizedRectangle.Value)) continue; - mapping = normalizedPixelPercentageToMapping[normalizedPixelPercentage.Value]; + mapping = normalizedRectangleToMapping[normalizedRectangle.Value]; if (string.IsNullOrEmpty(personDisplayDirectory)) throw new NotSupportedException(); directoryName = Path.GetDirectoryName(mapping.MappingFromItem.RelativePath); @@ -720,7 +746,7 @@ public class MapLogic continue; faceFileName = $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}"; checkFile = Path.Combine(directory, fileInfo.Name); - if (!_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(id.Value, out normalizedPixelPercentageToPeronContainerCollection) || !normalizedPixelPercentageToPeronContainerCollection.ContainsKey(normalizedPixelPercentage.Value)) + if (!_IdThenNormalizedRectangleToPersonContainers.TryGetValue(id.Value, out normalizedRectangleToPeronContainerCollection) || !normalizedRectangleToPeronContainerCollection.ContainsKey(normalizedRectangle.Value)) { if (!Directory.Exists(personDirectory)) _ = Directory.CreateDirectory(personDirectory); @@ -946,7 +972,7 @@ public class MapLogic SaveContainers(totalNotMapped, null, saveContainers); } - private List<(string, string, string, string)> GetCollectionForSaveShortcuts(string[] jLinks, string a2PeopleSingletonDirectory, PersonContainer[] personContainers, List filteredItems, Mapping[] mappingCollection, Dictionary personKeyToCount) + private (List<(string, DateTime[])>, List<(string, string, string, string)>) GetCollectionForSaveShortcutsForOutputResolutions(List filteredItems, Mapping[] mappingCollection, Dictionary personKeyToCount) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -956,19 +982,44 @@ public class MapLogic string? directoryName; string personDirectory; string personKeyFormatted; + List distinct = new(); List<(string, string, string, string)> collection = new(); - List personKeyFormattedCollection = GetPersonKeyFormattedCollection(jLinks, a2PeopleSingletonDirectory, personContainers, personKeyToCount); + List<(string, DateTime[])> directoriesAndDateTimes = new(); foreach (Item item in filteredItems) { - directoryName = Path.GetDirectoryName(item.RelativePath); - if (directoryName is null) - throw new NotSupportedException(); - if (item.Property?.Id is null || item.ResizedFileHolder?.DirectoryName is null || !item.ResizedFileHolder.Exists) + if (item.ResizedFileHolder is null) continue; - directory = Path.Combine(item.ResizedFileHolder.DirectoryName, $"{_PropertyConfiguration.ResultAllInOne}Shortcuts", _PropertyConfiguration.ResultAllInOne); - personDirectory = Path.Combine(directory, "No Faces"); - fileName = Path.Combine(personDirectory, $"{item.ResizedFileHolder.Name}.lnk"); - collection.Add(new(item.ResizedFileHolder.FullName, personDirectory, fileName, item.Property.Id.Value.ToString())); + foreach (Face face in item.Faces) + { + if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null || face.Mapping is null) + continue; + directoryName = Path.GetDirectoryName(face.Mapping.MappingFromItem.RelativePath); + if (directoryName is null) + throw new NotSupportedException(); + if (item.ResizedFileHolder?.DirectoryName is null || !item.ResizedFileHolder.Exists) + continue; + directory = Path.Combine(item.ResizedFileHolder.DirectoryName, $"{_PropertyConfiguration.ResultAllInOne}Shortcuts", _PropertyConfiguration.ResultAllInOne); + personDirectory = Path.Combine(directory, "No Faces"); + fileName = Path.Combine(personDirectory, $"{item.ResizedFileHolder.Name}.lnk"); + collection.Add(new(item.ResizedFileHolder.FullName, personDirectory, fileName, face.Mapping.MappingFromItem.Id.ToString())); + if (face.Mapping.MappingFromItem.ContainerDateTimes.Any() && !distinct.Contains(item.ResizedFileHolder.DirectoryName)) + { + distinct.Add(item.ResizedFileHolder.DirectoryName); + directoriesAndDateTimes.Add(new(item.ResizedFileHolder.DirectoryName, face.Mapping.MappingFromItem.ContainerDateTimes)); + } + } + } + foreach (Mapping mapping in mappingCollection) + { + if (mapping.MappingFromItem.ResizedFileHolder.DirectoryName is null || !mapping.MappingFromItem.ResizedFileHolder.Exists) + continue; + if (mapping.By is null or IMapLogic.Sorting || mapping.MappingFromPerson?.ApproximateYears is null) + continue; + if (string.IsNullOrEmpty(mapping.MappingFromPerson.SegmentB)) + throw new NotSupportedException(); + if (string.IsNullOrEmpty(mapping.MappingFromPerson.DisplayDirectoryName)) + throw new NotSupportedException(); + personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday); } foreach (Mapping mapping in mappingCollection) { @@ -979,6 +1030,11 @@ public class MapLogic continue; if (mapping.By is null or IMapLogic.Sorting || mapping.MappingFromPerson?.ApproximateYears is null) { + if (mapping.MappingFromItem.ContainerDateTimes.Any() && !distinct.Contains(mapping.MappingFromItem.ResizedFileHolder.DirectoryName)) + { + distinct.Add(mapping.MappingFromItem.ResizedFileHolder.DirectoryName); + directoriesAndDateTimes.Add(new(mapping.MappingFromItem.ResizedFileHolder.DirectoryName, mapping.MappingFromItem.ContainerDateTimes)); + } directory = Path.Combine(mapping.MappingFromItem.ResizedFileHolder.DirectoryName, $"{_PropertyConfiguration.ResultAllInOne}Shortcuts", _PropertyConfiguration.ResultAllInOne); personDirectory = Path.Combine(directory, "Unknown"); fileName = Path.Combine(personDirectory, $"{mapping.MappingFromItem.ResizedFileHolder.Name}.lnk"); @@ -991,9 +1047,12 @@ public class MapLogic if (string.IsNullOrEmpty(mapping.MappingFromPerson.DisplayDirectoryName)) throw new NotSupportedException(); personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday); - if (!personKeyFormattedCollection.Contains(personKeyFormatted)) - continue; personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks; + if (mapping.MappingFromItem.ContainerDateTimes.Any() && !distinct.Contains(mapping.MappingFromItem.ResizedFileHolder.DirectoryName)) + { + distinct.Add(mapping.MappingFromItem.ResizedFileHolder.DirectoryName); + directoriesAndDateTimes.Add(new(mapping.MappingFromItem.ResizedFileHolder.DirectoryName, mapping.MappingFromItem.ContainerDateTimes)); + } directory = Path.Combine(mapping.MappingFromItem.ResizedFileHolder.DirectoryName, $"{_PropertyConfiguration.ResultAllInOne}Shortcuts", personKeyFormatted); if (!personKeyToCount.ContainsKey(personKey)) personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName); @@ -1003,16 +1062,17 @@ public class MapLogic collection.Add(new(mapping.MappingFromItem.ResizedFileHolder.FullName, personDirectory, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey)); } } - return collection; + return new(directoriesAndDateTimes, collection); } - public void SaveShortcuts(string a2PeopleSingletonDirectory, PersonContainer[] personContainers, List filteredItems, Mapping[] mappingCollection, Dictionary personKeyToCount) + public void SaveShortcutsForOutputResolutions(List filteredItems, Mapping[] mappingCollection, Dictionary personKeyToCount) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); WindowsShortcut windowsShortcut; - string[] jLinks = new string[] { "All" }; - List<(string, string Directory, string, string)> collection = GetCollectionForSaveShortcuts(jLinks, a2PeopleSingletonDirectory, personContainers, filteredItems, mappingCollection, personKeyToCount); + List<(string, DateTime[])> directoriesAndDateTimes; + List<(string, string Directory, string, string)> collection; + (directoriesAndDateTimes, collection) = GetCollectionForSaveShortcutsForOutputResolutions(filteredItems, mappingCollection, personKeyToCount); string[] directories = (from l in collection select l.Directory).Distinct().ToArray(); foreach (string directory in directories) { @@ -1034,9 +1094,16 @@ public class MapLogic catch (Exception) { } } + foreach ((string directory, DateTime[] dateTimes) in directoriesAndDateTimes) + { + if (!dateTimes.Any()) + continue; + Directory.SetCreationTime(directory, dateTimes[0]); + Directory.SetLastWriteTime(directory, dateTimes[1]); + } } - private List<(string, FileHolder, string)> GetCollection(string dFacesContentDirectory, Dictionary> idToNormalizedPixelPercentageToMapping) + private List<(string, FileHolder, string)> GetCollection(string dFacesContentDirectory, Dictionary> idToNormalizedRectangleToMapping) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -1047,19 +1114,19 @@ public class MapLogic string? directoryName; string? facesDirectory; FileHolder faceFileHolder; - List? normalizedPixelPercentages; + List? normalizedRectangles; string by = nameof(IMapLogic.CopyNotMappedFaces); - Dictionary? normalizedPixelPercentageToPersonContainers; - foreach (KeyValuePair> keyValuePair in idToNormalizedPixelPercentageToMapping) + Dictionary? normalizedRectangleToPersonContainers; + foreach (KeyValuePair> keyValuePair in idToNormalizedRectangleToMapping) { - _ = _IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(keyValuePair.Key, out normalizedPixelPercentageToPersonContainers); - foreach (KeyValuePair normalizedPixelPercentageAndMapping in keyValuePair.Value) + _ = _IdThenNormalizedRectangleToPersonContainers.TryGetValue(keyValuePair.Key, out normalizedRectangleToPersonContainers); + foreach (KeyValuePair normalizedRectangleAndMapping in keyValuePair.Value) { - mapping = normalizedPixelPercentageAndMapping.Value; - if (normalizedPixelPercentageToPersonContainers is not null && normalizedPixelPercentageToPersonContainers.ContainsKey(mapping.MappingFromLocation.NormalizedPixelPercentage)) + mapping = normalizedRectangleAndMapping.Value; + if (normalizedRectangleToPersonContainers is not null && normalizedRectangleToPersonContainers.ContainsKey(mapping.MappingFromLocation.NormalizedRectangle)) continue; - _ = _SkipCollection.TryGetValue(keyValuePair.Key, out normalizedPixelPercentages); - if (normalizedPixelPercentages is not null && normalizedPixelPercentages.Contains(mapping.MappingFromLocation.NormalizedPixelPercentage)) + _ = _SkipCollection.TryGetValue(keyValuePair.Key, out normalizedRectangles); + if (normalizedRectangles is not null && normalizedRectangles.Contains(mapping.MappingFromLocation.NormalizedRectangle)) continue; directoryName = Path.GetDirectoryName(mapping.MappingFromItem.RelativePath); facesDirectory = GetFacesDirectory(dFacesContentDirectory, mapping.MappingFromItem); // Path.Combine($"{dFacesContentDirectory}{directoryName}", mapping.MappingFromItem.ImageFileHolder.NameWithoutExtension); @@ -1076,11 +1143,11 @@ public class MapLogic return results; } - public void CopyNotMappedFaces(int[] rangeFaceAreaPermilleTolerance, string dFacesContentDirectory, Dictionary> idToNormalizedPixelPercentageToMapping) + public void CopyNotMappedFaces(int[] rangeFaceAreaPermilleTolerance, string dFacesContentDirectory, Dictionary> idToNormalizedRectangleToMapping) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); - List<(string Directory, FileHolder FaceFileHolder, string CheckFile)> collection = GetCollection(dFacesContentDirectory, idToNormalizedPixelPercentageToMapping); + List<(string Directory, FileHolder FaceFileHolder, string CheckFile)> collection = GetCollection(dFacesContentDirectory, idToNormalizedRectangleToMapping); string[] directories = (from l in collection select l.Directory).Distinct().ToArray(); foreach (string directory in directories) { @@ -1097,4 +1164,249 @@ public class MapLogic } } + private DatabaseFileRoot GetDatabaseFileRoot() + { + if (_Configuration is null) + throw new NullReferenceException(nameof(_Configuration)); + string file = Path.Combine(_Configuration.PhotoPrismDirectory, "files.json"); + string json = File.ReadAllText(file); + DatabaseFileRoot? databaseFileRoot = JsonSerializer.Deserialize(json); + if (databaseFileRoot is null) + throw new NullReferenceException(nameof(databaseFileRoot)); + return databaseFileRoot; + } + + private Marker[] GetMarkers() + { + if (_Configuration is null) + throw new NullReferenceException(nameof(_Configuration)); + string file = Path.Combine(_Configuration.PhotoPrismDirectory, "markers.json"); + string json = File.ReadAllText(file); + Marker[]? markerRoot = JsonSerializer.Deserialize(json); + if (markerRoot is null) + throw new NullReferenceException(nameof(markerRoot)); + return markerRoot; + } + + private static Dictionary Get(DatabaseFileRoot databaseFileRoot) + { + Dictionary fileUidToFile = new(); + for (int i = 0; i < databaseFileRoot.Files.Count; i++) + fileUidToFile.Add(databaseFileRoot.Files[i].FileUid, databaseFileRoot.Files[i]); + return fileUidToFile; + } + + private static MarkerWith GetMarkerWith(int? dlib, DatabaseFile databaseFile, Marker marker, int? count, double? percent, int? normalizedRectangle, long? personKey, string personKeyFormatted) + { + return new(marker.MarkerUid, + marker.FileUid, + marker.MarkerType, + marker.MarkerSrc, + marker.MarkerName, + marker.MarkerReview, + marker.MarkerInvalid, + marker.SubjUid, + marker.SubjSrc, + marker.FaceId, + marker.FaceDist, + marker.EmbeddingsJson, + marker.LandmarksJson, + marker.X, + marker.Y, + marker.W, + marker.H, + marker.Q, + marker.Size, + marker.Score, + marker.Thumb, + marker.MatchedAt, + marker.CreatedAt, + marker.UpdatedAt, + databaseFile.Id, + databaseFile.FileName, + dlib, + count, + percent, + normalizedRectangle, + personKey, + personKeyFormatted); + } + + private static Dictionary> GetFacesByFileName(List filteredItems) + { + Dictionary> results = new(); + string key; + foreach (Item item in filteredItems) + { + foreach (Face face in item.Faces) + { + if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null || face.Mapping is null) + continue; + key = Path.GetFileNameWithoutExtension(face.Mapping.MappingFromItem.RelativePath); + if (!results.ContainsKey(key)) + results.Add(key, new()); + results[key].Add(face); + } + } + return results; + } + + public void FindMatch(List filteredItems) + { + if (_Configuration is null) + throw new NullReferenceException(nameof(_Configuration)); + int? dlib; + double? percent; + long? personKey; + const int zero = 0; + List? matches; + MarkerWith markerWith; + int? normalizedRectangle; + string personKeyFormatted; + DatabaseFile? databaseFile; + PersonBirthday personBirthday; + Marker[] markers = GetMarkers(); + string fileNameWithoutExtension; + PersonContainer[]? personContainers; + System.Drawing.Rectangle dlibRectangle; + System.Drawing.Rectangle prismRectangle; + System.Drawing.Rectangle intersectRectangle; + (Face Face, double Percent)[] sortedCollection; + List<(Face Face, double Percent)> collection = new(); + DatabaseFileRoot databaseFileRoot = GetDatabaseFileRoot(); + Dictionary fileUidToFile = Get(databaseFileRoot); + Dictionary? normalizedRectangleToPersonContainers; + Dictionary> keyValuePairs = GetFacesByFileName(filteredItems); + foreach (Marker marker in markers) + { + dlib = null; + personKey = null; + collection.Clear(); + normalizedRectangle = null; + personKeyFormatted = string.Empty; + normalizedRectangleToPersonContainers = null; + if (!fileUidToFile.TryGetValue(marker.FileUid, out databaseFile)) + continue; + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Path.Combine("C:", databaseFile.FileName)); + prismRectangle = new((int)(marker.X * databaseFile.FileWidth), (int)(marker.Y * databaseFile.FileHeight), (int)(marker.W * databaseFile.FileWidth), (int)(marker.H * databaseFile.FileHeight)); + if (!keyValuePairs.TryGetValue(fileNameWithoutExtension, out matches) || !int.TryParse(fileNameWithoutExtension, out int id)) + percent = null; + else + { + dlib = id; + _ = _IdThenNormalizedRectangleToPersonContainers.TryGetValue(dlib.Value, out normalizedRectangleToPersonContainers); + foreach (Face face in matches) + { + if (face.Location is null || face.OutputResolution is null) + continue; + dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top); + intersectRectangle = System.Drawing.Rectangle.Intersect(prismRectangle, dlibRectangle); + if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0) + continue; + percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height); + if (percent < 0.000001) + continue; + collection.Add(new(face, percent.Value)); + } + } + if (!collection.Any()) + percent = null; + else + { + sortedCollection = collection.OrderByDescending(l => l.Percent).ToArray(); + percent = sortedCollection[zero].Percent; + normalizedRectangle = sortedCollection[zero].Face.Mapping?.MappingFromLocation.NormalizedRectangle; + if (normalizedRectangleToPersonContainers is null || normalizedRectangle is null || !normalizedRectangleToPersonContainers.TryGetValue(normalizedRectangle.Value, out personContainers)) + personContainers = null; + else + { + foreach (PersonContainer personContainer in personContainers) + { + if (personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) + continue; + personBirthday = personContainer.Birthdays[zero]; + personKey = personBirthday.Value.Ticks; + personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personBirthday); + break; + } + } + } + markerWith = GetMarkerWith(dlib, databaseFile, marker, collection.Count, percent, normalizedRectangle, personKey, personKeyFormatted); + string json = JsonSerializer.Serialize(markerWith, new JsonSerializerOptions() { WriteIndented = true }); + if (IPath.WriteAllText(Path.Combine(_Configuration.PhotoPrismDirectory, "With", $"{marker.MarkerUid}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true)) + continue; + } + } + + public void SaveMarkers() + { + if (_Configuration is null) + throw new NullReferenceException(nameof(_Configuration)); + double[]? encoding; + string file = Path.Combine(_Configuration.PhotoPrismDirectory, "markers.json"); + string json = File.ReadAllText(file); + Marker[]? markers = JsonSerializer.Deserialize(json); + if (markers is null) + throw new NullReferenceException(nameof(markers)); + foreach (Marker marker in markers) + { + encoding = JsonSerializer.Deserialize(marker.EmbeddingsJson[1..^1]); + File.WriteAllText(Path.Combine(_Configuration.PhotoPrismDirectory, "EmbeddingsJson", $"{marker.MarkerUid}.json"), marker.EmbeddingsJson); + if (encoding is null) + continue; + } + } + + public void LoadMatches() + { + if (_Configuration is null) + throw new NullReferenceException(nameof(_Configuration)); + string json; + MarkerWith? markerWith; + List collection = new(); + StringBuilder stringBuilder = new(); + List<(int Count, MarkerWith MarkerWith)> countCollection = new(); + List<(double Percent, MarkerWith MarkerWith)> percentCollection = new(); + string[] files = Directory.GetFiles(Path.Combine(_Configuration.PhotoPrismDirectory, "With"), "*.json", SearchOption.TopDirectoryOnly); + foreach (string file in files) + { + json = File.ReadAllText(file); + markerWith = JsonSerializer.Deserialize(json); + if (markerWith is null || markerWith.DlibId is null) + continue; + collection.Add(markerWith); + if (markerWith.Count is null || markerWith.Count.Value == 0) + continue; + countCollection.Add(new(markerWith.Count.Value, markerWith)); + if (markerWith.Percent is null) + continue; + percentCollection.Add(new(markerWith.Percent.Value, markerWith)); + if (string.IsNullOrEmpty(markerWith.PersonKeyFormatted)) + continue; + _ = stringBuilder. + Append("update `markers` set subj_src = 'manual' marker_name = '"). + Append(markerWith.PersonKeyFormatted). + Append("' where marker_uid = '"). + Append(markerWith.MarkerUid). + AppendLine("';"); + } + (int, MarkerWith)[] countSorted = countCollection.OrderByDescending(l => l.Count).ToArray(); + (double, MarkerWith)[] percentSorted = percentCollection.OrderBy(l => l.Percent).ToArray(); + if (collection.Any()) + { } + File.WriteAllText(Path.Combine(_Configuration.PhotoPrismDirectory, "marker_name_update.sql"), stringBuilder.ToString()); + } + + public Dictionary> GetMissing(Dictionary> idToNormalizedRectangleToMapping) + { + Dictionary> results = new(); + foreach (KeyValuePair> normalizedRectangleToPersonContainers in _IdThenNormalizedRectangleToPersonContainers) + { + if (idToNormalizedRectangleToMapping.ContainsKey(normalizedRectangleToPersonContainers.Key)) + continue; + results.Add(normalizedRectangleToPersonContainers.Key, normalizedRectangleToPersonContainers.Value); + } + return results; + } + } \ No newline at end of file diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index 08f5194..cb2025d 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -39,7 +39,7 @@ internal abstract class MapLogic int? id; long personKey; string personKeyFormatted; - int? normalizedPixelPercentage; + int? normalizedRectangle; string newestPersonKeyFormatted; foreach (PersonContainer personContainer in personContainers) { @@ -47,12 +47,12 @@ internal abstract class MapLogic { if (!personDisplayDirectoryAllFile.EndsWith(configuration.FacesFileNameExtension)) continue; - (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(configuration.FacesFileNameExtension, personDisplayDirectoryAllFile); - if (id is null || normalizedPixelPercentage is null) + (id, normalizedRectangle, _) = IMapping.GetConverted(configuration.FacesFileNameExtension, personDisplayDirectoryAllFile); + if (id is null || normalizedRectangle is null) continue; if (!skipCollection.ContainsKey(id.Value)) skipCollection.Add(id.Value, new()); - skipCollection[id.Value].Add(normalizedPixelPercentage.Value); + skipCollection[id.Value].Add(normalizedRectangle.Value); } if (personContainer.Person is null || personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) continue; @@ -86,7 +86,7 @@ internal abstract class MapLogic string? personFirstInitial; DirectoryInfo directoryInfo; string[] personKeyDirectories; - int? normalizedPixelPercentage; + int? normalizedRectangle; string[] personNameDirectories; string[] personNameLinkDirectories; string? personFirstInitialDirectory; @@ -141,6 +141,16 @@ internal abstract class MapLogic else { personFirstInitial = personDisplayDirectoryNames[^1][..1]; + if (personFirstInitial.All(l => char.IsDigit(l))) + { + foreach (string file in files) + File.Delete(file); + files = Directory.GetFiles(personNameDirectory, "*", SearchOption.AllDirectories); + foreach (string file in files) + File.Delete(file); + _ = IPath.DeleteEmptyDirectories(personNameDirectory); + continue; + } personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial.ToString()); Directory.Move(personNameDirectory, personFirstInitialDirectory); files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); @@ -149,8 +159,8 @@ internal abstract class MapLogic { if (file.EndsWith(".lnk") || file.EndsWith(".json")) continue; - (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(configuration.FacesFileNameExtension, file); - if (id is null || normalizedPixelPercentage is null) + (id, normalizedRectangle, _) = IMapping.GetConverted(configuration.FacesFileNameExtension, file); + if (id is null || normalizedRectangle is null) continue; results.Add(new(personKeyFormatted, personDisplayDirectoryNames, file)); } @@ -182,15 +192,15 @@ internal abstract class MapLogic { Dictionary> results = new(); int? id; - int? normalizedPixelPercentage; + int? normalizedRectangle; foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string mappedFaceFile) in collection) { - (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(configuration.FacesFileNameExtension, mappedFaceFile); - if (id is null || normalizedPixelPercentage is null) + (id, normalizedRectangle, _) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFaceFile); + if (id is null || normalizedRectangle is null) continue; if (!results.ContainsKey(id.Value)) results.Add(id.Value, new()); - results[id.Value].Add(new(mappedFaceFile, normalizedPixelPercentage.Value)); + results[id.Value].Add(new(mappedFaceFile, normalizedRectangle.Value)); } return results; } @@ -211,7 +221,11 @@ internal abstract class MapLogic if (!Directory.Exists(eDistanceContentDirectory)) _ = Directory.CreateDirectory(eDistanceContentDirectory); else + { _ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory); + if (!Directory.Exists(eDistanceContentDirectory)) + _ = Directory.CreateDirectory(eDistanceContentDirectory); + } ticksDirectories = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly); } string message = $") {ticksDirectories.Length:000} collect from and clean ticks Director(ies) - A - {totalSeconds} total second(s)"; @@ -246,23 +260,23 @@ internal abstract class MapLogic return results.ToArray(); } - private static void SetKeyValuePairs(Configuration configuration, long ticks, List personContainers, Mapping[] mappingCollection, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedPixelPercentageCollection, List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, Dictionary personKeyToPersonContainer, Dictionary> idThenNormalizedPixelPercentageToPersonContainers, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer, Dictionary> incorrectIdThenNormalizedPixelPercentageToPersonContainers, Dictionary personKeyToRanges) + private static void SetKeyValuePairs(Configuration configuration, long ticks, List personContainers, Mapping[] mappingCollection, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection, List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection, Dictionary personKeyToPersonContainer, Dictionary> idThenNormalizedRectangleToPersonContainers, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer, Dictionary> incorrectIdThenNormalizedRectangleToPersonContainers, Dictionary personKeyToRanges) { PersonBirthday? personBirthday; PersonContainer[] distinctPersonContainers; Dictionary personKeyFormattedToPersonContainer = new(); - Dictionary>> idThenNormalizedPixelPercentageToPersonContainerCollection = new(); - Dictionary>> incorrectIdThenNormalizedPixelPercentageToPersonContainerCollection = new(); + Dictionary>> idThenNormalizedRectangleToPersonContainerCollection = new(); + Dictionary>> incorrectIdThenNormalizedRectangleToPersonContainerCollection = new(); List<(long, PersonContainer)> collection = GetDistinctCollection(configuration, personContainers, personKeyFormattedToPersonContainer); foreach ((long personKey, PersonContainer personContainer) in collection) personKeyToPersonContainer.Add(personKey, personContainer); - if (personKeyFormattedIdThenNormalizedPixelPercentageCollection.Any()) + if (personKeyFormattedIdThenNormalizedRectangleCollection.Any()) { string personDisplayDirectory; PersonContainer personContainer; string personDisplayDirectoryName; Dictionary personDisplayDirectoryTo = new(); - foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, int id, int normalizedPixelPercentage) in personKeyFormattedIdThenNormalizedPixelPercentageCollection) + foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, int id, int normalizedRectangle) in personKeyFormattedIdThenNormalizedRectangleCollection) { personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormatted); if (personBirthday is null) @@ -276,52 +290,52 @@ internal abstract class MapLogic } if (personDisplayDirectoryName.Length != 1 && personDisplayDirectoryName != configuration.MappingDefaultName && !personDisplayDirectoryTo.ContainsKey(personDisplayDirectory)) personDisplayDirectoryTo.Add(personDisplayDirectory, new(personDisplayDirectoryNames, personKeyFormattedToPersonContainer[personKeyFormatted])); - if (!idThenNormalizedPixelPercentageToPersonContainerCollection.ContainsKey(id)) - idThenNormalizedPixelPercentageToPersonContainerCollection.Add(id, new()); - if (!idThenNormalizedPixelPercentageToPersonContainerCollection[id].ContainsKey(normalizedPixelPercentage)) - idThenNormalizedPixelPercentageToPersonContainerCollection[id].Add(normalizedPixelPercentage, new()); - idThenNormalizedPixelPercentageToPersonContainerCollection[id][normalizedPixelPercentage].Add(personKeyFormattedToPersonContainer[personKeyFormatted]); + if (!idThenNormalizedRectangleToPersonContainerCollection.ContainsKey(id)) + idThenNormalizedRectangleToPersonContainerCollection.Add(id, new()); + if (!idThenNormalizedRectangleToPersonContainerCollection[id].ContainsKey(normalizedRectangle)) + idThenNormalizedRectangleToPersonContainerCollection[id].Add(normalizedRectangle, new()); + idThenNormalizedRectangleToPersonContainerCollection[id][normalizedRectangle].Add(personKeyFormattedToPersonContainer[personKeyFormatted]); } foreach (KeyValuePair keyValuePair in personDisplayDirectoryTo) possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Add(keyValuePair.Value); } - foreach (KeyValuePair>> keyValuePair in idThenNormalizedPixelPercentageToPersonContainerCollection) + foreach (KeyValuePair>> keyValuePair in idThenNormalizedRectangleToPersonContainerCollection) { - idThenNormalizedPixelPercentageToPersonContainers.Add(keyValuePair.Key, new()); + idThenNormalizedRectangleToPersonContainers.Add(keyValuePair.Key, new()); foreach (KeyValuePair> innerKeyValuePair in keyValuePair.Value) { distinctPersonContainers = GetDistinctPersonContainers(innerKeyValuePair.Value); - idThenNormalizedPixelPercentageToPersonContainers[keyValuePair.Key].Add(innerKeyValuePair.Key, distinctPersonContainers); + idThenNormalizedRectangleToPersonContainers[keyValuePair.Key].Add(innerKeyValuePair.Key, distinctPersonContainers); } }; - SetPersonTicks(configuration, ticks, mappingCollection, personKeyToRanges, idThenNormalizedPixelPercentageToPersonContainers); - if (incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection.Any()) + SetPersonTicks(configuration, ticks, mappingCollection, personKeyToRanges, idThenNormalizedRectangleToPersonContainers); + if (incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection.Any()) { PersonContainer personContainer; - foreach ((string personKeyFormatted, int id, int normalizedPixelPercentage) in incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection) + foreach ((string personKeyFormatted, int id, int normalizedRectangle) in incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection) { personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormatted); if (personBirthday is null) continue; - if (!incorrectIdThenNormalizedPixelPercentageToPersonContainerCollection.ContainsKey(id)) - incorrectIdThenNormalizedPixelPercentageToPersonContainerCollection.Add(id, new()); + if (!incorrectIdThenNormalizedRectangleToPersonContainerCollection.ContainsKey(id)) + incorrectIdThenNormalizedRectangleToPersonContainerCollection.Add(id, new()); if (!personKeyFormattedToPersonContainer.ContainsKey(personKeyFormatted)) { personContainer = new(personBirthday, configuration.MappingDefaultName); personKeyFormattedToPersonContainer.Add(personKeyFormatted, personContainer); } - if (!incorrectIdThenNormalizedPixelPercentageToPersonContainerCollection[id].ContainsKey(normalizedPixelPercentage)) - incorrectIdThenNormalizedPixelPercentageToPersonContainerCollection[id].Add(normalizedPixelPercentage, new()); - incorrectIdThenNormalizedPixelPercentageToPersonContainerCollection[id][normalizedPixelPercentage].Add(personKeyFormattedToPersonContainer[personKeyFormatted]); + if (!incorrectIdThenNormalizedRectangleToPersonContainerCollection[id].ContainsKey(normalizedRectangle)) + incorrectIdThenNormalizedRectangleToPersonContainerCollection[id].Add(normalizedRectangle, new()); + incorrectIdThenNormalizedRectangleToPersonContainerCollection[id][normalizedRectangle].Add(personKeyFormattedToPersonContainer[personKeyFormatted]); } } - foreach (KeyValuePair>> keyValuePair in incorrectIdThenNormalizedPixelPercentageToPersonContainerCollection) + foreach (KeyValuePair>> keyValuePair in incorrectIdThenNormalizedRectangleToPersonContainerCollection) { - incorrectIdThenNormalizedPixelPercentageToPersonContainers.Add(keyValuePair.Key, new()); + incorrectIdThenNormalizedRectangleToPersonContainers.Add(keyValuePair.Key, new()); foreach (KeyValuePair> innerKeyValuePair in keyValuePair.Value) { distinctPersonContainers = GetDistinctPersonContainers(innerKeyValuePair.Value); - incorrectIdThenNormalizedPixelPercentageToPersonContainers[keyValuePair.Key].Add(innerKeyValuePair.Key, distinctPersonContainers); + incorrectIdThenNormalizedRectangleToPersonContainers[keyValuePair.Key].Add(innerKeyValuePair.Key, distinctPersonContainers); } } } @@ -352,19 +366,19 @@ internal abstract class MapLogic return results; } - private static (int, int) SetCollectionsAndGetUnableToMatchCount(Configuration configuration, long ticks, Dictionary> idToMappingCollection, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedPixelPercentageCollection, List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, List<(string, string[], string)> collection) + private static (int, int) SetCollectionsAndGetUnableToMatchCount(Configuration configuration, long ticks, Dictionary> idToMappingCollection, Dictionary personKeyFormattedToNewestPersonKeyFormatted, List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection, List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection, List<(string, string[], string)> collection) { int result = 0; int? id; - int? normalizedPixelPercentage; + int? normalizedRectangle; string newestPersonKeyFormatted; List? mappingCollection; string personDisplayDirectoryName; - List normalizedPixelPercentages; + List normalizedRectangles; List checkMappingCollection = new(); List duplicateMappedFaceFiles = new(); bool idToMappingCollectionAny = idToMappingCollection.Any(); - Dictionary> idToNormalizedPixelPercentages = new(); + Dictionary> idToNormalizedRectangles = new(); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") {collection.Count:000} join from ticks Director(ies) - C - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; @@ -372,53 +386,51 @@ internal abstract class MapLogic foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string mappedFaceFile) in collection) { progressBar.Tick(); - (id, normalizedPixelPercentage, mappingCollection) = IMapping.GetReversedDeterministicHashCodeKey(configuration.FacesFileNameExtension, idToMappingCollectionAny, idToMappingCollection, mappedFaceFile); - if (id is null || normalizedPixelPercentage is null) - { - result++; - continue; - } - if (!idToNormalizedPixelPercentages.ContainsKey(id.Value)) - idToNormalizedPixelPercentages.Add(id.Value, new()); - normalizedPixelPercentages = idToNormalizedPixelPercentages[id.Value]; - if (mappingCollection is null) + (id, normalizedRectangle, mappingCollection) = IMapping.GetConverted(configuration.FacesFileNameExtension, idToMappingCollectionAny, idToMappingCollection, mappedFaceFile); + if (id is null || normalizedRectangle is null) { result++; continue; } + if (!idToNormalizedRectangles.ContainsKey(id.Value)) + idToNormalizedRectangles.Add(id.Value, new()); + normalizedRectangles = idToNormalizedRectangles[id.Value]; checkMappingCollection.Clear(); - foreach (Mapping mapping in mappingCollection) + if (mappingCollection is not null) { - if (normalizedPixelPercentage.Value != mapping.MappingFromLocation.NormalizedPixelPercentage) - continue; - if (normalizedPixelPercentages.Contains(mapping.MappingFromLocation.NormalizedPixelPercentage)) + foreach (Mapping mapping in mappingCollection) { - duplicateMappedFaceFiles.Add(mappedFaceFile); + if (normalizedRectangle.Value != mapping.MappingFromLocation.NormalizedRectangle) + continue; + if (normalizedRectangles.Contains(mapping.MappingFromLocation.NormalizedRectangle)) + { + duplicateMappedFaceFiles.Add(mappedFaceFile); + continue; + } + checkMappingCollection.Add(mapping); + } + if (!checkMappingCollection.Any()) + { + result++; + continue; + } + if (checkMappingCollection.Count != 1) + { + result++; continue; } - checkMappingCollection.Add(mapping); } - if (!checkMappingCollection.Any()) - { - result++; - continue; - } - if (checkMappingCollection.Count != 1) - { - result++; - continue; - } - normalizedPixelPercentages.Add(normalizedPixelPercentage.Value); - idToNormalizedPixelPercentages[id.Value].Add(normalizedPixelPercentage.Value); + normalizedRectangles.Add(normalizedRectangle.Value); + idToNormalizedRectangles[id.Value].Add(normalizedRectangle.Value); if (!personKeyFormattedToNewestPersonKeyFormatted.ContainsKey(personKeyFormatted)) newestPersonKeyFormatted = personKeyFormatted; else newestPersonKeyFormatted = personKeyFormattedToNewestPersonKeyFormatted[personKeyFormatted]; personDisplayDirectoryName = personDisplayDirectoryNames[^1]; if (string.IsNullOrEmpty(personDisplayDirectoryName) || personDisplayDirectoryName[0] == '!') - incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection.Add(new(newestPersonKeyFormatted, id.Value, normalizedPixelPercentage.Value)); + incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection.Add(new(newestPersonKeyFormatted, id.Value, normalizedRectangle.Value)); else - personKeyFormattedIdThenNormalizedPixelPercentageCollection.Add(new(newestPersonKeyFormatted, personDisplayDirectoryNames, id.Value, normalizedPixelPercentage.Value)); + personKeyFormattedIdThenNormalizedRectangleCollection.Add(new(newestPersonKeyFormatted, personDisplayDirectoryNames, id.Value, normalizedRectangle.Value)); } if (duplicateMappedFaceFiles.Any()) { @@ -494,7 +506,7 @@ internal abstract class MapLogic } } - private static void SetPersonTicks(Configuration configuration, long ticks, Mapping[] mappingCollection, Dictionary personKeyToRanges, Dictionary> idThenNormalizedPixelPercentageToPersonContainers) + private static void SetPersonTicks(Configuration configuration, long ticks, Mapping[] mappingCollection, Dictionary personKeyToRanges, Dictionary> idThenNormalizedRectangleToPersonContainers) { PersonContainer[]? personContainers; Dictionary? keyValuePairs; @@ -506,9 +518,9 @@ internal abstract class MapLogic foreach (Mapping mapping in mappingCollection) { progressBar.Tick(); - if (!idThenNormalizedPixelPercentageToPersonContainers.TryGetValue(mapping.MappingFromItem.Id, out keyValuePairs)) + if (!idThenNormalizedRectangleToPersonContainers.TryGetValue(mapping.MappingFromItem.Id, out keyValuePairs)) continue; - if (!keyValuePairs.TryGetValue(mapping.MappingFromLocation.NormalizedPixelPercentage, out personContainers)) + if (!keyValuePairs.TryGetValue(mapping.MappingFromLocation.NormalizedRectangle, out personContainers)) continue; foreach (PersonContainer personContainer in personContainers) { @@ -543,14 +555,14 @@ internal abstract class MapLogic return results; } - private static void AppendToSkipCollection(Dictionary> skipCollection, Dictionary> idThenNormalizedPixelPercentageToPersonContainers, Dictionary> incorrectIdThenNormalizedPixelPercentageToPersonContainers) + private static void AppendToSkipCollection(Dictionary> skipCollection, Dictionary> idThenNormalizedRectangleToPersonContainers, Dictionary> incorrectIdThenNormalizedRectangleToPersonContainers) { Dictionary? keyValuePairs; - foreach (KeyValuePair> keyValuePair in incorrectIdThenNormalizedPixelPercentageToPersonContainers) + foreach (KeyValuePair> keyValuePair in incorrectIdThenNormalizedRectangleToPersonContainers) { if (!skipCollection.ContainsKey(keyValuePair.Key)) skipCollection.Add(keyValuePair.Key, new()); - if (idThenNormalizedPixelPercentageToPersonContainers.TryGetValue(keyValuePair.Key, out keyValuePairs)) + if (idThenNormalizedRectangleToPersonContainers.TryGetValue(keyValuePair.Key, out keyValuePairs)) { if (keyValuePairs.ContainsKey(keyValuePair.Value.ElementAt(0).Key)) continue; @@ -600,7 +612,7 @@ internal abstract class MapLogic } } - internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, long ticks, List personContainers, string? a2PeopleContentDirectory, string eDistanceContentDirectory, Mapping[] mappingCollection, Shared.Models.Methods.IMapLogicSupport mapLogicSupport, Dictionary personKeyToPersonContainer, Dictionary personKeyToRanges, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> idThenNormalizedPixelPercentageToPersonContainers) + internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, long ticks, List personContainers, string? a2PeopleContentDirectory, string eDistanceContentDirectory, Mapping[] mappingCollection, Shared.Models.Methods.IMapLogicSupport mapLogicSupport, Dictionary personKeyToPersonContainer, Dictionary personKeyToRanges, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> idThenNormalizedRectangleToPersonContainers) { if (configuration is null) throw new NullReferenceException(nameof(configuration)); @@ -612,9 +624,9 @@ internal abstract class MapLogic Dictionary> idToMappingCollection = new(); Dictionary personKeyFormattedToNewestPersonKeyFormatted = new(); List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer = new(); - List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedPixelPercentageCollection = new(); - List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection = new(); - Dictionary> incorrectIdThenNormalizedPixelPercentageToPersonContainers = new(); + List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedRectangleCollection = new(); + List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection = new(); + Dictionary> incorrectIdThenNormalizedRectangleToPersonContainers = new(); SetPersonCollections(configuration, personContainers, personKeys, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection, skipCollection); personContainers.AddRange(AddToPersonKeysThenGetNonSpecificPeopleCollection(configuration, personKeys)); foreach (Mapping mapping in mappingCollection) @@ -627,14 +639,14 @@ internal abstract class MapLogic string[] ticksDirectories = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly); message = $") {ticksDirectories.Length:000} compile from and clean ticks Director(ies) - B - {totalSeconds} total second(s)"; List<(string, string[], string)> collection = DeleteEmptyDirectoriesAndGetCollection(configuration, personKeyFormattedCollection, ticksDirectories, message); - (int unableToMatchCount, int duplicateCount) = SetCollectionsAndGetUnableToMatchCount(configuration, ticks, idToMappingCollection, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedIdThenNormalizedPixelPercentageCollection, incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, collection); - SetKeyValuePairs(configuration, ticks, personContainers, mappingCollection, personKeyFormattedIdThenNormalizedPixelPercentageCollection, incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, personKeyToPersonContainer, idThenNormalizedPixelPercentageToPersonContainers, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer, incorrectIdThenNormalizedPixelPercentageToPersonContainers, personKeyToRanges); + (int unableToMatchCount, int duplicateCount) = SetCollectionsAndGetUnableToMatchCount(configuration, ticks, idToMappingCollection, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedIdThenNormalizedRectangleCollection, incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection, collection); + SetKeyValuePairs(configuration, ticks, personContainers, mappingCollection, personKeyFormattedIdThenNormalizedRectangleCollection, incorrectPersonKeyFormattedIdThenNormalizedRectangleCollection, personKeyToPersonContainer, idThenNormalizedRectangleToPersonContainers, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer, incorrectIdThenNormalizedRectangleToPersonContainers, personKeyToRanges); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); message = $") {collection.Count:000} message from ticks Director(ies) - D - {duplicateCount} Duplicate Count {unableToMatchCount} Unable To Match Count / {collection.Count} Collection - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using (ProgressBar progressBar = new(collection.Count, message, options)) { - foreach (KeyValuePair> keyValuePair in idThenNormalizedPixelPercentageToPersonContainers) + foreach (KeyValuePair> keyValuePair in idThenNormalizedRectangleToPersonContainers) { progressBar.Tick(); foreach (KeyValuePair keyValue in keyValuePair.Value) @@ -644,7 +656,7 @@ internal abstract class MapLogic long[] personKeyCollection = (from l in nullablePersonKeyCollection where l is not null select l.Value).Distinct().ToArray(); SetPersonKeyToPersonContainer(configuration, personContainers, personKeyCollection, personKeyToPersonContainer); notMappedPersonContainers.AddRange(GetNotMappedPersonContainers(configuration, personContainers, personKeyCollection)); - AppendToSkipCollection(skipCollection, idThenNormalizedPixelPercentageToPersonContainers, incorrectIdThenNormalizedPixelPercentageToPersonContainers); + AppendToSkipCollection(skipCollection, idThenNormalizedRectangleToPersonContainers, incorrectIdThenNormalizedRectangleToPersonContainers); if (possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Any()) mapLogicSupport.SavePossiblyNewPersonContainers(propertyConfiguration, configuration.PersonBirthdayFormat, configuration.FacesFileNameExtension, a2PeopleContentDirectory, personKeyToPersonContainer, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); } @@ -690,7 +702,7 @@ internal abstract class MapLogic internal static SaveContainer GetDebugSaveContainer(string directory, SortingContainer sortingContainer, Mapping mapping) { SaveContainer result; - FileHolder faceFileHolder = new($"C:/{sortingContainer.Sorting.Id}.{sortingContainer.Sorting.NormalizedPixelPercentage}"); + FileHolder faceFileHolder = new($"C:/{sortingContainer.Sorting.Id}.{sortingContainer.Sorting.NormalizedRectangle}"); string shortcutFile = Path.Combine(directory, $"{sortingContainer.Mapping.MappingFromLocation.DeterministicHashCodeKey}{sortingContainer.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}.debug.lnk"); result = new(directory, faceFileHolder, mapping.MappingFromItem.ResizedFileHolder, shortcutFile); return result; diff --git a/Metadata/Metadata.csproj b/Metadata/Metadata.csproj index f98ce14..93bd060 100644 --- a/Metadata/Metadata.csproj +++ b/Metadata/Metadata.csproj @@ -36,7 +36,7 @@ - + diff --git a/Metadata/Models/B_Metadata.cs b/Metadata/Models/B_Metadata.cs index d521e14..b6ee581 100644 --- a/Metadata/Models/B_Metadata.cs +++ b/Metadata/Models/B_Metadata.cs @@ -95,22 +95,11 @@ public class B_Metadata { List> results = new(); string json = string.Empty; - string[] changesFrom = Array.Empty(); Dictionary>>? dictionary; + string[] changesFrom = new string[] { nameof(Property.Models.A_Property) }; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); string bMetadataSingletonFile = Path.Combine(bResultsFullGroupDirectory, "{}", configuration.ResultAllInOne, $"{mappingFromItem.Id}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json"); FileInfo fileInfo = new(bMetadataSingletonFile); - if (!fileInfo.FullName.Contains(configuration.ResultAllInOne) && !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 (_ForceMetadataLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) { File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); diff --git a/Metadata/Models/Stateless/IMetadata.cs b/Metadata/Models/Stateless/IMetadata.cs index 1821fcd..211bf0a 100644 --- a/Metadata/Models/Stateless/IMetadata.cs +++ b/Metadata/Models/Stateless/IMetadata.cs @@ -8,9 +8,9 @@ public interface IMetadata static string? GetFaceEncoding(string file) => Metadata.GetFaceEncoding(file); - string? TestStatic_GetFaceLocation(string file) => - GetFaceLocation(file); - static string? GetFaceLocation(string file) => - Metadata.GetFaceLocation(file); + string? TestStatic_GetFaceX(string file) => + GetFaceX(file); + static string? GetFaceX(string file) => + Metadata.GetFaceX(file); } \ No newline at end of file diff --git a/Metadata/Models/Stateless/Metadata.cs b/Metadata/Models/Stateless/Metadata.cs index a2b83e7..a43ea01 100644 --- a/Metadata/Models/Stateless/Metadata.cs +++ b/Metadata/Models/Stateless/Metadata.cs @@ -29,7 +29,7 @@ internal class Metadata return result; } - internal static string? GetFaceLocation(string file) + internal static string? GetFaceX(string file) { string? result; List results = new(); diff --git a/Not-Copy-Copy/Models/Configuration.cs b/Not-Copy-Copy/Models/Configuration.cs index 3431f46..11b2458 100644 --- a/Not-Copy-Copy/Models/Configuration.cs +++ b/Not-Copy-Copy/Models/Configuration.cs @@ -32,9 +32,9 @@ public class Configuration public void Set(Property.Models.Configuration configuration) => _PropertyConfiguration = configuration; - public void SetAndUpdate(Property.Models.Configuration configuration, int? numberOfJitters, int? numberOfTimesToUpsample, string? modelName, string? predictorModelName) + public void SetAndUpdate(Property.Models.Configuration configuration) { - _PropertyConfiguration.Update(numberOfJitters, numberOfTimesToUpsample, modelName, predictorModelName); + _PropertyConfiguration.Update(); _CompareSource = Path.GetFullPath(_CompareSource); _SelectedSource = Path.GetFullPath(_SelectedSource); _EmptyDestination = Path.GetFullPath(_EmptyDestination); diff --git a/Not-Copy-Copy/Models/Stateless/Configuration.cs b/Not-Copy-Copy/Models/Stateless/Configuration.cs index 676e9f5..88e8d0b 100644 --- a/Not-Copy-Copy/Models/Stateless/Configuration.cs +++ b/Not-Copy-Copy/Models/Stateless/Configuration.cs @@ -19,7 +19,7 @@ public abstract class Configuration if (result is null) throw new Exception(json); string jsonThis = result.ToString(); - result.SetAndUpdate(propertyConfiguration, null, null, null, null); + result.SetAndUpdate(propertyConfiguration); if (jsonThis != json) { int? check = null; diff --git a/Not-Copy-Copy/Not-Copy-Copy.cs b/Not-Copy-Copy/Not-Copy-Copy.cs index 065b16f..04b1d9e 100644 --- a/Not-Copy-Copy/Not-Copy-Copy.cs +++ b/Not-Copy-Copy/Not-Copy-Copy.cs @@ -26,8 +26,9 @@ public class NotCopyCopy _IsEnvironment = isEnvironment; _Log = Serilog.Log.ForContext(); Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); - Property.Models.Configuration.Verify(propertyConfiguration, requireExist: true); Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); + _Log.Information(propertyConfiguration.RootDirectory); + Property.Models.Configuration.Verify(propertyConfiguration, requireExist: true); Verify(configuration); bool reverse = false; string outputExtension = ".jpg"; diff --git a/Not-Copy-Copy/Not-Copy-Copy.csproj b/Not-Copy-Copy/Not-Copy-Copy.csproj index fd3aac3..6d32614 100644 --- a/Not-Copy-Copy/Not-Copy-Copy.csproj +++ b/Not-Copy-Copy/Not-Copy-Copy.csproj @@ -35,8 +35,8 @@ - - + + @@ -45,7 +45,7 @@ - + diff --git a/Not-Copy-Copy/Program.cs b/Not-Copy-Copy/Program.cs index 7ca1a71..1703672 100644 --- a/Not-Copy-Copy/Program.cs +++ b/Not-Copy-Copy/Program.cs @@ -19,6 +19,7 @@ public class Program IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); IConfigurationRoot configurationRoot = configurationBuilder.Build(); AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); diff --git a/PrepareForOld/Models/Configuration.cs b/PrepareForOld/Models/Configuration.cs index 530d0cb..49d4c22 100644 --- a/PrepareForOld/Models/Configuration.cs +++ b/PrepareForOld/Models/Configuration.cs @@ -24,10 +24,10 @@ public class Configuration return result; } - public void SetAndUpdate(Property.Models.Configuration configuration, int? numberOfJitters, int? numberOfTimesToUpsample, string? modelName, string? predictorModelName) + public void SetAndUpdate(Property.Models.Configuration configuration) { _PropertyConfiguration = configuration; - _PropertyConfiguration.Update(numberOfJitters, numberOfTimesToUpsample, modelName, predictorModelName); + _PropertyConfiguration.Update(); } } \ No newline at end of file diff --git a/PrepareForOld/Models/Stateless/Configuration.cs b/PrepareForOld/Models/Stateless/Configuration.cs index 61f3c47..44d7910 100644 --- a/PrepareForOld/Models/Stateless/Configuration.cs +++ b/PrepareForOld/Models/Stateless/Configuration.cs @@ -19,7 +19,7 @@ public abstract class Configuration if (result is null) throw new Exception(json); string jsonThis = result.ToString(); - result.SetAndUpdate(propertyConfiguration, null, null, null, null); + result.SetAndUpdate(propertyConfiguration); if (jsonThis != json) { int? check = null; diff --git a/PrepareForOld/PrepareForOld.cs b/PrepareForOld/PrepareForOld.cs index c311fed..2a32434 100644 --- a/PrepareForOld/PrepareForOld.cs +++ b/PrepareForOld/PrepareForOld.cs @@ -1,658 +1,658 @@ -using Microsoft.Extensions.Configuration; -using Phares.Shared; -using System.Text.Json; -using System.Text.RegularExpressions; -using View_by_Distance.PrepareForOld.Models; -using View_by_Distance.Shared.Models.Methods; +// using Microsoft.Extensions.Configuration; +// using Phares.Shared; +// using System.Text.Json; +// using System.Text.RegularExpressions; +// using View_by_Distance.PrepareForOld.Models; +// using View_by_Distance.Shared.Models.Methods; -namespace View_by_Distance.PrepareForOld; +// namespace View_by_Distance.PrepareForOld; -public class PrepareForOld -{ +// public class PrepareForOld +// { - private readonly Serilog.ILogger? _Log; - private readonly AppSettings _AppSettings; - private readonly List _Exceptions; - private readonly IsEnvironment _IsEnvironment; - private readonly Configuration _Configuration; - private readonly List> _FileKeyValuePairs; - private readonly List<(string Find, string Replace)> _SpellingFindReplace; - private readonly Dictionary>> _FilePropertiesKeyValuePairs; +// private readonly Serilog.ILogger? _Log; +// private readonly AppSettings _AppSettings; +// private readonly List _Exceptions; +// private readonly IsEnvironment _IsEnvironment; +// private readonly Configuration _Configuration; +// private readonly List> _FileKeyValuePairs; +// private readonly List<(string Find, string Replace)> _SpellingFindReplace; +// private readonly Dictionary>> _FilePropertiesKeyValuePairs; - public PrepareForOld(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) - { - if (isSilent) - { } - if (console is null) - { } - string spellingA; - string spellingB; - _AppSettings = appSettings; - _SpellingFindReplace = new(); - _IsEnvironment = isEnvironment; - _Exceptions = new List(); - _Log = Serilog.Log.ForContext(); - _FileKeyValuePairs = new List>(); - _FilePropertiesKeyValuePairs = new Dictionary>>(); - Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); - Property.Models.Configuration.Verify(propertyConfiguration, requireExist: true); - Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); - Verify(configuration); - if (propertyConfiguration.IgnoreExtensions is null) - throw new NullReferenceException(nameof(propertyConfiguration.IgnoreExtensions)); - for (int i = 0; i < configuration.Spelling.Length; i++) - { - spellingA = configuration.Spelling[i]; - spellingB = configuration.Spelling[i + 1]; - if (spellingB.Contains(spellingA)) - throw new Exception("Change configuration!"); - _SpellingFindReplace.Add(new(spellingA, spellingB)); - i += 1; - } - string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories); - foreach (string dbFile in dbFiles) - File.Delete(dbFile); - string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(Property.Models.A_Property), "{}"); - if (!Directory.Exists(aPropertySingletonDirectory)) - throw new Exception(aPropertySingletonDirectory); - ConsoleKey? consoleKey = null; - for (int y = 0; y < int.MaxValue; y++) - { - _Log.Information($"Execute {nameof(VerifyAgainstIndexInfoJsonFiles)} \"Y(es)\" or \"N(o)\"?"); - consoleKey = Console.ReadKey().Key; - if (consoleKey is ConsoleKey.Y or ConsoleKey.N) - break; - } - _Log.Information(". . ."); - if (consoleKey == ConsoleKey.Y) - VerifyAgainstIndexInfoJsonFiles(propertyConfiguration, aPropertySingletonDirectory); - for (int y = 0; y < int.MaxValue; y++) - { - _Log.Information($"Execute {nameof(SaveTabSeparatedValues)} \"Y(es)\" or \"N(o)\"?"); - consoleKey = Console.ReadKey().Key; - if (consoleKey is ConsoleKey.Y or ConsoleKey.N) - break; - } - _Log.Information(". . ."); - if (consoleKey == ConsoleKey.Y) - SaveTabSeparatedValues(propertyConfiguration, aPropertySingletonDirectory); - for (int y = 0; y < int.MaxValue; y++) - { - _Log.Information($"Execute {nameof(ReSaveJsonFiles)} \"Y(es)\" or \"N(o)\"?"); - consoleKey = Console.ReadKey().Key; - if (consoleKey is ConsoleKey.Y or ConsoleKey.N) - break; - } - _Log.Information(". . ."); - if (consoleKey == ConsoleKey.Y) - ReSaveJsonFiles(); - for (int y = 0; y < int.MaxValue; y++) - { - _Log.Information($"Execute {nameof(CopyMissingImagesLogs)} \"Y(es)\" or \"N(o)\"?"); - consoleKey = Console.ReadKey().Key; - if (consoleKey is ConsoleKey.Y or ConsoleKey.N) - break; - } - _Log.Information(". . ."); - if (consoleKey == ConsoleKey.Y) - CopyMissingImagesLogs(); - 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); - _Configuration = configuration; - } +// public PrepareForOld(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) +// { +// if (isSilent) +// { } +// if (console is null) +// { } +// string spellingA; +// string spellingB; +// _AppSettings = appSettings; +// _SpellingFindReplace = new(); +// _IsEnvironment = isEnvironment; +// _Exceptions = new List(); +// _Log = Serilog.Log.ForContext(); +// _FileKeyValuePairs = new List>(); +// _FilePropertiesKeyValuePairs = new Dictionary>>(); +// Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); +// Property.Models.Configuration.Verify(propertyConfiguration, requireExist: true); +// Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); +// Verify(configuration); +// if (propertyConfiguration.IgnoreExtensions is null) +// throw new NullReferenceException(nameof(propertyConfiguration.IgnoreExtensions)); +// for (int i = 0; i < configuration.Spelling.Length; i++) +// { +// spellingA = configuration.Spelling[i]; +// spellingB = configuration.Spelling[i + 1]; +// if (spellingB.Contains(spellingA)) +// throw new Exception("Change configuration!"); +// _SpellingFindReplace.Add(new(spellingA, spellingB)); +// i += 1; +// } +// string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories); +// foreach (string dbFile in dbFiles) +// File.Delete(dbFile); +// string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(Property.Models.A_Property), "{}"); +// if (!Directory.Exists(aPropertySingletonDirectory)) +// throw new Exception(aPropertySingletonDirectory); +// ConsoleKey? consoleKey = null; +// for (int y = 0; y < int.MaxValue; y++) +// { +// _Log.Information($"Execute {nameof(VerifyAgainstIndexInfoJsonFiles)} \"Y(es)\" or \"N(o)\"?"); +// consoleKey = Console.ReadKey().Key; +// if (consoleKey is ConsoleKey.Y or ConsoleKey.N) +// break; +// } +// _Log.Information(". . ."); +// if (consoleKey == ConsoleKey.Y) +// VerifyAgainstIndexInfoJsonFiles(propertyConfiguration, aPropertySingletonDirectory); +// for (int y = 0; y < int.MaxValue; y++) +// { +// _Log.Information($"Execute {nameof(SaveTabSeparatedValues)} \"Y(es)\" or \"N(o)\"?"); +// consoleKey = Console.ReadKey().Key; +// if (consoleKey is ConsoleKey.Y or ConsoleKey.N) +// break; +// } +// _Log.Information(". . ."); +// if (consoleKey == ConsoleKey.Y) +// SaveTabSeparatedValues(propertyConfiguration, aPropertySingletonDirectory); +// for (int y = 0; y < int.MaxValue; y++) +// { +// _Log.Information($"Execute {nameof(ReSaveJsonFiles)} \"Y(es)\" or \"N(o)\"?"); +// consoleKey = Console.ReadKey().Key; +// if (consoleKey is ConsoleKey.Y or ConsoleKey.N) +// break; +// } +// _Log.Information(". . ."); +// if (consoleKey == ConsoleKey.Y) +// ReSaveJsonFiles(); +// for (int y = 0; y < int.MaxValue; y++) +// { +// _Log.Information($"Execute {nameof(CopyMissingImagesLogs)} \"Y(es)\" or \"N(o)\"?"); +// consoleKey = Console.ReadKey().Key; +// if (consoleKey is ConsoleKey.Y or ConsoleKey.N) +// break; +// } +// _Log.Information(". . ."); +// if (consoleKey == ConsoleKey.Y) +// CopyMissingImagesLogs(); +// 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); +// _Configuration = configuration; +// } - private static void Verify(Configuration configuration) - { - if (configuration.Spelling is null || !configuration.Spelling.Any()) - throw new NullReferenceException(nameof(configuration.Spelling)); - } +// private static void Verify(Configuration configuration) +// { +// if (configuration.Spelling is null || !configuration.Spelling.Any()) +// throw new NullReferenceException(nameof(configuration.Spelling)); +// } - private static List GetExifCollection(string infoDirectory, string infoDirectoryExtra, bool checkDistinct) - { - List results = new(); - string json; - Models.SaveTabSeparatedValues.ImageExifInfo[]? exifCollection; - List exifInfoFiles = Directory.GetFiles(infoDirectory, "ImageExifInfo.json", SearchOption.AllDirectories).ToList(); - if (!string.IsNullOrEmpty(infoDirectoryExtra)) - exifInfoFiles.AddRange(Directory.GetFiles(infoDirectoryExtra, "ImageExifInfo.json", SearchOption.AllDirectories)); - foreach (string exifInfoFile in exifInfoFiles) - { - json = File.ReadAllText(exifInfoFile); - exifCollection = JsonSerializer.Deserialize(json); - if (exifCollection is null) - continue; - results.AddRange(exifCollection); - } - if (checkDistinct) - { - int[] check = (from l in results select l.Index).Distinct().ToArray(); - if (check.Length != results.Count) - throw new Exception(); - } - return results; - } +// private static List GetExifCollection(string infoDirectory, string infoDirectoryExtra, bool checkDistinct) +// { +// List results = new(); +// string json; +// Models.SaveTabSeparatedValues.ImageExifInfo[]? exifCollection; +// List exifInfoFiles = Directory.GetFiles(infoDirectory, "ImageExifInfo.json", SearchOption.AllDirectories).ToList(); +// if (!string.IsNullOrEmpty(infoDirectoryExtra)) +// exifInfoFiles.AddRange(Directory.GetFiles(infoDirectoryExtra, "ImageExifInfo.json", SearchOption.AllDirectories)); +// foreach (string exifInfoFile in exifInfoFiles) +// { +// json = File.ReadAllText(exifInfoFile); +// exifCollection = JsonSerializer.Deserialize(json); +// if (exifCollection is null) +// continue; +// results.AddRange(exifCollection); +// } +// if (checkDistinct) +// { +// int[] check = (from l in results select l.Index).Distinct().ToArray(); +// if (check.Length != results.Count) +// throw new Exception(); +// } +// return results; +// } - private List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> GetIndexCollection(string infoDirectory, string infoDirectoryExtra, bool checkDistinct) - { - List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> results = new(); - if (_Configuration?.PropertyConfiguration is null) - throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - long ticks; - string json; - string extension; - string corrected; - string regexResult; - string relativeDirectory; - List dateTimes; - string fileNameWithoutExtension; - string firstFileSegmentCollection; - DateTime? dateTimeFromName = null; - Dictionary keyValuePairs = new(); - Models.SaveTabSeparatedValues.IndexInfo[]? indexCollection; - List exifCollection = GetExifCollection(infoDirectory, infoDirectoryExtra, checkDistinct); - List indexInfoFiles = Directory.GetFiles(infoDirectory, "IndexInfo.json", SearchOption.AllDirectories).ToList(); - if (!string.IsNullOrEmpty(infoDirectoryExtra)) - indexInfoFiles.AddRange(Directory.GetFiles(infoDirectoryExtra, "IndexInfo.json", SearchOption.AllDirectories)); - foreach (Models.SaveTabSeparatedValues.ImageExifInfo exifInfo in exifCollection) - { - dateTimes = Shared.Models.Stateless.Methods.IProperty.GetDateTimes(exifInfo.CreationTime, exifInfo.LastWriteTime, exifInfo.DateTime, dateTimeFromName, exifInfo.DateTimeDigitized, exifInfo.DateTimeOriginal, exifInfo.GPSDateStamp); - if (!checkDistinct && keyValuePairs.ContainsKey(exifInfo.Index)) - continue; - keyValuePairs.Add(exifInfo.Index, dateTimes.Min().Ticks); - } - foreach (string indexInfoFile in indexInfoFiles) - { - json = File.ReadAllText(indexInfoFile); - indexCollection = JsonSerializer.Deserialize(json); - if (indexCollection is null) - continue; - foreach (Models.SaveTabSeparatedValues.IndexInfo indexInfo in indexCollection) - { - if (indexInfo.FileSegmentCollection is null) - continue; - // if (indexInfo.FileSegmentCollection.Length != 1) - // continue; - ticks = keyValuePairs[indexInfo.Index]; - firstFileSegmentCollection = indexInfo.FileSegmentCollection[0]; - extension = Path.GetExtension(firstFileSegmentCollection); - fileNameWithoutExtension = Path.GetFileNameWithoutExtension(firstFileSegmentCollection); - corrected = firstFileSegmentCollection[..(firstFileSegmentCollection.Length - extension.Length)]; - relativeDirectory = firstFileSegmentCollection[..(firstFileSegmentCollection.Length - fileNameWithoutExtension.Length - extension.Length)]; - if ((from l in _SpellingFindReplace where corrected.Contains(l.Find) select true).Any()) - { - foreach ((string find, string replace) in _SpellingFindReplace) - corrected = corrected.Replace(find, replace); - } - if (string.IsNullOrEmpty(_Configuration.PropertyConfiguration.Pattern)) - regexResult = corrected; - else - regexResult = Regex.Replace(corrected, _Configuration.PropertyConfiguration.Pattern, string.Empty); - results.Add(new(indexInfo.Index, ticks, relativeDirectory, fileNameWithoutExtension, extension, regexResult)); - } - } - return results; - } +// private List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> GetIndexCollection(string infoDirectory, string infoDirectoryExtra, bool checkDistinct) +// { +// List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> results = new(); +// if (_Configuration?.PropertyConfiguration is null) +// throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); +// long ticks; +// string json; +// string extension; +// string corrected; +// string regexResult; +// string relativeDirectory; +// List dateTimes; +// string fileNameWithoutExtension; +// string firstFileSegmentCollection; +// DateTime? dateTimeFromName = null; +// Dictionary keyValuePairs = new(); +// Models.SaveTabSeparatedValues.IndexInfo[]? indexCollection; +// List exifCollection = GetExifCollection(infoDirectory, infoDirectoryExtra, checkDistinct); +// List indexInfoFiles = Directory.GetFiles(infoDirectory, "IndexInfo.json", SearchOption.AllDirectories).ToList(); +// if (!string.IsNullOrEmpty(infoDirectoryExtra)) +// indexInfoFiles.AddRange(Directory.GetFiles(infoDirectoryExtra, "IndexInfo.json", SearchOption.AllDirectories)); +// foreach (Models.SaveTabSeparatedValues.ImageExifInfo exifInfo in exifCollection) +// { +// dateTimes = Shared.Models.Stateless.Methods.IProperty.GetDateTimes(exifInfo.CreationTime, exifInfo.LastWriteTime, exifInfo.DateTime, dateTimeFromName, exifInfo.DateTimeDigitized, exifInfo.DateTimeOriginal, exifInfo.GPSDateStamp); +// if (!checkDistinct && keyValuePairs.ContainsKey(exifInfo.Index)) +// continue; +// keyValuePairs.Add(exifInfo.Index, dateTimes.Min().Ticks); +// } +// foreach (string indexInfoFile in indexInfoFiles) +// { +// json = File.ReadAllText(indexInfoFile); +// indexCollection = JsonSerializer.Deserialize(json); +// if (indexCollection is null) +// continue; +// foreach (Models.SaveTabSeparatedValues.IndexInfo indexInfo in indexCollection) +// { +// if (indexInfo.FileSegmentCollection is null) +// continue; +// // if (indexInfo.FileSegmentCollection.Length != 1) +// // continue; +// ticks = keyValuePairs[indexInfo.Index]; +// firstFileSegmentCollection = indexInfo.FileSegmentCollection[0]; +// extension = Path.GetExtension(firstFileSegmentCollection); +// fileNameWithoutExtension = Path.GetFileNameWithoutExtension(firstFileSegmentCollection); +// corrected = firstFileSegmentCollection[..(firstFileSegmentCollection.Length - extension.Length)]; +// relativeDirectory = firstFileSegmentCollection[..(firstFileSegmentCollection.Length - fileNameWithoutExtension.Length - extension.Length)]; +// if ((from l in _SpellingFindReplace where corrected.Contains(l.Find) select true).Any()) +// { +// foreach ((string find, string replace) in _SpellingFindReplace) +// corrected = corrected.Replace(find, replace); +// } +// if (string.IsNullOrEmpty(_Configuration.PropertyConfiguration.Pattern)) +// regexResult = corrected; +// else +// regexResult = Regex.Replace(corrected, _Configuration.PropertyConfiguration.Pattern, string.Empty); +// results.Add(new(indexInfo.Index, ticks, relativeDirectory, fileNameWithoutExtension, extension, regexResult)); +// } +// } +// return results; +// } - private static List GetUseTabSeparatedValueIndices(string useDirectory) - { - List results = new(); - string[] lines; - string[] segments; - string[] tabSeparatedValueFiles = Directory.GetFiles(useDirectory, "*.tsv", SearchOption.TopDirectoryOnly); - foreach (string tabSeparatedValueFile in tabSeparatedValueFiles) - { - lines = File.ReadAllLines(tabSeparatedValueFile); - foreach (string line in lines) - { - if (string.IsNullOrEmpty(line)) - continue; - segments = line.Split('\t'); - if (segments.Length < 1) - continue; - if (!int.TryParse(segments[0], out int index)) - continue; - results.Add(index); - } - } - return results.Distinct().OrderBy(l => l).ToList(); - } +// private static List GetUseTabSeparatedValueIndices(string useDirectory) +// { +// List results = new(); +// string[] lines; +// string[] segments; +// string[] tabSeparatedValueFiles = Directory.GetFiles(useDirectory, "*.tsv", SearchOption.TopDirectoryOnly); +// foreach (string tabSeparatedValueFile in tabSeparatedValueFiles) +// { +// lines = File.ReadAllLines(tabSeparatedValueFile); +// foreach (string line in lines) +// { +// if (string.IsNullOrEmpty(line)) +// continue; +// segments = line.Split('\t'); +// if (segments.Length < 1) +// continue; +// if (!int.TryParse(segments[0], out int index)) +// continue; +// results.Add(index); +// } +// } +// return results.Distinct().OrderBy(l => l).ToList(); +// } - private void SaveTabSeparatedValues(Property.Models.Configuration configuration, string aPropertySingletonDirectory) - { - if (_Log is null) - throw new NullReferenceException(nameof(_Log)); - if (_Configuration?.PropertyConfiguration is null) - throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory); - if (string.IsNullOrEmpty(rootDirectoryParent)) - throw new NullReferenceException(nameof(rootDirectoryParent)); - int z = 0; - int mappedIndex; - int? propertyId; - long? propertyTicks; - int loadLessThan = 7; - string useDirectory = Path.Combine(rootDirectoryParent, "Use - =="); - if (!Directory.Exists(useDirectory)) - _ = Directory.CreateDirectory(useDirectory); - string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp"); - if (!Directory.Exists(tempDirectory)) - _ = Directory.CreateDirectory(tempDirectory); - string diffRootDirectory = string.Empty; - List duplicates = new(); - string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared"); - string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json"); - string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07"); - string infoDirectoryExtra = Path.Combine(imageSharedDirectory, "Images - 4) Info - - - Extra", "2022-04-14"); - List mappedIndices = GetUseTabSeparatedValueIndices(useDirectory); - List<(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)> collection = new(); - PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory); - PropertyCompare.Models.PropertyCompare[] propertyCompareCollection = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan, duplicates, deleteExtension: false); - { - long ticks = DateTime.Now.Ticks; - string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray(); - string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(Property.Models.A_Property), "[{}]"); - File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines); - string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true }); - File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json); - } - List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryExtra, checkDistinct: true); - foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection) - { - z += 1; - if (_IsEnvironment.Development && z % 1000 == 0) - _Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}"); - propertyId = null; - propertyTicks = null; - foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompareCollection) - { - if (propertyCompare?.Property?.Id is null) - continue; - if (ticks != propertyCompare.MinimumDateTime.Ticks) - { - // if (ticks > propertyCompare.MinimumDateTime.AddHours(18).Ticks || ticks < propertyCompare.MinimumDateTime.AddHours(-18).Ticks) - continue; - } - if (!regexResult.Equals(propertyCompare.RegexResult, StringComparison.CurrentCultureIgnoreCase)) - continue; - propertyId = propertyCompare.Property.Id; - propertyTicks = propertyCompare.MinimumDateTime.Ticks; - mappedIndex = mappedIndices.IndexOf(index); - if (mappedIndex > -1) - mappedIndices.RemoveAt(mappedIndex); - break; - } - collection.Add(new(index, relativeDirectory, $"{fileNameWithoutExtension}{extension}", regexResult, ticks, propertyId, propertyTicks)); - } - (int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] matched = (from l in collection where l.PropertyId.HasValue select l).ToArray(); - (int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] notMatched = (from l in collection where l.PropertyId is null select l).ToArray(); - string[] duplicatesLines = ( - from l - in duplicates - select $"{l.Property.Id}\t{l.RegexResult}\t{l.MinimumDateTime:yyyy-MM-dd_HH-mm-ss}\t{l.MinimumDateTime}\t{l.RelativeDirectory}\t{l.FileNameWithoutExtension}{l.Extension}.___" - ).ToArray(); - string[] matchedLines = ( - from l - in matched - select $"{l.Index}\t{l.PropertyId}\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t{l.PropertyTicks}\t{l.RelativeDirectory}\t{l.FileName}" - ).ToArray(); - List notMatchedLines = ( - from l - in notMatched - where !mappedIndices.Contains(l.Index) - select $"{l.Index}\t______________\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t_________________\t{l.RelativeDirectory}\t{l.FileName}" - ).ToList(); - { - long ticks = DateTime.Now.Ticks; - notMatchedLines.AddRange(from l in mappedIndices select $"{l}\tFrom other files"); - File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}.tsv", matchedLines); - File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}.txt", duplicatesLines); - File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}-Not.tsv", notMatchedLines); - } - _Log.Debug($"Done with {nameof(SaveTabSeparatedValues)}"); - } +// private void SaveTabSeparatedValues(Property.Models.Configuration configuration, string aPropertySingletonDirectory) +// { +// if (_Log is null) +// throw new NullReferenceException(nameof(_Log)); +// if (_Configuration?.PropertyConfiguration is null) +// throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); +// string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory); +// if (string.IsNullOrEmpty(rootDirectoryParent)) +// throw new NullReferenceException(nameof(rootDirectoryParent)); +// int z = 0; +// int mappedIndex; +// int? propertyId; +// long? propertyTicks; +// int loadLessThan = 7; +// string useDirectory = Path.Combine(rootDirectoryParent, "Use - =="); +// if (!Directory.Exists(useDirectory)) +// _ = Directory.CreateDirectory(useDirectory); +// string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp"); +// if (!Directory.Exists(tempDirectory)) +// _ = Directory.CreateDirectory(tempDirectory); +// string diffRootDirectory = string.Empty; +// List duplicates = new(); +// string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared"); +// string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json"); +// string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07"); +// string infoDirectoryExtra = Path.Combine(imageSharedDirectory, "Images - 4) Info - - - Extra", "2022-04-14"); +// List mappedIndices = GetUseTabSeparatedValueIndices(useDirectory); +// List<(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)> collection = new(); +// PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory); +// PropertyCompare.Models.PropertyCompare[] propertyCompareCollection = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan, duplicates, deleteExtension: false); +// { +// long ticks = DateTime.Now.Ticks; +// string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray(); +// string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(Property.Models.A_Property), "[{}]"); +// File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines); +// string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true }); +// File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json); +// } +// List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryExtra, checkDistinct: true); +// foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection) +// { +// z += 1; +// if (_IsEnvironment.Development && z % 1000 == 0) +// _Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}"); +// propertyId = null; +// propertyTicks = null; +// foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompareCollection) +// { +// if (propertyCompare?.Property?.Id is null) +// continue; +// if (ticks != propertyCompare.MinimumDateTime.Ticks) +// { +// // if (ticks > propertyCompare.MinimumDateTime.AddHours(18).Ticks || ticks < propertyCompare.MinimumDateTime.AddHours(-18).Ticks) +// continue; +// } +// if (!regexResult.Equals(propertyCompare.RegexResult, StringComparison.CurrentCultureIgnoreCase)) +// continue; +// propertyId = propertyCompare.Property.Id; +// propertyTicks = propertyCompare.MinimumDateTime.Ticks; +// mappedIndex = mappedIndices.IndexOf(index); +// if (mappedIndex > -1) +// mappedIndices.RemoveAt(mappedIndex); +// break; +// } +// collection.Add(new(index, relativeDirectory, $"{fileNameWithoutExtension}{extension}", regexResult, ticks, propertyId, propertyTicks)); +// } +// (int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] matched = (from l in collection where l.PropertyId.HasValue select l).ToArray(); +// (int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] notMatched = (from l in collection where l.PropertyId is null select l).ToArray(); +// string[] duplicatesLines = ( +// from l +// in duplicates +// select $"{l.Property.Id}\t{l.RegexResult}\t{l.MinimumDateTime:yyyy-MM-dd_HH-mm-ss}\t{l.MinimumDateTime}\t{l.RelativeDirectory}\t{l.FileNameWithoutExtension}{l.Extension}.___" +// ).ToArray(); +// string[] matchedLines = ( +// from l +// in matched +// select $"{l.Index}\t{l.PropertyId}\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t{l.PropertyTicks}\t{l.RelativeDirectory}\t{l.FileName}" +// ).ToArray(); +// List notMatchedLines = ( +// from l +// in notMatched +// where !mappedIndices.Contains(l.Index) +// select $"{l.Index}\t______________\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t_________________\t{l.RelativeDirectory}\t{l.FileName}" +// ).ToList(); +// { +// long ticks = DateTime.Now.Ticks; +// notMatchedLines.AddRange(from l in mappedIndices select $"{l}\tFrom other files"); +// File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}.tsv", matchedLines); +// File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}.txt", duplicatesLines); +// File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}-Not.tsv", notMatchedLines); +// } +// _Log.Debug($"Done with {nameof(SaveTabSeparatedValues)}"); +// } - private static void GetUseTabSeparatedValueLines(string useDirectory, Dictionary> mappedLines) - { - string[] lines; - string[] segments; - string useDirectoryName = Path.GetFileName(useDirectory).Split('-')[1].Trim(); - string[] tabSeparatedValueFiles = Directory.GetFiles(useDirectory, "*.tsv", SearchOption.TopDirectoryOnly); - foreach (string tabSeparatedValueFile in tabSeparatedValueFiles) - { - lines = File.ReadAllLines(tabSeparatedValueFile); - foreach (string line in lines) - { - if (string.IsNullOrEmpty(line)) - continue; - segments = line.Split('\t'); - if (segments.Length < 1) - continue; - if (!int.TryParse(segments[0], out int index)) - continue; - if (!mappedLines.ContainsKey(index)) - mappedLines.Add(index, new()); - mappedLines[index].Add($"{line},\t{useDirectoryName}"); - } - } - } +// private static void GetUseTabSeparatedValueLines(string useDirectory, Dictionary> mappedLines) +// { +// string[] lines; +// string[] segments; +// string useDirectoryName = Path.GetFileName(useDirectory).Split('-')[1].Trim(); +// string[] tabSeparatedValueFiles = Directory.GetFiles(useDirectory, "*.tsv", SearchOption.TopDirectoryOnly); +// foreach (string tabSeparatedValueFile in tabSeparatedValueFiles) +// { +// lines = File.ReadAllLines(tabSeparatedValueFile); +// foreach (string line in lines) +// { +// if (string.IsNullOrEmpty(line)) +// continue; +// segments = line.Split('\t'); +// if (segments.Length < 1) +// continue; +// if (!int.TryParse(segments[0], out int index)) +// continue; +// if (!mappedLines.ContainsKey(index)) +// mappedLines.Add(index, new()); +// mappedLines[index].Add($"{line},\t{useDirectoryName}"); +// } +// } +// } - private static void Populate(Dictionary> keyValuePairs, Dictionary> mappedLines) - { - string[] segments; - foreach (KeyValuePair> keyValuePair in mappedLines) - { - segments = keyValuePair.Value[0].Split('\t'); - if (segments.Length < 2) - continue; - if (!int.TryParse(segments[1], out int id)) - continue; - if (!keyValuePairs.ContainsKey(id)) - keyValuePairs.Add(id, new() { id }); - keyValuePairs[id].Add(keyValuePair.Key); - } - } +// private static void Populate(Dictionary> keyValuePairs, Dictionary> mappedLines) +// { +// string[] segments; +// foreach (KeyValuePair> keyValuePair in mappedLines) +// { +// segments = keyValuePair.Value[0].Split('\t'); +// if (segments.Length < 2) +// continue; +// if (!int.TryParse(segments[1], out int id)) +// continue; +// if (!keyValuePairs.ContainsKey(id)) +// keyValuePairs.Add(id, new() { id }); +// keyValuePairs[id].Add(keyValuePair.Key); +// } +// } - private static Dictionary GetUseTabSeparatedValue(string useEqualsDirectory, string use18HoursDirectory, string useAnyDateDirectory, Dictionary> keyValuePairs, List lines) - { - Dictionary results = new(); - string[] segments; - Dictionary> mappedLines = new(); - GetUseTabSeparatedValueLines(useEqualsDirectory, mappedLines); - GetUseTabSeparatedValueLines(use18HoursDirectory, mappedLines); - GetUseTabSeparatedValueLines(useAnyDateDirectory, mappedLines); - Populate(keyValuePairs, mappedLines); - foreach (KeyValuePair> keyValuePair in mappedLines) - { - segments = keyValuePair.Value[0].Split('\t'); - if (segments.Length < 2) - continue; - if (!int.TryParse(segments[1], out int id)) - continue; - foreach (string line in keyValuePair.Value) - lines.Add(line); - results.Add(keyValuePair.Key, id); - } - return results; - } +// private static Dictionary GetUseTabSeparatedValue(string useEqualsDirectory, string use18HoursDirectory, string useAnyDateDirectory, Dictionary> keyValuePairs, List lines) +// { +// Dictionary results = new(); +// string[] segments; +// Dictionary> mappedLines = new(); +// GetUseTabSeparatedValueLines(useEqualsDirectory, mappedLines); +// GetUseTabSeparatedValueLines(use18HoursDirectory, mappedLines); +// GetUseTabSeparatedValueLines(useAnyDateDirectory, mappedLines); +// Populate(keyValuePairs, mappedLines); +// foreach (KeyValuePair> keyValuePair in mappedLines) +// { +// segments = keyValuePair.Value[0].Split('\t'); +// if (segments.Length < 2) +// continue; +// if (!int.TryParse(segments[1], out int id)) +// continue; +// foreach (string line in keyValuePair.Value) +// lines.Add(line); +// results.Add(keyValuePair.Key, id); +// } +// return results; +// } - private static void ReSaveExifFiles(string infoDirectory, string infoDirectoryIgnore, Dictionary findReplace, List missingIndices) - { - string json; - int propertyId; - Models.SaveTabSeparatedValues.ImageExifInfo[]? exifCollection; - List exifInfoFiles = Directory.GetFiles(infoDirectory, "ImageExifInfo.json", SearchOption.AllDirectories).ToList(); - exifInfoFiles.AddRange(Directory.GetFiles(infoDirectoryIgnore, "ImageExifInfo.json", SearchOption.AllDirectories)); - foreach (string exifInfoFile in exifInfoFiles) - { - json = File.ReadAllText(exifInfoFile); - exifCollection = JsonSerializer.Deserialize(json); - if (exifCollection is null) - continue; - foreach (Models.SaveTabSeparatedValues.ImageExifInfo exifInfo in exifCollection) - { - if (missingIndices.Contains(exifInfo.Index)) - continue; - propertyId = findReplace[exifInfo.Index]; - exifInfo.Index = propertyId; - } - json = JsonSerializer.Serialize(exifCollection); - File.WriteAllText(exifInfoFile, json); - } - } +// private static void ReSaveExifFiles(string infoDirectory, string infoDirectoryIgnore, Dictionary findReplace, List missingIndices) +// { +// string json; +// int propertyId; +// Models.SaveTabSeparatedValues.ImageExifInfo[]? exifCollection; +// List exifInfoFiles = Directory.GetFiles(infoDirectory, "ImageExifInfo.json", SearchOption.AllDirectories).ToList(); +// exifInfoFiles.AddRange(Directory.GetFiles(infoDirectoryIgnore, "ImageExifInfo.json", SearchOption.AllDirectories)); +// foreach (string exifInfoFile in exifInfoFiles) +// { +// json = File.ReadAllText(exifInfoFile); +// exifCollection = JsonSerializer.Deserialize(json); +// if (exifCollection is null) +// continue; +// foreach (Models.SaveTabSeparatedValues.ImageExifInfo exifInfo in exifCollection) +// { +// if (missingIndices.Contains(exifInfo.Index)) +// continue; +// propertyId = findReplace[exifInfo.Index]; +// exifInfo.Index = propertyId; +// } +// json = JsonSerializer.Serialize(exifCollection); +// File.WriteAllText(exifInfoFile, json); +// } +// } - private static void ReSaveNamedFaceInfoFile(string namedFaceInfoFile, Dictionary findReplace, List missingIndices) - { - Dictionary destination = new(); - string json = File.ReadAllText(namedFaceInfoFile); - List<(int PropertyId, string[] Birthdays)> collection = new(); - JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true }; - Dictionary? source = JsonSerializer.Deserialize>(json); - if (source is null) - throw new NullReferenceException(nameof(source)); - { - int propertyId; - foreach (KeyValuePair keyValuePair in source) - { - if (missingIndices.Contains(keyValuePair.Key)) - continue; - propertyId = findReplace[keyValuePair.Key]; - collection.Add(new(propertyId, keyValuePair.Value)); - } - } - foreach ((int propertyId, string[] birthdays) in collection.OrderBy(l => l.PropertyId)) - { - if (destination.ContainsKey(propertyId)) - { - if (birthdays.Length != destination[propertyId].Length) - throw new Exception($"{birthdays.Length} != {destination[propertyId].Length}"); - if (birthdays[0] != destination[propertyId][0]) - throw new Exception($"{birthdays[0]} != {destination[propertyId][0]}"); - continue; - } - destination.Add(propertyId, birthdays); - } - json = JsonSerializer.Serialize(destination, jsonSerializerOptions); - File.WriteAllText(namedFaceInfoFile, json); - } +// private static void ReSaveNamedFaceInfoFile(string namedFaceInfoFile, Dictionary findReplace, List missingIndices) +// { +// Dictionary destination = new(); +// string json = File.ReadAllText(namedFaceInfoFile); +// List<(int PropertyId, string[] Birthdays)> collection = new(); +// JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true }; +// Dictionary? source = JsonSerializer.Deserialize>(json); +// if (source is null) +// throw new NullReferenceException(nameof(source)); +// { +// int propertyId; +// foreach (KeyValuePair keyValuePair in source) +// { +// if (missingIndices.Contains(keyValuePair.Key)) +// continue; +// propertyId = findReplace[keyValuePair.Key]; +// collection.Add(new(propertyId, keyValuePair.Value)); +// } +// } +// foreach ((int propertyId, string[] birthdays) in collection.OrderBy(l => l.PropertyId)) +// { +// if (destination.ContainsKey(propertyId)) +// { +// if (birthdays.Length != destination[propertyId].Length) +// throw new Exception($"{birthdays.Length} != {destination[propertyId].Length}"); +// if (birthdays[0] != destination[propertyId][0]) +// throw new Exception($"{birthdays[0]} != {destination[propertyId][0]}"); +// continue; +// } +// destination.Add(propertyId, birthdays); +// } +// json = JsonSerializer.Serialize(destination, jsonSerializerOptions); +// File.WriteAllText(namedFaceInfoFile, json); +// } - private static void ReSaveIndexFiles(string infoDirectory, string infoDirectoryIgnore, Dictionary findReplace, List missingIndices) - { - string json; - int propertyId; - Models.SaveTabSeparatedValues.IndexInfo[]? indexCollection; - List indexInfoFiles = Directory.GetFiles(infoDirectory, "IndexInfo.json", SearchOption.AllDirectories).ToList(); - indexInfoFiles.AddRange(Directory.GetFiles(infoDirectoryIgnore, "IndexInfo.json", SearchOption.AllDirectories)); - foreach (string indexInfoFile in indexInfoFiles) - { - json = File.ReadAllText(indexInfoFile); - indexCollection = JsonSerializer.Deserialize(json); - if (indexCollection is null) - continue; - foreach (Models.SaveTabSeparatedValues.IndexInfo indexInfo in indexCollection) - { - if (missingIndices.Contains(indexInfo.Index)) - continue; - propertyId = findReplace[indexInfo.Index]; - indexInfo.Index = propertyId; - } - json = JsonSerializer.Serialize(indexCollection); - File.WriteAllText(indexInfoFile, json); - } - } +// private static void ReSaveIndexFiles(string infoDirectory, string infoDirectoryIgnore, Dictionary findReplace, List missingIndices) +// { +// string json; +// int propertyId; +// Models.SaveTabSeparatedValues.IndexInfo[]? indexCollection; +// List indexInfoFiles = Directory.GetFiles(infoDirectory, "IndexInfo.json", SearchOption.AllDirectories).ToList(); +// indexInfoFiles.AddRange(Directory.GetFiles(infoDirectoryIgnore, "IndexInfo.json", SearchOption.AllDirectories)); +// foreach (string indexInfoFile in indexInfoFiles) +// { +// json = File.ReadAllText(indexInfoFile); +// indexCollection = JsonSerializer.Deserialize(json); +// if (indexCollection is null) +// continue; +// foreach (Models.SaveTabSeparatedValues.IndexInfo indexInfo in indexCollection) +// { +// if (missingIndices.Contains(indexInfo.Index)) +// continue; +// propertyId = findReplace[indexInfo.Index]; +// indexInfo.Index = propertyId; +// } +// json = JsonSerializer.Serialize(indexCollection); +// File.WriteAllText(indexInfoFile, json); +// } +// } - private void ReSaveJsonFiles() - { - if (_Log is null) - throw new NullReferenceException(nameof(_Log)); - if (_Configuration?.PropertyConfiguration is null) - throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory); - if (string.IsNullOrEmpty(rootDirectoryParent)) - throw new NullReferenceException(nameof(rootDirectoryParent)); - int z = 0; - int propertyId; - List missingIndices = new(); - Dictionary findReplace = new(); - List useTabSeparatedValueLines = new(); - Dictionary> keyValuePairs = new(); - string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp"); - string useEqualsDirectory = Path.Combine(rootDirectoryParent, "Use - =="); - string use18HoursDirectory = Path.Combine(rootDirectoryParent, "Use - 18 Hours"); - string useAnyDateDirectory = Path.Combine(rootDirectoryParent, "Use - Any Date"); - string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared"); - string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json"); - string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07"); - string infoDirectoryIgnore = Path.Combine(imageSharedDirectory, "Images - 4) Info - - - Ignore", "2022-04-14"); - Dictionary useTabSeparatedValueCollection = GetUseTabSeparatedValue(useEqualsDirectory, use18HoursDirectory, useAnyDateDirectory, keyValuePairs, useTabSeparatedValueLines); - { - long ticks = DateTime.Now.Ticks; - string json = JsonSerializer.Serialize(keyValuePairs, new JsonSerializerOptions { WriteIndented = true }); - File.WriteAllText($"{tempDirectory}/{nameof(keyValuePairs)}-{ticks}.json", json); - } - List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryIgnore, checkDistinct: true); - foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection) - { - z += 1; - if (_IsEnvironment.Development && z % 1000 == 0) - _Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}"); - if (!useTabSeparatedValueCollection.ContainsKey(index)) - { - missingIndices.Add(index); - continue; - } - propertyId = useTabSeparatedValueCollection[index]; - findReplace.Add(index, propertyId); - } - ReSaveIndexFiles(infoDirectory, infoDirectoryIgnore, findReplace, missingIndices); - ReSaveExifFiles(infoDirectory, infoDirectoryIgnore, findReplace, missingIndices); - ReSaveNamedFaceInfoFile(namedFaceInfoFile, findReplace, missingIndices); - { - long ticks = DateTime.Now.Ticks; - File.WriteAllLines($"{tempDirectory}/{nameof(useTabSeparatedValueLines)}-{ticks}.tsv", useTabSeparatedValueLines); - File.WriteAllText($"{tempDirectory}/{nameof(missingIndices)}-{ticks}.txt", string.Join(Environment.NewLine, missingIndices)); - } - _Log.Debug($"Done with {nameof(ReSaveJsonFiles)}"); - } +// private void ReSaveJsonFiles() +// { +// if (_Log is null) +// throw new NullReferenceException(nameof(_Log)); +// if (_Configuration?.PropertyConfiguration is null) +// throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); +// string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory); +// if (string.IsNullOrEmpty(rootDirectoryParent)) +// throw new NullReferenceException(nameof(rootDirectoryParent)); +// int z = 0; +// int propertyId; +// List missingIndices = new(); +// Dictionary findReplace = new(); +// List useTabSeparatedValueLines = new(); +// Dictionary> keyValuePairs = new(); +// string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp"); +// string useEqualsDirectory = Path.Combine(rootDirectoryParent, "Use - =="); +// string use18HoursDirectory = Path.Combine(rootDirectoryParent, "Use - 18 Hours"); +// string useAnyDateDirectory = Path.Combine(rootDirectoryParent, "Use - Any Date"); +// string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared"); +// string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json"); +// string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07"); +// string infoDirectoryIgnore = Path.Combine(imageSharedDirectory, "Images - 4) Info - - - Ignore", "2022-04-14"); +// Dictionary useTabSeparatedValueCollection = GetUseTabSeparatedValue(useEqualsDirectory, use18HoursDirectory, useAnyDateDirectory, keyValuePairs, useTabSeparatedValueLines); +// { +// long ticks = DateTime.Now.Ticks; +// string json = JsonSerializer.Serialize(keyValuePairs, new JsonSerializerOptions { WriteIndented = true }); +// File.WriteAllText($"{tempDirectory}/{nameof(keyValuePairs)}-{ticks}.json", json); +// } +// List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryIgnore, checkDistinct: true); +// foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection) +// { +// z += 1; +// if (_IsEnvironment.Development && z % 1000 == 0) +// _Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}"); +// if (!useTabSeparatedValueCollection.ContainsKey(index)) +// { +// missingIndices.Add(index); +// continue; +// } +// propertyId = useTabSeparatedValueCollection[index]; +// findReplace.Add(index, propertyId); +// } +// ReSaveIndexFiles(infoDirectory, infoDirectoryIgnore, findReplace, missingIndices); +// ReSaveExifFiles(infoDirectory, infoDirectoryIgnore, findReplace, missingIndices); +// ReSaveNamedFaceInfoFile(namedFaceInfoFile, findReplace, missingIndices); +// { +// long ticks = DateTime.Now.Ticks; +// File.WriteAllLines($"{tempDirectory}/{nameof(useTabSeparatedValueLines)}-{ticks}.tsv", useTabSeparatedValueLines); +// File.WriteAllText($"{tempDirectory}/{nameof(missingIndices)}-{ticks}.txt", string.Join(Environment.NewLine, missingIndices)); +// } +// _Log.Debug($"Done with {nameof(ReSaveJsonFiles)}"); +// } - private void CopyMissingImagesLogs() - { - if (_Log is null) - throw new NullReferenceException(nameof(_Log)); - if (_Configuration?.PropertyConfiguration is null) - throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory); - if (_Configuration?.PropertyConfiguration is null) - throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - if (string.IsNullOrEmpty(rootDirectoryParent)) - throw new NullReferenceException(nameof(rootDirectoryParent)); - int z = 0; - int propertyId; - Dictionary findReplace = new(); - List missingIndices = new(); - List useTabSeparatedValueLines = new(); - Dictionary> keyValuePairs = new(); - string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp"); - string currentDirectory = Path.Combine(rootDirectoryParent, "@) Images"); - string useEqualsDirectory = Path.Combine(rootDirectoryParent, "Use - =="); - string use18HoursDirectory = Path.Combine(rootDirectoryParent, "Use - 18 Hours"); - string useAnyDateDirectory = Path.Combine(rootDirectoryParent, "Use - Any Date"); - string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared"); - string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json"); - string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07"); - string infoDirectoryIgnore = Path.Combine(imageSharedDirectory, "Images - 4) Info - - - Ignore", "2022-04-14"); - Dictionary useTabSeparatedValueCollection = GetUseTabSeparatedValue(useEqualsDirectory, use18HoursDirectory, useAnyDateDirectory, keyValuePairs, useTabSeparatedValueLines); - { - long ticks = DateTime.Now.Ticks; - string json = JsonSerializer.Serialize(keyValuePairs, new JsonSerializerOptions { WriteIndented = true }); - File.WriteAllText($"{tempDirectory}/{nameof(keyValuePairs)}-{ticks}.json", json); - } - List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryIgnore, checkDistinct: false); - foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection) - { - z += 1; - if (_IsEnvironment.Development && z % 1000 == 0) - _Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}"); - if (!useTabSeparatedValueCollection.ContainsKey(index)) - { - missingIndices.Add(index); - continue; - } - propertyId = useTabSeparatedValueCollection[index]; - findReplace.Add(index, propertyId); - } - { - long ticks = DateTime.Now.Ticks; - File.WriteAllLines($"{tempDirectory}/{nameof(useTabSeparatedValueLines)}-{ticks}.tsv", useTabSeparatedValueLines); - File.WriteAllText($"{tempDirectory}/{nameof(missingIndices)}-{ticks}.txt", string.Join(Environment.NewLine, missingIndices)); - } - _Log.Debug($"Done with {nameof(CopyMissingImagesLogs)}"); - } +// private void CopyMissingImagesLogs() +// { +// if (_Log is null) +// throw new NullReferenceException(nameof(_Log)); +// if (_Configuration?.PropertyConfiguration is null) +// throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); +// string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory); +// if (_Configuration?.PropertyConfiguration is null) +// throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); +// if (string.IsNullOrEmpty(rootDirectoryParent)) +// throw new NullReferenceException(nameof(rootDirectoryParent)); +// int z = 0; +// int propertyId; +// Dictionary findReplace = new(); +// List missingIndices = new(); +// List useTabSeparatedValueLines = new(); +// Dictionary> keyValuePairs = new(); +// string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp"); +// string currentDirectory = Path.Combine(rootDirectoryParent, "@) Images"); +// string useEqualsDirectory = Path.Combine(rootDirectoryParent, "Use - =="); +// string use18HoursDirectory = Path.Combine(rootDirectoryParent, "Use - 18 Hours"); +// string useAnyDateDirectory = Path.Combine(rootDirectoryParent, "Use - Any Date"); +// string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared"); +// string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json"); +// string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07"); +// string infoDirectoryIgnore = Path.Combine(imageSharedDirectory, "Images - 4) Info - - - Ignore", "2022-04-14"); +// Dictionary useTabSeparatedValueCollection = GetUseTabSeparatedValue(useEqualsDirectory, use18HoursDirectory, useAnyDateDirectory, keyValuePairs, useTabSeparatedValueLines); +// { +// long ticks = DateTime.Now.Ticks; +// string json = JsonSerializer.Serialize(keyValuePairs, new JsonSerializerOptions { WriteIndented = true }); +// File.WriteAllText($"{tempDirectory}/{nameof(keyValuePairs)}-{ticks}.json", json); +// } +// List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryIgnore, checkDistinct: false); +// foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection) +// { +// z += 1; +// if (_IsEnvironment.Development && z % 1000 == 0) +// _Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}"); +// if (!useTabSeparatedValueCollection.ContainsKey(index)) +// { +// missingIndices.Add(index); +// continue; +// } +// propertyId = useTabSeparatedValueCollection[index]; +// findReplace.Add(index, propertyId); +// } +// { +// long ticks = DateTime.Now.Ticks; +// File.WriteAllLines($"{tempDirectory}/{nameof(useTabSeparatedValueLines)}-{ticks}.tsv", useTabSeparatedValueLines); +// File.WriteAllText($"{tempDirectory}/{nameof(missingIndices)}-{ticks}.txt", string.Join(Environment.NewLine, missingIndices)); +// } +// _Log.Debug($"Done with {nameof(CopyMissingImagesLogs)}"); +// } - private static Dictionary> GetKeyValuePairs(PropertyCompare.Models.PropertyCompare[] propertyCompares) - { - Dictionary> results = new(); - foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompares) - { - if (propertyCompare?.Property?.Id is null) - continue; - if (!results.ContainsKey(propertyCompare.Property.Id.Value)) - results.Add(propertyCompare.Property.Id.Value, new()); - results[propertyCompare.Property.Id.Value].Add(propertyCompare); - } - return results; - } +// private static Dictionary> GetKeyValuePairs(PropertyCompare.Models.PropertyCompare[] propertyCompares) +// { +// Dictionary> results = new(); +// foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompares) +// { +// if (propertyCompare?.Property?.Id is null) +// continue; +// if (!results.ContainsKey(propertyCompare.Property.Id.Value)) +// results.Add(propertyCompare.Property.Id.Value, new()); +// results[propertyCompare.Property.Id.Value].Add(propertyCompare); +// } +// return results; +// } - private void VerifyAgainstIndexInfoJsonFiles(Property.Models.Configuration configuration, string aPropertySingletonDirectory) - { - if (_Log is null) - throw new NullReferenceException(nameof(_Log)); - if (_Configuration?.PropertyConfiguration is null) - throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); - string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory); - if (string.IsNullOrEmpty(rootDirectoryParent)) - throw new NullReferenceException(nameof(rootDirectoryParent)); - int z = 0; - int? propertyId; - long? propertyTicks; - int loadLessThan = 7; - string diffRootDirectory = string.Empty; - PropertyCompare.Models.PropertyCompare propertyCompare; - string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp"); - if (!Directory.Exists(tempDirectory)) - _ = Directory.CreateDirectory(tempDirectory); - string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared"); - string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json"); - string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07"); - List<(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)> collection = new(); - PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory); - PropertyCompare.Models.PropertyCompare[] propertyCompareCollection = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan); - { - long ticks = DateTime.Now.Ticks; - string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray(); - string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(Property.Models.A_Property), "[{}]"); - File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines); - string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true }); - File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json); - } - Dictionary> keyValuePairs = GetKeyValuePairs(propertyCompareCollection); - List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryExtra: string.Empty, checkDistinct: false); - foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection) - { - z += 1; - if (_IsEnvironment.Development && z % 1000 == 0) - _Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}"); - propertyId = null; - propertyTicks = null; - if (keyValuePairs.ContainsKey(index)) - { - propertyCompare = keyValuePairs[index][0]; - if (propertyCompare?.Property?.Id is null) - continue; - propertyId = propertyCompare.Property.Id; - propertyTicks = propertyCompare.MinimumDateTime.Ticks; - } - collection.Add(new(index, relativeDirectory, $"{fileNameWithoutExtension}{extension}", regexResult, ticks, propertyId, propertyTicks)); - } - (int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] matched = (from l in collection where l.PropertyId.HasValue select l).ToArray(); - (int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] notMatched = (from l in collection where l.PropertyId is null select l).ToArray(); - string[] matchedLines = ( - from l - in matched - select $"{l.Index}\t{l.PropertyId}\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t{l.PropertyTicks}\t{l.RelativeDirectory}\t{l.FileName}" - ).ToArray(); - List notMatchedLines = ( - from l - in notMatched - select $"{l.Index}\t______________\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t_________________\t{l.RelativeDirectory}\t{l.FileName}" - ).ToList(); - { - long ticks = DateTime.Now.Ticks; - File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}.tsv", matchedLines); - File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}-Not.tsv", notMatchedLines); - } - _Log.Debug($"Done with {nameof(VerifyAgainstIndexInfoJsonFiles)}"); - } +// private void VerifyAgainstIndexInfoJsonFiles(Property.Models.Configuration configuration, string aPropertySingletonDirectory) +// { +// if (_Log is null) +// throw new NullReferenceException(nameof(_Log)); +// if (_Configuration?.PropertyConfiguration is null) +// throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); +// string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory); +// if (string.IsNullOrEmpty(rootDirectoryParent)) +// throw new NullReferenceException(nameof(rootDirectoryParent)); +// int z = 0; +// int? propertyId; +// long? propertyTicks; +// int loadLessThan = 7; +// string diffRootDirectory = string.Empty; +// PropertyCompare.Models.PropertyCompare propertyCompare; +// string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp"); +// if (!Directory.Exists(tempDirectory)) +// _ = Directory.CreateDirectory(tempDirectory); +// string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared"); +// string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json"); +// string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07"); +// List<(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)> collection = new(); +// PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory); +// PropertyCompare.Models.PropertyCompare[] propertyCompareCollection = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan); +// { +// long ticks = DateTime.Now.Ticks; +// string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray(); +// string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(Property.Models.A_Property), "[{}]"); +// File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines); +// string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true }); +// File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json); +// } +// Dictionary> keyValuePairs = GetKeyValuePairs(propertyCompareCollection); +// List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryExtra: string.Empty, checkDistinct: false); +// foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection) +// { +// z += 1; +// if (_IsEnvironment.Development && z % 1000 == 0) +// _Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}"); +// propertyId = null; +// propertyTicks = null; +// if (keyValuePairs.ContainsKey(index)) +// { +// propertyCompare = keyValuePairs[index][0]; +// if (propertyCompare?.Property?.Id is null) +// continue; +// propertyId = propertyCompare.Property.Id; +// propertyTicks = propertyCompare.MinimumDateTime.Ticks; +// } +// collection.Add(new(index, relativeDirectory, $"{fileNameWithoutExtension}{extension}", regexResult, ticks, propertyId, propertyTicks)); +// } +// (int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] matched = (from l in collection where l.PropertyId.HasValue select l).ToArray(); +// (int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] notMatched = (from l in collection where l.PropertyId is null select l).ToArray(); +// string[] matchedLines = ( +// from l +// in matched +// select $"{l.Index}\t{l.PropertyId}\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t{l.PropertyTicks}\t{l.RelativeDirectory}\t{l.FileName}" +// ).ToArray(); +// List notMatchedLines = ( +// from l +// in notMatched +// select $"{l.Index}\t______________\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t_________________\t{l.RelativeDirectory}\t{l.FileName}" +// ).ToList(); +// { +// long ticks = DateTime.Now.Ticks; +// File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}.tsv", matchedLines); +// File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}-Not.tsv", notMatchedLines); +// } +// _Log.Debug($"Done with {nameof(VerifyAgainstIndexInfoJsonFiles)}"); +// } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/PrepareForOld/PrepareForOld.csproj b/PrepareForOld/PrepareForOld.csproj index 4fba30a..f6de5f3 100644 --- a/PrepareForOld/PrepareForOld.csproj +++ b/PrepareForOld/PrepareForOld.csproj @@ -41,10 +41,10 @@ - + - - + + diff --git a/PrepareForOld/Program.cs b/PrepareForOld/Program.cs index ca2d4f5..ea5baa2 100644 --- a/PrepareForOld/Program.cs +++ b/PrepareForOld/Program.cs @@ -19,6 +19,7 @@ public class Program IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); IConfigurationRoot configurationRoot = configurationBuilder.Build(); AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); @@ -38,8 +39,8 @@ public class Program { if (args is null) throw new Exception("args is null!"); - Shared.Models.Console console = new(); - PrepareForOld dlibDotNet = new(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console); + // Shared.Models.Console console = new(); + // PrepareForOld dlibDotNet = new(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console); } catch (Exception ex) { diff --git a/Property-Compare/Models/PropertyCompareItem.cs b/Property-Compare/Models/PropertyCompareItem.cs index a78fdfb..ee2c6d2 100644 --- a/Property-Compare/Models/PropertyCompareItem.cs +++ b/Property-Compare/Models/PropertyCompareItem.cs @@ -1,29 +1,29 @@ -namespace View_by_Distance.PropertyCompare.Models; +// namespace View_by_Distance.PropertyCompare.Models; -internal class PropertyCompareItem -{ +// internal class PropertyCompareItem +// { - protected readonly string _ImageFileName; - protected readonly bool _IsArg; - protected readonly string _JsonFileNameWithoutExtension; - protected readonly long[] _Numbers; - protected readonly Shared.Models.Property _Property; - protected readonly string[] _Strings; - public string ImageFileName => _ImageFileName; - public bool IsArg => _IsArg; - public string JsonFileNameWithoutExtension => _JsonFileNameWithoutExtension; - public long[] Numbers => _Numbers; - public Shared.Models.Property Property => _Property; - public string[] Strings => _Strings; +// protected readonly string _ImageFileName; +// protected readonly bool _IsArg; +// protected readonly string _JsonFileNameWithoutExtension; +// protected readonly long[] _Numbers; +// protected readonly Shared.Models.Property _Property; +// protected readonly string[] _Strings; +// public string ImageFileName => _ImageFileName; +// public bool IsArg => _IsArg; +// public string JsonFileNameWithoutExtension => _JsonFileNameWithoutExtension; +// public long[] Numbers => _Numbers; +// public Shared.Models.Property Property => _Property; +// public string[] Strings => _Strings; - public PropertyCompareItem(string imageFileName, bool isArg, string jsonFileNameWithoutExtension, long[] numbers, Shared.Models.Property property, string[] strings) - { - _ImageFileName = imageFileName; - _IsArg = isArg; - _JsonFileNameWithoutExtension = jsonFileNameWithoutExtension; - _Numbers = numbers; - _Property = property; - _Strings = strings; - } +// public PropertyCompareItem(string imageFileName, bool isArg, string jsonFileNameWithoutExtension, long[] numbers, Shared.Models.Property property, string[] strings) +// { +// _ImageFileName = imageFileName; +// _IsArg = isArg; +// _JsonFileNameWithoutExtension = jsonFileNameWithoutExtension; +// _Numbers = numbers; +// _Property = property; +// _Strings = strings; +// } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/Property-Compare/Models/PropertyCompareLogic.cs b/Property-Compare/Models/PropertyCompareLogic.cs index ee286b7..172d012 100644 --- a/Property-Compare/Models/PropertyCompareLogic.cs +++ b/Property-Compare/Models/PropertyCompareLogic.cs @@ -1,609 +1,609 @@ -using ShellProgressBar; -using System.Text.Json; -using System.Text.RegularExpressions; -using View_by_Distance.Property.Models; +// using ShellProgressBar; +// using System.Text.Json; +// using System.Text.RegularExpressions; +// using View_by_Distance.Property.Models; -namespace View_by_Distance.PropertyCompare.Models; +// namespace View_by_Distance.PropertyCompare.Models; -public class PropertyCompareLogic -{ +// public class PropertyCompareLogic +// { - private readonly Serilog.ILogger? _Log; - private readonly string? _DiffRootDirectory; - private readonly int _MaxDegreeOfParallelism; - private readonly Configuration _Configuration; - private readonly List<(string Find, string Replace)>? _SpellingFindReplace; +// private readonly Serilog.ILogger? _Log; +// private readonly string? _DiffRootDirectory; +// private readonly int _MaxDegreeOfParallelism; +// private readonly Configuration _Configuration; +// private readonly List<(string Find, string Replace)>? _SpellingFindReplace; - public PropertyCompareLogic(int maxDegreeOfParallelism, Configuration configuration, List<(string Find, string Replace)>? spellingFindReplace = null, string? diffRootDirectory = null) - { - _Configuration = configuration; - _DiffRootDirectory = diffRootDirectory; - _SpellingFindReplace = spellingFindReplace; - _Log = Serilog.Log.ForContext(); - _MaxDegreeOfParallelism = Math.Abs(maxDegreeOfParallelism); - } +// public PropertyCompareLogic(int maxDegreeOfParallelism, Configuration configuration, List<(string Find, string Replace)>? spellingFindReplace = null, string? diffRootDirectory = null) +// { +// _Configuration = configuration; +// _DiffRootDirectory = diffRootDirectory; +// _SpellingFindReplace = spellingFindReplace; +// _Log = Serilog.Log.ForContext(); +// _MaxDegreeOfParallelism = Math.Abs(maxDegreeOfParallelism); +// } - public override string ToString() - { - string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); - return result; - } +// public override string ToString() +// { +// string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); +// return result; +// } - private List GetDuplicates(PropertyCompare[] propertyCompares, int i, PropertyCompare[]? diffPropertyCompares) - { - List results = new(); - if (_Log is null) - throw new NullReferenceException(nameof(_Log)); - int index; - string value; - long[] distinctNumberValues; - List checkValues = new(); - List checkNumberValues = new(); - if (diffPropertyCompares is null || propertyCompares.Length != diffPropertyCompares.Length) - { - foreach (PropertyCompare propertyCompare in propertyCompares) - { - value = $"{propertyCompare.Numbers[i]}\t{propertyCompare.Strings[i]}"; - checkNumberValues.Add(propertyCompare.Numbers[i]); - checkValues.Add(value); - } - distinctNumberValues = checkNumberValues.Distinct().ToArray(); - if (distinctNumberValues.Length != propertyCompares.Length) - _Log.Debug($"A) Distinct {nameof(propertyCompares)} - <{distinctNumberValues.Length} != {propertyCompares.Length}>"); - } - if (diffPropertyCompares is not null) - { - foreach (PropertyCompare propertyCompare in diffPropertyCompares) - { - value = $"{propertyCompare.Numbers[i]}\t{propertyCompare.Strings[i]}"; - if (checkNumberValues.Contains(propertyCompare.Numbers[i])) - { - index = checkValues.IndexOf(value); - if (index > -1) - { - if (index >= propertyCompares.Length - 1) - continue; - results.Add(propertyCompare); - results.Add(propertyCompares[index]); - } - } - checkNumberValues.Add(propertyCompare.Numbers[i]); - checkValues.Add(value); - } - distinctNumberValues = checkNumberValues.Distinct().ToArray(); - if (distinctNumberValues.Length != propertyCompares.Length) - _Log.Debug($"B) Distinct {nameof(propertyCompares)} - <{distinctNumberValues.Length} != {propertyCompares.Length}>"); - } - return results; - } +// private List GetDuplicates(PropertyCompare[] propertyCompares, int i, PropertyCompare[]? diffPropertyCompares) +// { +// List results = new(); +// if (_Log is null) +// throw new NullReferenceException(nameof(_Log)); +// int index; +// string value; +// long[] distinctNumberValues; +// List checkValues = new(); +// List checkNumberValues = new(); +// if (diffPropertyCompares is null || propertyCompares.Length != diffPropertyCompares.Length) +// { +// foreach (PropertyCompare propertyCompare in propertyCompares) +// { +// value = $"{propertyCompare.Numbers[i]}\t{propertyCompare.Strings[i]}"; +// checkNumberValues.Add(propertyCompare.Numbers[i]); +// checkValues.Add(value); +// } +// distinctNumberValues = checkNumberValues.Distinct().ToArray(); +// if (distinctNumberValues.Length != propertyCompares.Length) +// _Log.Debug($"A) Distinct {nameof(propertyCompares)} - <{distinctNumberValues.Length} != {propertyCompares.Length}>"); +// } +// if (diffPropertyCompares is not null) +// { +// foreach (PropertyCompare propertyCompare in diffPropertyCompares) +// { +// value = $"{propertyCompare.Numbers[i]}\t{propertyCompare.Strings[i]}"; +// if (checkNumberValues.Contains(propertyCompare.Numbers[i])) +// { +// index = checkValues.IndexOf(value); +// if (index > -1) +// { +// if (index >= propertyCompares.Length - 1) +// continue; +// results.Add(propertyCompare); +// results.Add(propertyCompares[index]); +// } +// } +// checkNumberValues.Add(propertyCompare.Numbers[i]); +// checkValues.Add(value); +// } +// distinctNumberValues = checkNumberValues.Distinct().ToArray(); +// if (distinctNumberValues.Length != propertyCompares.Length) +// _Log.Debug($"B) Distinct {nameof(propertyCompares)} - <{distinctNumberValues.Length} != {propertyCompares.Length}>"); +// } +// return results; +// } - private (string[] ToDirectories, List FromThenToCollection) Get(string aPropertyCollectionDirectory, PropertyCompare[] propertyCompares, int i, PropertyCompare[]? diffPropertyCompares) - { - List fromThenToCollection = new(); - if (_Log is null) - throw new NullReferenceException(nameof(_Log)); - int z = 0; - string to; - string from; - bool extensionIsNullOrEmpty; - string fileName; - string toDirectory; - string fromDirectory; - List toCollection = new(); - List toDirectories = new(); - List fromCollection = new(); - List bothCollection = new(); - foreach (PropertyCompare propertyCompare in propertyCompares) - bothCollection.Add(propertyCompare); - if (diffPropertyCompares is not null) - { - foreach (PropertyCompare propertyCompare in diffPropertyCompares) - bothCollection.Add(propertyCompare); - } - foreach (PropertyCompare propertyCompare in bothCollection) - { - z += 1; - if (z % 1000 == 0) - { - if (!propertyCompare.IsArg) - _Log.Debug($"{z}) Loop {_DiffRootDirectory}"); - else - _Log.Debug($"{z}) Loop {_Configuration.RootDirectory}"); - } - extensionIsNullOrEmpty = string.IsNullOrEmpty(propertyCompare.Extension); - if (propertyCompare.IsArg) - fromDirectory = string.Concat(_Configuration.RootDirectory, propertyCompare.RelativeDirectory); - else - fromDirectory = string.Concat(_DiffRootDirectory, propertyCompare.RelativeDirectory); - if (!Directory.Exists(fromDirectory)) - _ = Directory.CreateDirectory(fromDirectory); - to = string.Empty; - if (extensionIsNullOrEmpty) - from = Path.GetFullPath(Path.Combine(fromDirectory, $"{propertyCompare.FileNameWithoutExtension}.jpg")); - else - from = Path.GetFullPath(Path.Combine(fromDirectory, $"{propertyCompare.FileNameWithoutExtension}{propertyCompare.Extension}")); - if (fromCollection.Contains(from)) - continue; - if (!extensionIsNullOrEmpty && !File.Exists(from)) - continue; - fromCollection.Add(from); - for (short c = 65; c < short.MaxValue; c++) - { - if (c > 95) - break; - if (extensionIsNullOrEmpty && !propertyCompare.IsArg) - c += 1; - fileName = Regex.Replace(propertyCompare.Strings[i], @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]", "_"); - toDirectory = Path.Combine(aPropertyCollectionDirectory, $". . . {i} - {(char)c}"); - if (!extensionIsNullOrEmpty) - to = Path.GetFullPath(Path.Combine(toDirectory, $"{propertyCompare.Numbers[i]}{fileName}{propertyCompare.Extension.ToLower()}")); - else - { - to = Path.GetFullPath(Path.Combine(toDirectory, $"{propertyCompare.Numbers[i]}{fileName}.jpg")); - break; - } - if (toCollection.Contains(to)) - continue; - if (!toDirectories.Contains(toDirectory)) - toDirectories.Add(toDirectory); - toCollection.Add(to); - break; - } - if (string.IsNullOrEmpty(to)) - continue; - fromThenToCollection.Add(new string[] { from, to }); - } - return new(toDirectories.ToArray(), fromThenToCollection); - } +// private (string[] ToDirectories, List FromThenToCollection) Get(string aPropertyCollectionDirectory, PropertyCompare[] propertyCompares, int i, PropertyCompare[]? diffPropertyCompares) +// { +// List fromThenToCollection = new(); +// if (_Log is null) +// throw new NullReferenceException(nameof(_Log)); +// int z = 0; +// string to; +// string from; +// bool extensionIsNullOrEmpty; +// string fileName; +// string toDirectory; +// string fromDirectory; +// List toCollection = new(); +// List toDirectories = new(); +// List fromCollection = new(); +// List bothCollection = new(); +// foreach (PropertyCompare propertyCompare in propertyCompares) +// bothCollection.Add(propertyCompare); +// if (diffPropertyCompares is not null) +// { +// foreach (PropertyCompare propertyCompare in diffPropertyCompares) +// bothCollection.Add(propertyCompare); +// } +// foreach (PropertyCompare propertyCompare in bothCollection) +// { +// z += 1; +// if (z % 1000 == 0) +// { +// if (!propertyCompare.IsArg) +// _Log.Debug($"{z}) Loop {_DiffRootDirectory}"); +// else +// _Log.Debug($"{z}) Loop {_Configuration.RootDirectory}"); +// } +// extensionIsNullOrEmpty = string.IsNullOrEmpty(propertyCompare.Extension); +// if (propertyCompare.IsArg) +// fromDirectory = string.Concat(_Configuration.RootDirectory, propertyCompare.RelativeDirectory); +// else +// fromDirectory = string.Concat(_DiffRootDirectory, propertyCompare.RelativeDirectory); +// if (!Directory.Exists(fromDirectory)) +// _ = Directory.CreateDirectory(fromDirectory); +// to = string.Empty; +// if (extensionIsNullOrEmpty) +// from = Path.GetFullPath(Path.Combine(fromDirectory, $"{propertyCompare.FileNameWithoutExtension}.jpg")); +// else +// from = Path.GetFullPath(Path.Combine(fromDirectory, $"{propertyCompare.FileNameWithoutExtension}{propertyCompare.Extension}")); +// if (fromCollection.Contains(from)) +// continue; +// if (!extensionIsNullOrEmpty && !File.Exists(from)) +// continue; +// fromCollection.Add(from); +// for (short c = 65; c < short.MaxValue; c++) +// { +// if (c > 95) +// break; +// if (extensionIsNullOrEmpty && !propertyCompare.IsArg) +// c += 1; +// fileName = Regex.Replace(propertyCompare.Strings[i], @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]", "_"); +// toDirectory = Path.Combine(aPropertyCollectionDirectory, $". . . {i} - {(char)c}"); +// if (!extensionIsNullOrEmpty) +// to = Path.GetFullPath(Path.Combine(toDirectory, $"{propertyCompare.Numbers[i]}{fileName}{propertyCompare.Extension.ToLower()}")); +// else +// { +// to = Path.GetFullPath(Path.Combine(toDirectory, $"{propertyCompare.Numbers[i]}{fileName}.jpg")); +// break; +// } +// if (toCollection.Contains(to)) +// continue; +// if (!toDirectories.Contains(toDirectory)) +// toDirectories.Add(toDirectory); +// toCollection.Add(to); +// break; +// } +// if (string.IsNullOrEmpty(to)) +// continue; +// fromThenToCollection.Add(new string[] { from, to }); +// } +// return new(toDirectories.ToArray(), fromThenToCollection); +// } - private void ParallelGet(List? duplicates, List results, List ids, List collection, int loadLessThan, string directory, object @lock, string relativeDirectory, string[] files, List filesWithoutExtension, bool isArg, string jsonFile) - { - long n; - string s; - int index; - string extension; - string corrected; - List numbers; - string regexResult; - List strings; - PropertyCompare propertyCompare; - string jsonFileNameWithoutExtension = Path.GetFileNameWithoutExtension(jsonFile); - string check = Path.Combine(directory, jsonFileNameWithoutExtension); - index = filesWithoutExtension.IndexOf(check); - if (index == -1) - extension = string.Empty; - else - extension = Path.GetExtension(files[index]); - string json = File.ReadAllText(jsonFile); - Shared.Models.Property? property = JsonSerializer.Deserialize(json); - if (property?.Id is null) - throw new NullReferenceException(nameof(property)); - DateTime minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property); - corrected = string.Concat(relativeDirectory, jsonFileNameWithoutExtension); - if (_SpellingFindReplace is not null && (from l in _SpellingFindReplace where corrected.Contains(l.Find) select true).Any()) - { - foreach ((string find, string replace) in _SpellingFindReplace) - corrected = corrected.Replace(find, replace); - } - if (string.IsNullOrEmpty(_Configuration.Pattern)) - regexResult = corrected; - else - regexResult = Regex.Replace(corrected, _Configuration.Pattern, string.Empty); - numbers = new(); - strings = new(); - for (int i = 0; i < loadLessThan; i++) - { - n = i switch - { - 0 => property.Id.Value, - 1 => property.Id.Value, - 2 => property.Id.Value, - 3 => property.Id.Value, - 4 => property.Id.Value, - 5 => Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks, - 6 => property.CreationTime.Ticks, - 7 => property.FileSize, - 8 => Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks, - 9 => property.FileSize, - _ => throw new Exception() - }; - s = i switch - { - 0 => $"{jsonFileNameWithoutExtension.ToLower()}", - 1 => $"{property.FileSize}{Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks}", - 2 => $"{property.FileSize}{property.CreationTime:yyyy-MM-dd_HH-mm-ss}", - 3 => $"{property.FileSize}{property.Width}{property.Height}", - 4 => string.Empty, - 5 => $"{property.FileSize}", - 6 => $"{property.FileSize}", - 7 => $"{property.Width}{property.Height}", - 8 => string.Empty, - 9 => string.Empty, - _ => throw new Exception() - }; - numbers.Add(n); - strings.Add(s); - } - propertyCompare = new(extension, jsonFileNameWithoutExtension, isArg, minimumDateTime, numbers, property, regexResult, relativeDirectory, strings); - lock (@lock) - results.Add(propertyCompare); - if (duplicates is not null) - { - string value = $"{property.Id.Value}\t{property}"; - index = ids.IndexOf(property.Id.Value); - if (index > -1) - { - lock (@lock) - { - duplicates.Add(propertyCompare); - duplicates.Add(collection[index]); - } - } - lock (@lock) - { - ids.Add(property.Id.Value); - collection.Add(propertyCompare); - } - } - } +// private void ParallelGet(List? duplicates, List results, List ids, List collection, int loadLessThan, string directory, object @lock, string relativeDirectory, string[] files, List filesWithoutExtension, bool isArg, string jsonFile) +// { +// long n; +// string s; +// int index; +// string extension; +// string corrected; +// List numbers; +// string regexResult; +// List strings; +// PropertyCompare propertyCompare; +// string jsonFileNameWithoutExtension = Path.GetFileNameWithoutExtension(jsonFile); +// string check = Path.Combine(directory, jsonFileNameWithoutExtension); +// index = filesWithoutExtension.IndexOf(check); +// if (index == -1) +// extension = string.Empty; +// else +// extension = Path.GetExtension(files[index]); +// string json = File.ReadAllText(jsonFile); +// Shared.Models.Property? property = JsonSerializer.Deserialize(json); +// if (property?.Id is null) +// throw new NullReferenceException(nameof(property)); +// DateTime minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property); +// corrected = string.Concat(relativeDirectory, jsonFileNameWithoutExtension); +// if (_SpellingFindReplace is not null && (from l in _SpellingFindReplace where corrected.Contains(l.Find) select true).Any()) +// { +// foreach ((string find, string replace) in _SpellingFindReplace) +// corrected = corrected.Replace(find, replace); +// } +// if (string.IsNullOrEmpty(_Configuration.Pattern)) +// regexResult = corrected; +// else +// regexResult = Regex.Replace(corrected, _Configuration.Pattern, string.Empty); +// numbers = new(); +// strings = new(); +// for (int i = 0; i < loadLessThan; i++) +// { +// n = i switch +// { +// 0 => property.Id.Value, +// 1 => property.Id.Value, +// 2 => property.Id.Value, +// 3 => property.Id.Value, +// 4 => property.Id.Value, +// 5 => Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks, +// 6 => property.CreationTime.Ticks, +// 7 => property.FileSize, +// 8 => Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks, +// 9 => property.FileSize, +// _ => throw new Exception() +// }; +// s = i switch +// { +// 0 => $"{jsonFileNameWithoutExtension.ToLower()}", +// 1 => $"{property.FileSize}{Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks}", +// 2 => $"{property.FileSize}{property.CreationTime:yyyy-MM-dd_HH-mm-ss}", +// 3 => $"{property.FileSize}{property.Width}{property.Height}", +// 4 => string.Empty, +// 5 => $"{property.FileSize}", +// 6 => $"{property.FileSize}", +// 7 => $"{property.Width}{property.Height}", +// 8 => string.Empty, +// 9 => string.Empty, +// _ => throw new Exception() +// }; +// numbers.Add(n); +// strings.Add(s); +// } +// propertyCompare = new(extension, jsonFileNameWithoutExtension, isArg, minimumDateTime, numbers, property, regexResult, relativeDirectory, strings); +// lock (@lock) +// results.Add(propertyCompare); +// if (duplicates is not null) +// { +// string value = $"{property.Id.Value}\t{property}"; +// index = ids.IndexOf(property.Id.Value); +// if (index > -1) +// { +// lock (@lock) +// { +// duplicates.Add(propertyCompare); +// duplicates.Add(collection[index]); +// } +// } +// lock (@lock) +// { +// ids.Add(property.Id.Value); +// collection.Add(propertyCompare); +// } +// } +// } - public PropertyCompare[] Get(string aPropertySingletonDirectory, int loadLessThan = 7, List? duplicates = null, bool deleteExtension = false) - { - List results = new(); - if (_Log is null) - throw new NullReferenceException(nameof(_Log)); - string[] files; - int totalSeconds; - string directory; - string searchPattern; - object @lock = new(); - int exceptionCount = 0; - List ids = new(); - string relativeDirectory; - if (!deleteExtension) - searchPattern = "*.json"; - else - searchPattern = "*.delete"; - long ticks = DateTime.Now.Ticks; - List filesWithoutExtension; - List topDirectories = new(); - string extension = searchPattern[1..]; - string[] filteredSourceDirectoryFiles; - List collection = new(); - bool isArg = aPropertySingletonDirectory.Contains(_Configuration.RootDirectory); - List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection; - ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _MaxDegreeOfParallelism }; - ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; - (int r, groupCollection) = Property.Models.Stateless.Container.GetGroupCollection(aPropertySingletonDirectory, searchPattern, topDirectories); - foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in groupCollection) - { - if (!topDirectories.Any()) - continue; - if (!sourceDirectoryFiles.Any()) - continue; - relativeDirectory = sourceDirectory[aPropertySingletonDirectory.Length..]; - if (!isArg) - directory = string.Concat(_DiffRootDirectory, relativeDirectory); - else - directory = string.Concat(_Configuration.RootDirectory, relativeDirectory); - if (!Directory.Exists(directory)) - _ = Directory.CreateDirectory(directory); - files = Directory.GetFiles(directory); - filesWithoutExtension = files.Select(l => Path.Combine($"{Path.GetDirectoryName(l)}", Path.GetFileNameWithoutExtension(l))).ToList(); - filteredSourceDirectoryFiles = (from l in sourceDirectoryFiles where l.EndsWith(extension) select l).ToArray(); - if (!filteredSourceDirectoryFiles.Any()) - continue; - totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); - 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, state) => - { - try - { - ParallelGet(duplicates, results, ids, collection, loadLessThan, directory, @lock, relativeDirectory, files, filesWithoutExtension, isArg, sourceDirectoryFiles[i]); - progressBar.Tick(); - } - catch (Exception ex) - { - exceptionCount += 1; - _Log.Error(string.Concat(sourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex); - if (exceptionCount == filteredSourceDirectoryFiles.Length) - throw new Exception(string.Concat("All in [", sourceDirectory, "]failed!")); - } - }); - } - if (exceptionCount != 0) - throw new Exception(); - return (from l in results orderby Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(l.Property).Ticks select l).ToArray(); - } +// public PropertyCompare[] Get(string aPropertySingletonDirectory, int loadLessThan = 7, List? duplicates = null, bool deleteExtension = false) +// { +// List results = new(); +// if (_Log is null) +// throw new NullReferenceException(nameof(_Log)); +// string[] files; +// int totalSeconds; +// string directory; +// string searchPattern; +// object @lock = new(); +// int exceptionCount = 0; +// List ids = new(); +// string relativeDirectory; +// if (!deleteExtension) +// searchPattern = "*.json"; +// else +// searchPattern = "*.delete"; +// long ticks = DateTime.Now.Ticks; +// List filesWithoutExtension; +// List topDirectories = new(); +// string extension = searchPattern[1..]; +// string[] filteredSourceDirectoryFiles; +// List collection = new(); +// bool isArg = aPropertySingletonDirectory.Contains(_Configuration.RootDirectory); +// List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection; +// ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _MaxDegreeOfParallelism }; +// ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; +// (int r, groupCollection) = Property.Models.Stateless.Container.GetGroupCollection(aPropertySingletonDirectory, searchPattern, topDirectories); +// foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in groupCollection) +// { +// if (!topDirectories.Any()) +// continue; +// if (!sourceDirectoryFiles.Any()) +// continue; +// relativeDirectory = sourceDirectory[aPropertySingletonDirectory.Length..]; +// if (!isArg) +// directory = string.Concat(_DiffRootDirectory, relativeDirectory); +// else +// directory = string.Concat(_Configuration.RootDirectory, relativeDirectory); +// if (!Directory.Exists(directory)) +// _ = Directory.CreateDirectory(directory); +// files = Directory.GetFiles(directory); +// filesWithoutExtension = files.Select(l => Path.Combine($"{Path.GetDirectoryName(l)}", Path.GetFileNameWithoutExtension(l))).ToList(); +// filteredSourceDirectoryFiles = (from l in sourceDirectoryFiles where l.EndsWith(extension) select l).ToArray(); +// if (!filteredSourceDirectoryFiles.Any()) +// continue; +// totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); +// 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, state) => +// { +// try +// { +// ParallelGet(duplicates, results, ids, collection, loadLessThan, directory, @lock, relativeDirectory, files, filesWithoutExtension, isArg, sourceDirectoryFiles[i]); +// progressBar.Tick(); +// } +// catch (Exception ex) +// { +// exceptionCount += 1; +// _Log.Error(string.Concat(sourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex); +// if (exceptionCount == filteredSourceDirectoryFiles.Length) +// throw new Exception(string.Concat("All in [", sourceDirectory, "]failed!")); +// } +// }); +// } +// if (exceptionCount != 0) +// throw new Exception(); +// return (from l in results orderby Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(l.Property).Ticks select l).ToArray(); +// } - private void MoveFiles(string[] directories, List fromThenToCollection) - { - if (_Log is null) - throw new NullReferenceException(nameof(_Log)); - int z; - string to; - string from; - int moved = 0; - _Log.Information("Ready to move?"); - ConsoleKey? consoleKey = null; - for (int y = 0; y < int.MaxValue; y++) - { - _Log.Information("Press \"Y\" key when ready to continue"); - if (Console.ReadKey().Key == ConsoleKey.Y) - break; - } - _Log.Information(". . ."); - foreach (string directory in directories) - { - if (!Directory.Exists(directory)) - _ = Directory.CreateDirectory(directory); - } - z = 0; - foreach (string[] fromThenTo in fromThenToCollection) - { - z += 1; - from = fromThenTo[0]; - to = fromThenTo[1]; - if (z % 1000 == 0) - _Log.Information($"{z})"); - if (!File.Exists(from)) - continue; - if (File.Exists(to)) - continue; - File.Move(from, to); - moved += 1; - } - _Log.Information($"{moved} file(s) moved"); - for (int m = 0; m < int.MaxValue; m++) - { - moved = 0; - _Log.Information($"{m}) Ready to move back?"); - for (int y = 0; y < int.MaxValue; y++) - { - _Log.Information("Press \"Y\" key when ready to continue"); - if (Console.ReadKey().Key == ConsoleKey.Y) - break; - } - _Log.Information(". . ."); - z = 0; - foreach (string[] fromThenTo in fromThenToCollection) - { - z += 1; - from = fromThenTo[1]; - to = fromThenTo[0]; - if (z % 1000 == 0) - _Log.Information($"{z})"); - if (!File.Exists(from)) - continue; - if (File.Exists(to)) - continue; - File.Move(from, to); - moved += 1; - } - foreach (string directory in directories) - { - if (Directory.Exists(directory)) - { - if (!Directory.GetFiles(directory, "*", SearchOption.AllDirectories).Any()) - Directory.Delete(directory); - } - } - _Log.Information($"Done moving back {moved} file(s) for loop {m})"); - for (int y = 0; y < int.MaxValue; y++) - { - _Log.Information("Press \"Y\" key when ready to continue"); - _Log.Information("Press \"End\" key when ready to break"); - consoleKey = Console.ReadKey().Key; - if (consoleKey is ConsoleKey.Y or ConsoleKey.End) - break; - } - _Log.Information(". . ."); - if (consoleKey.HasValue && consoleKey == ConsoleKey.End) - break; - } - } +// private void MoveFiles(string[] directories, List fromThenToCollection) +// { +// if (_Log is null) +// throw new NullReferenceException(nameof(_Log)); +// int z; +// string to; +// string from; +// int moved = 0; +// _Log.Information("Ready to move?"); +// ConsoleKey? consoleKey = null; +// for (int y = 0; y < int.MaxValue; y++) +// { +// _Log.Information("Press \"Y\" key when ready to continue"); +// if (Console.ReadKey().Key == ConsoleKey.Y) +// break; +// } +// _Log.Information(". . ."); +// foreach (string directory in directories) +// { +// if (!Directory.Exists(directory)) +// _ = Directory.CreateDirectory(directory); +// } +// z = 0; +// foreach (string[] fromThenTo in fromThenToCollection) +// { +// z += 1; +// from = fromThenTo[0]; +// to = fromThenTo[1]; +// if (z % 1000 == 0) +// _Log.Information($"{z})"); +// if (!File.Exists(from)) +// continue; +// if (File.Exists(to)) +// continue; +// File.Move(from, to); +// moved += 1; +// } +// _Log.Information($"{moved} file(s) moved"); +// for (int m = 0; m < int.MaxValue; m++) +// { +// moved = 0; +// _Log.Information($"{m}) Ready to move back?"); +// for (int y = 0; y < int.MaxValue; y++) +// { +// _Log.Information("Press \"Y\" key when ready to continue"); +// if (Console.ReadKey().Key == ConsoleKey.Y) +// break; +// } +// _Log.Information(". . ."); +// z = 0; +// foreach (string[] fromThenTo in fromThenToCollection) +// { +// z += 1; +// from = fromThenTo[1]; +// to = fromThenTo[0]; +// if (z % 1000 == 0) +// _Log.Information($"{z})"); +// if (!File.Exists(from)) +// continue; +// if (File.Exists(to)) +// continue; +// File.Move(from, to); +// moved += 1; +// } +// foreach (string directory in directories) +// { +// if (Directory.Exists(directory)) +// { +// if (!Directory.GetFiles(directory, "*", SearchOption.AllDirectories).Any()) +// Directory.Delete(directory); +// } +// } +// _Log.Information($"Done moving back {moved} file(s) for loop {m})"); +// for (int y = 0; y < int.MaxValue; y++) +// { +// _Log.Information("Press \"Y\" key when ready to continue"); +// _Log.Information("Press \"End\" key when ready to break"); +// consoleKey = Console.ReadKey().Key; +// if (consoleKey is ConsoleKey.Y or ConsoleKey.End) +// break; +// } +// _Log.Information(". . ."); +// if (consoleKey.HasValue && consoleKey == ConsoleKey.End) +// break; +// } +// } - public void SaveDiffFiles(string aPropertyCollectionDirectory, int loadLessThan, PropertyCompare[] propertyCompares, PropertyCompare[]? diffPropertyCompares) - { - if (_Log is null) - throw new NullReferenceException(nameof(_Log)); - string text; - string[] lines; - string fileName; - ConsoleKey? consoleKey = null; - List duplicateCollection; - for (int i = 0; i < loadLessThan; i++) - { - if (!propertyCompares.Any()) - continue; - if (diffPropertyCompares is null || !diffPropertyCompares.Any()) - duplicateCollection = GetDuplicates(propertyCompares, i, diffPropertyCompares); - else - { - if (i != 0) - { - if (diffPropertyCompares is null) - continue; - } - if (propertyCompares.Length == diffPropertyCompares.Length) - continue; - duplicateCollection = GetDuplicates(propertyCompares, i, diffPropertyCompares); - } - lines = (from l in duplicateCollection select l.GetSelect()).ToArray(); - _Log.Debug($"{i}) loop has {lines.Length} line(s)"); - if ((duplicateCollection.Count % 2) != 0) - continue; - fileName = Path.Join(aPropertyCollectionDirectory, $". . . {i}-Duplicates.txt"); - if (!duplicateCollection.Any()) - { - if (File.Exists(fileName)) - File.Delete(fileName); - continue; - } - text = string.Join(Environment.NewLine, lines); - File.WriteAllText(fileName, text); - for (int y = 0; y < int.MaxValue; y++) - { - _Log.Information("Press \"Y\" key when ready to continue"); - _Log.Information("Press \"End\" key when ready to break"); - consoleKey = Console.ReadKey().Key; - if (consoleKey is ConsoleKey.Y or ConsoleKey.End) - break; - } - _Log.Information(". . ."); - if (consoleKey.HasValue && consoleKey == ConsoleKey.End) - break; - } - } +// public void SaveDiffFiles(string aPropertyCollectionDirectory, int loadLessThan, PropertyCompare[] propertyCompares, PropertyCompare[]? diffPropertyCompares) +// { +// if (_Log is null) +// throw new NullReferenceException(nameof(_Log)); +// string text; +// string[] lines; +// string fileName; +// ConsoleKey? consoleKey = null; +// List duplicateCollection; +// for (int i = 0; i < loadLessThan; i++) +// { +// if (!propertyCompares.Any()) +// continue; +// if (diffPropertyCompares is null || !diffPropertyCompares.Any()) +// duplicateCollection = GetDuplicates(propertyCompares, i, diffPropertyCompares); +// else +// { +// if (i != 0) +// { +// if (diffPropertyCompares is null) +// continue; +// } +// if (propertyCompares.Length == diffPropertyCompares.Length) +// continue; +// duplicateCollection = GetDuplicates(propertyCompares, i, diffPropertyCompares); +// } +// lines = (from l in duplicateCollection select l.GetSelect()).ToArray(); +// _Log.Debug($"{i}) loop has {lines.Length} line(s)"); +// if ((duplicateCollection.Count % 2) != 0) +// continue; +// fileName = Path.Join(aPropertyCollectionDirectory, $". . . {i}-Duplicates.txt"); +// if (!duplicateCollection.Any()) +// { +// if (File.Exists(fileName)) +// File.Delete(fileName); +// continue; +// } +// text = string.Join(Environment.NewLine, lines); +// File.WriteAllText(fileName, text); +// for (int y = 0; y < int.MaxValue; y++) +// { +// _Log.Information("Press \"Y\" key when ready to continue"); +// _Log.Information("Press \"End\" key when ready to break"); +// consoleKey = Console.ReadKey().Key; +// if (consoleKey is ConsoleKey.Y or ConsoleKey.End) +// break; +// } +// _Log.Information(". . ."); +// if (consoleKey.HasValue && consoleKey == ConsoleKey.End) +// break; +// } +// } - public void SaveLogAndMoveFiles(string aPropertyCollectionDirectory, int loadLessThan, PropertyCompare[] propertyCompares, PropertyCompare[]? diffPropertyCompares, int i) - { - if (_Log is null) - throw new NullReferenceException(nameof(_Log)); - List lines; - string checkDirectory; - string[] toDirectories; - ConsoleKey? consoleKey = null; - List fromThenToCollection; - _Log.Information($"{i}) example - number:{propertyCompares[0].Numbers[i]}; string:{propertyCompares[0].Strings[i]};"); - (toDirectories, fromThenToCollection) = Get(aPropertyCollectionDirectory, propertyCompares, i, diffPropertyCompares); - if (toDirectories.Length < 2) - _Log.Information($"{i}) loop only one directory :)"); - else - { - checkDirectory = toDirectories[1]; - _Log.Information($"{i}) loop {toDirectories.Length} directories and . . .{i}) - B will have ~{fromThenToCollection.Where(l => l[1].StartsWith(checkDirectory)).Count()}"); - } - for (int y = 0; y < int.MaxValue; y++) - { - _Log.Information($"Press \"Y\" key to {nameof(MoveFiles)} \"N\" to skip"); - consoleKey = Console.ReadKey().Key; - if (consoleKey is ConsoleKey.Y or ConsoleKey.N) - break; - } - _Log.Information(". . ."); - if (consoleKey.HasValue && consoleKey.Value == ConsoleKey.Y) - { - lines = new(); - foreach (string[] fromThenTo in fromThenToCollection) - { - lines.Add(fromThenTo[0]); - lines.Add(fromThenTo[1]); - } - File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . {i}-All.txt"), lines); - MoveFiles(toDirectories, fromThenToCollection); - } - } +// public void SaveLogAndMoveFiles(string aPropertyCollectionDirectory, int loadLessThan, PropertyCompare[] propertyCompares, PropertyCompare[]? diffPropertyCompares, int i) +// { +// if (_Log is null) +// throw new NullReferenceException(nameof(_Log)); +// List lines; +// string checkDirectory; +// string[] toDirectories; +// ConsoleKey? consoleKey = null; +// List fromThenToCollection; +// _Log.Information($"{i}) example - number:{propertyCompares[0].Numbers[i]}; string:{propertyCompares[0].Strings[i]};"); +// (toDirectories, fromThenToCollection) = Get(aPropertyCollectionDirectory, propertyCompares, i, diffPropertyCompares); +// if (toDirectories.Length < 2) +// _Log.Information($"{i}) loop only one directory :)"); +// else +// { +// checkDirectory = toDirectories[1]; +// _Log.Information($"{i}) loop {toDirectories.Length} directories and . . .{i}) - B will have ~{fromThenToCollection.Where(l => l[1].StartsWith(checkDirectory)).Count()}"); +// } +// for (int y = 0; y < int.MaxValue; y++) +// { +// _Log.Information($"Press \"Y\" key to {nameof(MoveFiles)} \"N\" to skip"); +// consoleKey = Console.ReadKey().Key; +// if (consoleKey is ConsoleKey.Y or ConsoleKey.N) +// break; +// } +// _Log.Information(". . ."); +// if (consoleKey.HasValue && consoleKey.Value == ConsoleKey.Y) +// { +// lines = new(); +// foreach (string[] fromThenTo in fromThenToCollection) +// { +// lines.Add(fromThenTo[0]); +// lines.Add(fromThenTo[1]); +// } +// File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . {i}-All.txt"), lines); +// MoveFiles(toDirectories, fromThenToCollection); +// } +// } - public void WithSubdirectory(string propertyDirectory, bool subDirectoriesAny, string fileName, bool renameCompare, bool deleteArg) - { - if (_Log is null) - throw new NullReferenceException(nameof(_Log)); - List fileCollection = new(); - if (renameCompare && deleteArg) - throw new Exception(); - if (!renameCompare && !deleteArg) - throw new Exception(); - string[] lines; - string[] txtFiles = Directory.GetFiles(propertyDirectory, fileName, SearchOption.TopDirectoryOnly); - if (txtFiles.Length != 1) - lines = Array.Empty(); - else - lines = File.ReadAllLines(txtFiles[0]); - if (lines.Any()) - { - string argLine; - string moveFile; - string argFileName; - string compareLine; - string? argDirectory; - string argFullFileName; - string compareFileName; - string argDirectoryName; - string? compareDirectory; - string compareFullFileName; - string compareDirectoryName; - for (int i = 0; i < lines.Length; i++) - { - argLine = lines[i]; - compareLine = lines[i + 1]; - i += 1; - if (!subDirectoriesAny) - { - if (!argLine.StartsWith(_Configuration.RootDirectory) || !compareLine.StartsWith(_Configuration.RootDirectory)) - throw new Exception(i.ToString()); - } - else - { - if (!argLine.StartsWith(_Configuration.RootDirectory) || compareLine.StartsWith(_Configuration.RootDirectory)) - throw new Exception(i.ToString()); - } - } - for (int i = 0; i < lines.Length; i++) - { - argLine = lines[i]; - compareLine = lines[i + 1]; - i += 1; - if (!subDirectoriesAny) - { - if (!argLine.StartsWith(_Configuration.RootDirectory) || !compareLine.StartsWith(_Configuration.RootDirectory)) - throw new Exception(i.ToString()); - } - else - { - if (!argLine.StartsWith(_Configuration.RootDirectory) || compareLine.StartsWith(_Configuration.RootDirectory)) - throw new Exception(i.ToString()); - } - argFullFileName = argLine.Split('\t')[0]; - compareFullFileName = compareLine.Split('\t')[0]; - argFileName = Path.GetFileName(argFullFileName); - if (deleteArg) - { - if (!File.Exists(argFullFileName)) - continue; - fileCollection.Add(new string[] { argFullFileName }); - } - else if (renameCompare) - { - argDirectory = Path.GetDirectoryName(argFullFileName); - if (string.IsNullOrEmpty(argDirectory)) - continue; - compareDirectory = Path.GetDirectoryName(compareFullFileName); - if (string.IsNullOrEmpty(compareDirectory)) - continue; - argDirectoryName = Path.GetFileName(argDirectory); - if (argDirectoryName[..3].Equals(argFileName[..3], StringComparison.CurrentCultureIgnoreCase)) - continue; - compareDirectoryName = Path.GetFileName(argDirectory); - compareFileName = Path.GetFileName(compareFullFileName); - if (!compareDirectoryName[..3].Equals(compareFileName[..3], StringComparison.CurrentCultureIgnoreCase)) - continue; - if (!File.Exists(compareFullFileName)) - { - if (File.Exists(argFullFileName)) - fileCollection.Add(new string[] { argFullFileName }); - continue; - } - moveFile = Path.Combine(compareDirectory, argFileName); - if (File.Exists(moveFile)) - { - _Log.Information(argLine); - _Log.Information(compareLine); - continue; - } - fileCollection.Add(new string[] { compareFullFileName, moveFile }); - } - else - throw new Exception(); - } - } - foreach (string[] file in fileCollection) - { - if (deleteArg) - File.Delete(Path.GetFullPath(file[0])); - else if (renameCompare) - File.Move(Path.GetFullPath(file[0]), Path.GetFullPath(file[1])); - } - } +// public void WithSubdirectory(string propertyDirectory, bool subDirectoriesAny, string fileName, bool renameCompare, bool deleteArg) +// { +// if (_Log is null) +// throw new NullReferenceException(nameof(_Log)); +// List fileCollection = new(); +// if (renameCompare && deleteArg) +// throw new Exception(); +// if (!renameCompare && !deleteArg) +// throw new Exception(); +// string[] lines; +// string[] txtFiles = Directory.GetFiles(propertyDirectory, fileName, SearchOption.TopDirectoryOnly); +// if (txtFiles.Length != 1) +// lines = Array.Empty(); +// else +// lines = File.ReadAllLines(txtFiles[0]); +// if (lines.Any()) +// { +// string argLine; +// string moveFile; +// string argFileName; +// string compareLine; +// string? argDirectory; +// string argFullFileName; +// string compareFileName; +// string argDirectoryName; +// string? compareDirectory; +// string compareFullFileName; +// string compareDirectoryName; +// for (int i = 0; i < lines.Length; i++) +// { +// argLine = lines[i]; +// compareLine = lines[i + 1]; +// i += 1; +// if (!subDirectoriesAny) +// { +// if (!argLine.StartsWith(_Configuration.RootDirectory) || !compareLine.StartsWith(_Configuration.RootDirectory)) +// throw new Exception(i.ToString()); +// } +// else +// { +// if (!argLine.StartsWith(_Configuration.RootDirectory) || compareLine.StartsWith(_Configuration.RootDirectory)) +// throw new Exception(i.ToString()); +// } +// } +// for (int i = 0; i < lines.Length; i++) +// { +// argLine = lines[i]; +// compareLine = lines[i + 1]; +// i += 1; +// if (!subDirectoriesAny) +// { +// if (!argLine.StartsWith(_Configuration.RootDirectory) || !compareLine.StartsWith(_Configuration.RootDirectory)) +// throw new Exception(i.ToString()); +// } +// else +// { +// if (!argLine.StartsWith(_Configuration.RootDirectory) || compareLine.StartsWith(_Configuration.RootDirectory)) +// throw new Exception(i.ToString()); +// } +// argFullFileName = argLine.Split('\t')[0]; +// compareFullFileName = compareLine.Split('\t')[0]; +// argFileName = Path.GetFileName(argFullFileName); +// if (deleteArg) +// { +// if (!File.Exists(argFullFileName)) +// continue; +// fileCollection.Add(new string[] { argFullFileName }); +// } +// else if (renameCompare) +// { +// argDirectory = Path.GetDirectoryName(argFullFileName); +// if (string.IsNullOrEmpty(argDirectory)) +// continue; +// compareDirectory = Path.GetDirectoryName(compareFullFileName); +// if (string.IsNullOrEmpty(compareDirectory)) +// continue; +// argDirectoryName = Path.GetFileName(argDirectory); +// if (argDirectoryName[..3].Equals(argFileName[..3], StringComparison.CurrentCultureIgnoreCase)) +// continue; +// compareDirectoryName = Path.GetFileName(argDirectory); +// compareFileName = Path.GetFileName(compareFullFileName); +// if (!compareDirectoryName[..3].Equals(compareFileName[..3], StringComparison.CurrentCultureIgnoreCase)) +// continue; +// if (!File.Exists(compareFullFileName)) +// { +// if (File.Exists(argFullFileName)) +// fileCollection.Add(new string[] { argFullFileName }); +// continue; +// } +// moveFile = Path.Combine(compareDirectory, argFileName); +// if (File.Exists(moveFile)) +// { +// _Log.Information(argLine); +// _Log.Information(compareLine); +// continue; +// } +// fileCollection.Add(new string[] { compareFullFileName, moveFile }); +// } +// else +// throw new Exception(); +// } +// } +// foreach (string[] file in fileCollection) +// { +// if (deleteArg) +// File.Delete(Path.GetFullPath(file[0])); +// else if (renameCompare) +// File.Move(Path.GetFullPath(file[0]), Path.GetFullPath(file[1])); +// } +// } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/Property-Compare/Property-Compare.csproj b/Property-Compare/Property-Compare.csproj index ad3ee1d..4a86252 100644 --- a/Property-Compare/Property-Compare.csproj +++ b/Property-Compare/Property-Compare.csproj @@ -37,7 +37,7 @@ - + diff --git a/Property/Models/A_Property.cs b/Property/Models/A_Property.cs index 6af00cb..4aa4cac 100644 --- a/Property/Models/A_Property.cs +++ b/Property/Models/A_Property.cs @@ -64,7 +64,7 @@ public class A_Property #pragma warning disable CA1416 - private Shared.Models.Property GetImageProperty(FileHolder fileHolder, Shared.Models.Property? property, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id, List indices) + private Shared.Models.Property GetImageProperty(FileHolder fileHolder, Shared.Models.Property? property, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id) { Shared.Models.Property result; if (_Log is null) @@ -99,7 +99,7 @@ public class A_Property try { using Image image = Image.FromFile(fileHolder.FullName); - if (populateId && (id is null || !indices.Any())) + if (populateId && id is null) { using Bitmap bitmap = new(image); string angleBracket = AngleBracketCollection[0]; @@ -225,9 +225,9 @@ public class A_Property if (fileHolder.LastWriteTime is null && property?.LastWriteTime is null) throw new NullReferenceException(nameof(fileHolder.LastWriteTime)); if (fileHolder.CreationTime is not null && fileHolder.LastWriteTime is not null) - result = new(fileHolder.CreationTime.Value, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, fileLength, gpsDateStamp, height, id, indices.ToArray(), fileHolder.LastWriteTime.Value, make, model, orientation, width); + result = new(fileHolder.CreationTime.Value, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, fileLength, gpsDateStamp, height, id, fileHolder.LastWriteTime.Value, make, model, orientation, width); else if (property is not null) - result = new(property.CreationTime, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, fileLength, gpsDateStamp, height, id, indices.ToArray(), property.LastWriteTime, make, model, orientation, width); + result = new(property.CreationTime, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, fileLength, gpsDateStamp, height, id, property.LastWriteTime, make, model, orientation, width); else throw new NullReferenceException(nameof(property)); return result; @@ -240,9 +240,7 @@ public class A_Property Shared.Models.Property? result; string json; int? id = null; - List indices = new(); bool hasWrongYearProperty = false; - Shared.Models.Property? property = null; string[] changesFrom = Array.Empty(); string angleBracket = AngleBracketCollection[0]; bool populateId = _Configuration.PopulatePropertyId; @@ -254,17 +252,6 @@ public class A_Property fileInfo.Refresh(); } List dateTimes = (from l in sourceDirectoryFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - if (!fileInfo.FullName.Contains(_Configuration.ResultAllInOne) && !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 && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) { File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); @@ -288,62 +275,50 @@ public class A_Property json = File.ReadAllText(fileInfo.FullName); try { - bool check = true; - property = JsonSerializer.Deserialize(json); - if (!isIgnoreExtension && item.ValidImageFormatExtension && ((populateId && property?.Id is null) || property?.Width is null || property?.Height is null)) + if (item.Property is not null) + result = item.Property; + else + result = JsonSerializer.Deserialize(json); + if (result is not null && json.Contains("WrongYear")) { - check = false; - id = property?.Id; - if (property is not null && property.Indices.Any()) - indices = property.Indices.ToList(); - property = GetImageProperty(item.ImageFileHolder, property, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices); + id = result.Id; + hasWrongYearProperty = true; + result = null; } - if (!isIgnoreExtension && item.ValidImageFormatExtension && populateId && property is not null && !property.Indices.Any()) + if (!isIgnoreExtension && item.ValidImageFormatExtension && ((populateId && result?.Id is null) || result?.Width is null || result.Height is null)) { - check = false; - id = property?.Id; - if (property is not null && property.Indices.Any()) - indices = property.Indices.ToList(); - property = GetImageProperty(item.ImageFileHolder, property, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices); + id = result?.Id; + result = null; } - if (!isIgnoreExtension && item.ValidImageFormatExtension && populateId && property is not null && property.LastWriteTime != item.ImageFileHolder.LastWriteTime) + if (!isIgnoreExtension && item.ValidImageFormatExtension && populateId && result is not null) + { + id = result.Id; + result = null; + } + if (!isIgnoreExtension && item.ValidImageFormatExtension && populateId && result is not null && result.LastWriteTime != item.ImageFileHolder.LastWriteTime) { - check = false; id = null; - indices.Clear(); - property = GetImageProperty(item.ImageFileHolder, property, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices); + result = null; } - if (!isIgnoreExtension && item.ValidImageFormatExtension && property?.Width is not null && property?.Height is not null && property.Width.Value == property.Height.Value && item.ImageFileHolder.Exists) + if (!isIgnoreExtension && item.ValidImageFormatExtension && result?.Width is not null && result.Height is not null && result.Width.Value == result.Height.Value && item.ImageFileHolder.Exists) { - check = false; - id = property?.Id; - if (property is not null && property.Indices.Any()) - indices = property.Indices.ToList(); - property = GetImageProperty(item.ImageFileHolder, property, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices); - if (property?.Width is not null && property?.Height is not null && property.Width.Value != property.Height.Value) + id = result.Id; + result = null; + if (result?.Width is not null && result.Height is not null && result.Width.Value != result.Height.Value) throw new Exception("Was square!"); } - // if (filteredSourceDirectoryFileFileInfo.CreationTime != property?.CreationTime || filteredSourceDirectoryFileFileInfo.LastWriteTime != property?.LastWriteTime) - // { - // check = false; - // id = null; - // indices.Clear(); - // property = GetImagePropertyB(filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices); - // } - if (json.Contains("WrongYear")) + if (!isIgnoreExtension && item.ValidImageFormatExtension && result is not null && result.FileSize != fileInfo.Length) { - id = property?.Id; - hasWrongYearProperty = true; - } - if (property is null) - throw new Exception(); - if (!check) + id = result.Id; result = null; - else - { - result = property; - sourceDirectoryFileTuples.Add(new Tuple(nameof(A_Property), fileInfo.LastWriteTime)); } + // if (filteredSourceDirectoryFileFileInfo.CreationTime != result.CreationTime || filteredSourceDirectoryFileFileInfo.LastWriteTime != result?.LastWriteTime) + // { + // id = null; + // property = ; + // } + if (result is not null) + sourceDirectoryFileTuples.Add(new Tuple(nameof(A_Property), fileInfo.LastWriteTime)); } catch (Exception) { @@ -353,7 +328,8 @@ public class A_Property } if (result is null) { - result = GetImageProperty(item.ImageFileHolder, property, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices); + id ??= item.ImageFileHolder.Id; + result = GetImageProperty(item.ImageFileHolder, result, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id); json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions); if (populateId && Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true)) { diff --git a/Property/Models/Binder/Configuration.cs b/Property/Models/Binder/Configuration.cs index 2e87105..33c46fd 100644 --- a/Property/Models/Binder/Configuration.cs +++ b/Property/Models/Binder/Configuration.cs @@ -99,6 +99,8 @@ public class Configuration IConfigurationSection configurationSection = configurationRoot.GetSection(section); configuration = configurationSection.Get(); } + if (configuration is null) + throw new NullReferenceException(nameof(configuration)); result = Get(configuration); return result; } diff --git a/Property/Models/Configuration.cs b/Property/Models/Configuration.cs index effb648..4e00d7b 100644 --- a/Property/Models/Configuration.cs +++ b/Property/Models/Configuration.cs @@ -92,6 +92,8 @@ public class Configuration : Shared.Models.Properties.IPropertyConfiguration _RootDirectory = Path.GetFullPath(_RootDirectory); } + public void Update() => Update(numberOfJitters: null, numberOfTimesToUpsample: null, modelName: null, predictorModelName: null); + public static void Verify(Configuration propertyConfiguration, bool requireExist) { if (propertyConfiguration is null) @@ -118,6 +120,8 @@ public class Configuration : Shared.Models.Properties.IPropertyConfiguration throw new NullReferenceException(nameof(propertyConfiguration.Pattern)); if (string.IsNullOrEmpty(propertyConfiguration.RootDirectory) || (requireExist && !Directory.Exists(propertyConfiguration.RootDirectory))) throw new NullReferenceException(nameof(propertyConfiguration.RootDirectory)); + if (propertyConfiguration.RootDirectory != Path.GetFullPath(propertyConfiguration.RootDirectory)) + throw new Exception(); } } \ No newline at end of file diff --git a/Property/Models/Stateless/Container.cs b/Property/Models/Stateless/Container.cs index 7d3aa3c..148cadd 100644 --- a/Property/Models/Stateless/Container.cs +++ b/Property/Models/Stateless/Container.cs @@ -6,126 +6,46 @@ namespace View_by_Distance.Property.Models.Stateless; public class Container { - public static (int t, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)>) GetGroupCollection(string rootDirectory, int maxImagesInDirectoryForTopLevelFirstPass, bool reverse, string searchPattern, List topDirectories) - { - int result = 0; - List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> results = new(); - string? parentDirectory; - string[] subDirectories; - string[] sourceDirectoryFiles; - List fileCollections = new(); - if (!topDirectories.Any()) - { - if (!Directory.Exists(rootDirectory)) - _ = Directory.CreateDirectory(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) - { - for (int i = fileCollections.Count - 1; i > -1; i--) - { - parentDirectory = Path.GetDirectoryName(fileCollections[i][0]); - if (string.IsNullOrEmpty(parentDirectory)) - continue; - results.Add(new(g, parentDirectory, fileCollections[i])); - fileCollections.RemoveAt(i); - } - } - else if (g == 2) - { - for (int i = fileCollections.Count - 1; i > -1; i--) - { - if (fileCollections[i].Length > maxImagesInDirectoryForTopLevelFirstPass * g) - break; - parentDirectory = Path.GetDirectoryName(fileCollections[i][0]); - if (string.IsNullOrEmpty(parentDirectory)) - continue; - results.Add(new(g, parentDirectory, fileCollections[i])); - fileCollections.RemoveAt(i); - } - } - else if (g == 3) - { - subDirectories = Directory.GetDirectories(rootDirectory, "*", SearchOption.AllDirectories); - if (reverse) - subDirectories = subDirectories.Reverse().ToArray(); - foreach (string subDirectory in subDirectories) - { - sourceDirectoryFiles = Directory.GetFiles(subDirectory, "*", SearchOption.TopDirectoryOnly); - result += sourceDirectoryFiles.Length; - if (!topDirectories.Contains(subDirectory)) - results.Add(new(g, subDirectory, sourceDirectoryFiles)); - } - } - else if (g == 1) - { - sourceDirectoryFiles = Directory.GetFiles(rootDirectory, searchPattern, SearchOption.TopDirectoryOnly); - result += sourceDirectoryFiles.Length; - if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass) - fileCollections.Add(sourceDirectoryFiles); - else - results.Add(new(g, rootDirectory, sourceDirectoryFiles)); - if (reverse) - topDirectories.Reverse(); - subDirectories = topDirectories.ToArray(); - foreach (string subDirectory in subDirectories) - { - sourceDirectoryFiles = Directory.GetFiles(subDirectory, searchPattern, SearchOption.TopDirectoryOnly); - result += sourceDirectoryFiles.Length; - if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass) - fileCollections.Add(sourceDirectoryFiles); - else - { - if (sourceDirectoryFiles.Any() || Directory.GetDirectories(subDirectory, "*", SearchOption.TopDirectoryOnly).Any()) - results.Add(new(g, subDirectory, sourceDirectoryFiles)); - else if (searchPattern == "*" && subDirectory != rootDirectory) - Directory.Delete(subDirectory); - } - } - fileCollections.Reverse(); - } - else - throw new Exception(); - } - return new(result, results); - } - - public static (int t, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)>) GetGroupCollection(string rootDirectory, string searchPattern, List topDirectories) - { - (int t, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)>) results; - int maxImagesInDirectoryForTopLevelFirstPass = 50; - bool reverse = false; - results = GetGroupCollection(rootDirectory, maxImagesInDirectoryForTopLevelFirstPass, reverse, searchPattern, topDirectories); - return results; - } - - private static (int j, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)>) GetJsonGroupCollection(Configuration configuration, A_Property propertyLogic, string rootDirectory) - { - (int j, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)>) results; - string searchPattern = "*.json"; - List topDirectories = new(); - results = GetGroupCollection(rootDirectory, configuration.MaxImagesInDirectoryForTopLevelFirstPass, propertyLogic.Reverse, searchPattern, topDirectories); - return results; - } - private static (int f, List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles)>) GetFileHolderGroupCollection(Configuration configuration, A_Property propertyLogic, string searchPattern, List topDirectories) { List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles)> results = new(); + int? id; + int parsedId; + string idFile; + string[] lines; + const int zero = 0; + List<(string File, int? Id)> files = new(); List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> collection; - (int f, collection) = GetGroupCollection(configuration.RootDirectory, configuration.MaxImagesInDirectoryForTopLevelFirstPass, propertyLogic.Reverse, searchPattern, topDirectories); + (int f, collection) = Shared.Models.Stateless.Methods.IFileHolder.GetGroupCollection(configuration.RootDirectory, configuration.MaxImagesInDirectoryForTopLevelFirstPass, propertyLogic.Reverse, searchPattern, topDirectories); foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in collection) - results.Add(new(g, sourceDirectory, (from l in sourceDirectoryFiles select new FileHolder(l)).ToArray())); + { + files.Clear(); + foreach (string sourceDirectoryFile in sourceDirectoryFiles) + { + if (sourceDirectoryFile.EndsWith(".id")) + continue; + id = null; + idFile = $"{sourceDirectoryFile}.id"; + if (sourceDirectoryFiles.Contains(idFile)) + { + lines = File.ReadAllLines(idFile); + File.Delete(idFile); + if (lines.Any() && int.TryParse(lines[zero], out parsedId)) + id = parsedId; + }; + files.Add(new(sourceDirectoryFile, id)); + } + results.Add(new(g, sourceDirectory, (from l in files select new FileHolder(l.File, l.Id)).ToArray())); + } return new(f, results); } - private static void ParallelFor(List<(int, string, string[])> jsonCollection, int i, int length, List<(int, string, List<(string, Shared.Models.Property?)>)> results) + private static void ParallelFor(List<(string, string[])> jsonCollection, int i, int length, List<(string, List<(string, Shared.Models.Property?)>)> results) { string key; string json; Shared.Models.Property? property; - (int g, string sourceDirectory, string[] sourceDirectoryFiles) = jsonCollection[i]; + (string sourceDirectory, string[] sourceDirectoryFiles) = jsonCollection[i]; List<(string, Shared.Models.Property?)> collection = new(); foreach (string sourceDirectoryFile in sourceDirectoryFiles) { @@ -135,37 +55,28 @@ public class Container collection.Add(new(sourceDirectoryFile, property)); } lock (results) - results.Add(new(g, sourceDirectory, collection)); + results.Add(new(sourceDirectory, collection)); } - private static List<(int g, string sourceDirectory, List<(string sourceDirectoryFile, Shared.Models.Property? property)> collection)> GetCollection(string rootDirectory, List<(int g, string sourceDirectory, string[] SourceDirectoryFiles)> jsonCollection) + private static List<(string sourceDirectory, List<(string sourceDirectoryFile, Shared.Models.Property? property)> collection)> GetCollection(string rootDirectory, List<(string sourceDirectory, string[] SourceDirectoryFiles)> jsonCollection) { - List<(int, string, List<(string, Shared.Models.Property?)>)> results = new(); + List<(string, List<(string, Shared.Models.Property?)>)> results = new(); int length = rootDirectory.Length; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = Environment.ProcessorCount }; _ = Parallel.For(0, jsonCollection.Count, parallelOptions, (i, state) => ParallelFor(jsonCollection, i, length, results)); return results; } - private static Item GetNewItem(Configuration configuration, A_Property propertyLogic, string relativePath, FileHolder sourceDirectoryFileHolder) + private static Item GetNewItem(Configuration configuration, string relativePath, FileHolder sourceDirectoryFileHolder) { Item result; Shared.Models.Property? property = null; bool isValidImageFormatExtension = configuration.ValidImageFormatExtensions.Contains(sourceDirectoryFileHolder.ExtensionLowered); - if (configuration.PopulatePropertyId) - result = new(sourceDirectoryFileHolder.FullName, relativePath, sourceDirectoryFileHolder, isValidImageFormatExtension, property, null, null, null); - else - { - List parseExceptions = new(); - List> subFileTuples = new(); - Item item = new(sourceDirectoryFileHolder.FullName, relativePath, sourceDirectoryFileHolder, isValidImageFormatExtension, property, null, null, null); - property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions); - result = new(sourceDirectoryFileHolder.FullName, relativePath, sourceDirectoryFileHolder, isValidImageFormatExtension, property, null, null, null); - } + result = new(sourceDirectoryFileHolder, relativePath, sourceDirectoryFileHolder, isValidImageFormatExtension, property, null, null, null); return result; } - private static (int, Shared.Models.Container[]) GetContainers(Configuration configuration, A_Property propertyLogic, string aPropertySingletonDirectory, List<(int, string, FileHolder[])> fileHolderGroupCollection, List<(int, string, List<(string, Shared.Models.Property?)>)> collectionFromJson) + private static (int, Shared.Models.Container[]) GetContainers(Configuration configuration, A_Property propertyLogic, string aPropertySingletonDirectory, List<(int, string, FileHolder[])> fileHolderGroupCollection, List<(string, List<(string, Shared.Models.Property?)>)> collectionFromJson) { int result = 0; Shared.Models.Container[] results; @@ -174,9 +85,11 @@ public class Container int additional; string inferred; List items; + const int last = 9; string keyWithJson; string relativePath; bool fileSizeChanged; + FileHolder fileHolder; FileHolder keyFileHolder; bool lastWriteTimeChanged; bool isValidImageFormatExtension; @@ -190,11 +103,13 @@ public class Container foreach (FileHolder sourceDirectoryFileHolder in sourceDirectoryFileHolderCollection) { relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFileHolder.FullName, length, forceExtensionToLower: true); + if (fileHolderKeyValuePairs.ContainsKey(relativePath)) + throw new NotSupportedException(); fileHolderKeyValuePairs.Add(relativePath, new(sourceDirectory, sourceDirectoryFileHolder)); } } length = aPropertySingletonDirectory.Length; - foreach ((int g, string _, List<(string, Shared.Models.Property?)> collection) in collectionFromJson) + foreach ((string _, List<(string, Shared.Models.Property?)> collection) in collectionFromJson) { if (!collection.Any()) continue; @@ -202,6 +117,7 @@ public class Container keySourceDirectories = new(); foreach ((string sourceDirectoryFile, Shared.Models.Property? property) in collection) { + fileHolder = new(sourceDirectoryFile); keyWithJson = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFile, length, forceExtensionToLower: false); relativePath = keyWithJson[..^5]; if (!fileHolderKeyValuePairs.ContainsKey(relativePath)) @@ -212,7 +128,7 @@ public class Container continue; keySourceDirectories.Add(string.Concat(keyFileHolder.DirectoryName)); isValidImageFormatExtension = configuration.ValidImageFormatExtensions.Contains(keyFileHolder.ExtensionLowered); - item = new(sourceDirectoryFile, relativePath, keyFileHolder, isValidImageFormatExtension, property, true, null, null); + item = new(fileHolder, relativePath, keyFileHolder, isValidImageFormatExtension, property, true, null, null); items.Add(item); } else @@ -225,12 +141,12 @@ public class Container continue; isValidImageFormatExtension = configuration.ValidImageFormatExtensions.Contains(keyFileHolder.ExtensionLowered); if (property?.Id is null || property?.Width is null || property?.Height is null) - item = new(sourceDirectoryFile, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, null, null); + item = new(fileHolder, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, null, null); else { fileSizeChanged = property.FileSize != keyFileHolder.Length; lastWriteTimeChanged = configuration.PropertiesChangedForProperty || property.LastWriteTime != keyFileHolder.LastWriteTime; - item = new(sourceDirectoryFile, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, fileSizeChanged, lastWriteTimeChanged); + item = new(fileHolder, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, fileSizeChanged, lastWriteTimeChanged); } items.Add(item); } @@ -240,7 +156,7 @@ public class Container result += items.Count; if (keySourceDirectories.Distinct().Count() != 1) continue; - container = new(g, items, keySourceDirectories[0]); + container = new(last, items, keySourceDirectories[0]); keyValuePairs.Add(keySourceDirectories[0], container); } } @@ -258,7 +174,7 @@ public class Container throw new Exception(); if (sourceDirectoryFileHolder.ExtensionLowered is ".json") continue; - item = GetNewItem(configuration, propertyLogic, relativePath, sourceDirectoryFileHolder); + item = GetNewItem(configuration, relativePath, sourceDirectoryFileHolder); items.Add(item); } if (sourceDirectory == configuration.RootDirectory || items.Any()) @@ -285,19 +201,54 @@ public class Container return new(result, results); } + private static void SetCollections(string aPropertySingletonDirectory, List otherCollection, List<(string, string[])> jsonCollection) + { + string searchPattern = "*"; + (string, string[])[] collection = Shared.Models.Stateless.Methods.IFileHolder.GetFiles(aPropertySingletonDirectory, searchPattern).ToArray(); + foreach ((string sourceDirectory, string[] files) in collection) + { + otherCollection.AddRange(files.Where(l => !l.EndsWith(".json"))); + jsonCollection.Add(new(sourceDirectory, files.Where(l => l.EndsWith(".json")).ToArray())); + } + } + + private static void DeleteAbandoned(Configuration configuration, string aPropertySingletonDirectory, List otherCollection, List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles)> fileHolderGroupCollection) + { + string relativePath; + string checkFileName; + List checkCollection = new(); + checkCollection.AddRange(otherCollection); + int length = configuration.RootDirectory.Length; + foreach ((int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles) in fileHolderGroupCollection) + { + foreach (FileHolder fileHolder in sourceDirectoryFiles) + { + relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(fileHolder.FullName, length); + checkFileName = Path.GetFullPath(string.Concat(aPropertySingletonDirectory, relativePath)); + if (!checkCollection.Remove(checkFileName)) + File.WriteAllText(checkFileName, string.Empty); + } + } + foreach (string file in checkCollection) + File.Delete(file); + } + public static (int, int, int, Shared.Models.Container[]) GetContainers(Configuration configuration, A_Property propertyLogic) { Shared.Models.Container[] results; string searchPattern = "*"; List topDirectories = new(); - List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> jsonCollection; + List otherCollection = new(); + List<(string, string[])> jsonCollection = new(); List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles)> fileHolderGroupCollection; string aPropertySingletonDirectory = IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); - List<(int g, string sourceDirectory, List<(string sourceDirectoryFile, Shared.Models.Property? property)> collection)> collectionFromJson; - (int j, jsonCollection) = GetJsonGroupCollection(configuration, propertyLogic, aPropertySingletonDirectory); + SetCollections(aPropertySingletonDirectory, otherCollection, jsonCollection); (int f, fileHolderGroupCollection) = GetFileHolderGroupCollection(configuration, propertyLogic, searchPattern, topDirectories); + DeleteAbandoned(configuration, aPropertySingletonDirectory, otherCollection, fileHolderGroupCollection); + List<(string sourceDirectory, List<(string sourceDirectoryFile, Shared.Models.Property? property)> collection)> collectionFromJson; collectionFromJson = GetCollection(aPropertySingletonDirectory, jsonCollection); (int t, results) = GetContainers(configuration, propertyLogic, aPropertySingletonDirectory, fileHolderGroupCollection, collectionFromJson); + int j = jsonCollection.Select(l => l.Item2.Length).Sum(); return (j, f, t, results); } diff --git a/Property/Models/Stateless/Result.cs b/Property/Models/Stateless/Result.cs index 8a73785..3436d2c 100644 --- a/Property/Models/Stateless/Result.cs +++ b/Property/Models/Stateless/Result.cs @@ -52,7 +52,7 @@ internal class Result predictorModelName = PredictorModel.Large.ToString(); else predictorModelName = propertyConfiguration.PredictorModelName; - string dateGroupDirectory = string.Concat(outputResolution.Replace(" ", string.Empty), " - ", modelName, " - ", predictorModelName); + string dateGroupDirectory = string.Concat(outputResolution.Replace(" ", string.Empty), "-", modelName, "-", predictorModelName, "-", propertyConfiguration.NumberOfJitters, "-", propertyConfiguration.NumberOfTimesToUpsample); result = Path.Combine(result, dateGroupDirectory); } else if (includeModel) diff --git a/Property/Property.csproj b/Property/Property.csproj index 39601ac..3c84b45 100644 --- a/Property/Property.csproj +++ b/Property/Property.csproj @@ -45,7 +45,7 @@ - + diff --git a/Resize/Models/_C_Resize.cs b/Resize/Models/_C_Resize.cs index a5945af..db4456a 100644 --- a/Resize/Models/_C_Resize.cs +++ b/Resize/Models/_C_Resize.cs @@ -313,12 +313,12 @@ public class C_Resize return results; } - public byte[] GetResizedBytes(string outputResolution, string cResultsFullGroupDirectory, List> subFileTuples, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary imageResizes) + public byte[] GetResizedBytes(string outputResolution, string cResultsFullGroupDirectory, List> subFileTuples, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary imageResizeKeyValuePairs) { byte[] results; - if (!imageResizes.ContainsKey(outputResolution)) + if (!imageResizeKeyValuePairs.ContainsKey(outputResolution)) throw new Exception(); - int[] resize = imageResizes[outputResolution]; + int[] resize = imageResizeKeyValuePairs[outputResolution]; int outputResolutionWidth = resize[_OutputResolutionWidthIndex]; int outputResolutionHeight = resize[_OutputResolutionHeightIndex]; int outputResolutionOrientation = resize[_OutputResolutionOrientationIndex]; @@ -327,34 +327,35 @@ public class C_Resize return results; } - public void SaveResizedSubfile(Property.Models.Configuration configuration, string outputResolution, string cResultsFullGroupDirectory, List> subFileTuples, Item item, Shared.Models.Property property, MappingFromItem mappingFromItem, string original, Dictionary imageResizes) + public void SaveResizedSubfile(Property.Models.Configuration configuration, string outputResolution, string cResultsFullGroupDirectory, List> subFileTuples, Item item, Shared.Models.Property property, MappingFromItem mappingFromItem, string original, Dictionary imageResizeKeyValuePairs) { if (mappingFromItem.ResizedFileHolder is null) throw new NullReferenceException(nameof(mappingFromItem.ResizedFileHolder)); - if (!imageResizes.ContainsKey(outputResolution)) + if (!imageResizeKeyValuePairs.ContainsKey(original)) + throw new Exception(); + if (!imageResizeKeyValuePairs.ContainsKey(outputResolution)) throw new Exception(); FileInfo fileInfo = new(mappingFromItem.ResizedFileHolder.FullName); - if (!fileInfo.FullName.Contains(configuration.ResultAllInOne) && !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); - item.SetResizedFileHolder(_FileNameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(mappingFromItem.ResizedFileHolder)); - fileInfo.Refresh(); - } - } - int[] resize = imageResizes[outputResolution]; + bool check = false; + int[] resize = imageResizeKeyValuePairs[outputResolution]; int outputResolutionWidth = resize[_OutputResolutionWidthIndex]; int outputResolutionHeight = resize[_OutputResolutionHeightIndex]; int outputResolutionOrientation = resize[_OutputResolutionOrientationIndex]; - int[] originalCollection = imageResizes[original]; + int[] originalCollection = imageResizeKeyValuePairs[original]; + string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata), nameof(C_Resize) }; + List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); + if (_OverrideForResizeImages) + check = true; + else if (!fileInfo.Exists) + check = true; if (outputResolutionWidth == originalCollection[_OutputResolutionWidthIndex] && outputResolutionHeight == originalCollection[_OutputResolutionHeightIndex] && outputResolutionOrientation == originalCollection[_OutputResolutionOrientationIndex]) { - if (!fileInfo.Exists) + if (!check && dateTimes.Any() && dateTimes.Max() > fileInfo.CreationTime.AddDays(1)) + check = true; + if (check) { + if (fileInfo.Exists) + File.Delete(fileInfo.FullName); File.Copy(mappingFromItem.ImageFileHolder.FullName, fileInfo.FullName); item.SetResizedFileHolder(_FileNameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(mappingFromItem.ResizedFileHolder)); subFileTuples.Add(new Tuple(nameof(C_Resize), DateTime.Now)); @@ -362,14 +363,7 @@ public class C_Resize } else { - bool check = false; - string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata), nameof(C_Resize) }; - List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - if (_OverrideForResizeImages) - check = true; - else if (!fileInfo.Exists) - check = true; - else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime) + if (!check && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime) check = true; if (check) { @@ -461,17 +455,6 @@ public class C_Resize List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); string cResizeSingletonFile = Path.Combine(cResultsFullGroupDirectory, "{}", configuration.ResultAllInOne, $"{mappingFromItem.Id}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json"); FileInfo fileInfo = new(cResizeSingletonFile); - if (!fileInfo.FullName.Contains(configuration.ResultAllInOne) && !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 (_ForceResizeLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) { File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); @@ -535,4 +518,13 @@ public class C_Resize return results; } + public static byte[] GetBytes(string value) + { + byte[] results = new byte[value.Length + 1]; + for (int i = 0; i < value.Length; i++) + results[i] = (byte)value[i]; + results[value.Length] = 0x00; + return results; + } + } \ No newline at end of file diff --git a/Resize/Resize.csproj b/Resize/Resize.csproj index d26cc67..57646c3 100644 --- a/Resize/Resize.csproj +++ b/Resize/Resize.csproj @@ -37,7 +37,7 @@ - + diff --git a/Shared/Models/FaceDistance.cs b/Shared/Models/FaceDistance.cs index d267996..ddc2fd6 100644 --- a/Shared/Models/FaceDistance.cs +++ b/Shared/Models/FaceDistance.cs @@ -12,10 +12,10 @@ public record class FaceDistance : Properties.IFaceDistance public bool? IsWrongYear { init; get; } public double? Length { init; get; } public DateTime? MinimumDateTime { init; get; } - public int? NormalizedPixelPercentage { init; get; } + public int? NormalizedRectangle { init; get; } [JsonConstructor] - public FaceDistance(int? confidencePercent, object? encoding, int id, bool? isWrongYear, double? length, DateTime? minimumDateTime, int? normalizedPixelPercentage) + public FaceDistance(int? confidencePercent, object? encoding, int id, bool? isWrongYear, double? length, DateTime? minimumDateTime, int? normalizedRectangle) { ConfidencePercent = confidencePercent; Encoding = encoding; @@ -23,15 +23,15 @@ public record class FaceDistance : Properties.IFaceDistance IsWrongYear = isWrongYear; Length = length; MinimumDateTime = minimumDateTime; - NormalizedPixelPercentage = normalizedPixelPercentage; + NormalizedRectangle = normalizedRectangle; } - public FaceDistance(int? confidencePercent, object? encoding, int id, bool? isWrongYear, DateTime? minimumDateTime, int? normalizedPixelPercentage) : - this(confidencePercent, encoding, id, isWrongYear, null, minimumDateTime, normalizedPixelPercentage) + public FaceDistance(int? confidencePercent, object? encoding, int id, bool? isWrongYear, DateTime? minimumDateTime, int? normalizedRectangle) : + this(confidencePercent, encoding, id, isWrongYear, null, minimumDateTime, normalizedRectangle) { } public FaceDistance(FaceDistance faceDistance, double length) : - this(faceDistance.ConfidencePercent, null, faceDistance.Id, faceDistance.IsWrongYear, length, faceDistance.MinimumDateTime, faceDistance.NormalizedPixelPercentage) + this(faceDistance.ConfidencePercent, null, faceDistance.Id, faceDistance.IsWrongYear, length, faceDistance.MinimumDateTime, faceDistance.NormalizedRectangle) { } public FaceDistance(object encoding) => Encoding = encoding; diff --git a/Shared/Models/FileHolder.cs b/Shared/Models/FileHolder.cs index 8864fd3..958f31e 100644 --- a/Shared/Models/FileHolder.cs +++ b/Shared/Models/FileHolder.cs @@ -10,6 +10,7 @@ public class FileHolder : Properties.IFileHolder protected readonly bool _Exists; protected readonly string _ExtensionLowered; protected readonly string _FullName; + protected readonly int? _Id; protected readonly DateTime? _LastWriteTime; protected readonly long? _Length; protected readonly string _Name; @@ -19,25 +20,27 @@ public class FileHolder : Properties.IFileHolder public bool Exists => _Exists; public string ExtensionLowered => _ExtensionLowered; public string FullName => _FullName; + public int? Id => _Id; public DateTime? LastWriteTime => _LastWriteTime; public long? Length => _Length; public string Name => _Name; public string NameWithoutExtension => _NameWithoutExtension; - public FileHolder(DateTime? creationTime, string? directoryName, bool exists, string extensionLowered, string fullName, DateTime? lastWriteTime, long? length, string name, string nameWithoutExtension) + public FileHolder(DateTime? creationTime, string? directoryName, bool exists, string extensionLowered, string fullName, int? id, DateTime? lastWriteTime, long? length, string name, string nameWithoutExtension) { _CreationTime = creationTime; _DirectoryName = directoryName; _Exists = exists; _ExtensionLowered = extensionLowered; _FullName = fullName; + _Id = id; _LastWriteTime = lastWriteTime; _Length = length; _Name = name; _NameWithoutExtension = nameWithoutExtension; } - public FileHolder(FileInfo fileInfo) + public FileHolder(FileInfo fileInfo, int? id) { if (fileInfo.Exists) { @@ -49,13 +52,18 @@ public class FileHolder : Properties.IFileHolder _DirectoryName = fileInfo.DirectoryName; _Exists = fileInfo.Exists; _ExtensionLowered = fileInfo.Extension.ToLower(); + _Id = id; _FullName = fileInfo.FullName; _Name = fileInfo.Name; _NameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName); } public FileHolder(string fileName) : - this(new FileInfo(fileName)) + this(new FileInfo(fileName), null) + { } + + public FileHolder(string fileName, int? id) : + this(new FileInfo(fileName), id) { } public override string ToString() diff --git a/Shared/Models/Item.cs b/Shared/Models/Item.cs index 0ac4886..0254800 100644 --- a/Shared/Models/Item.cs +++ b/Shared/Models/Item.cs @@ -16,7 +16,7 @@ public class Item : Properties.IItem protected Property? _Property; protected readonly string _RelativePath; protected FileHolder? _ResizedFileHolder; - protected readonly string _SourceDirectoryFile; + protected readonly FileHolder _SourceDirectoryFileHolder; protected bool _ValidImageFormatExtension; public bool? Abandoned => _Abandoned; public List Faces => _Faces; @@ -28,11 +28,11 @@ public class Item : Properties.IItem public Property? Property => _Property; public string RelativePath => _RelativePath; public FileHolder? ResizedFileHolder => _ResizedFileHolder; - public string SourceDirectoryFile => _SourceDirectoryFile; + public FileHolder SourceDirectoryFileHolder => _SourceDirectoryFileHolder; public bool ValidImageFormatExtension => _ValidImageFormatExtension; [JsonConstructor] - public Item(bool? abandoned, List faces, bool? fileSizeChanged, FileHolder imageFileHolder, bool? lastWriteTimeChanged, bool? moved, bool? noJson, Property? property, string relativePath, FileHolder? resizedFileHolder, string sourceDirectoryFile, bool validImageFormatExtension) + public Item(bool? abandoned, List faces, bool? fileSizeChanged, FileHolder imageFileHolder, bool? lastWriteTimeChanged, bool? moved, bool? noJson, Property? property, string relativePath, FileHolder? resizedFileHolder, FileHolder sourceDirectoryFileHolder, bool validImageFormatExtension) { _Faces = faces; _Moved = moved; @@ -43,13 +43,13 @@ public class Item : Properties.IItem _FileSizeChanged = fileSizeChanged; _ImageFileHolder = imageFileHolder; _ResizedFileHolder = resizedFileHolder; - _SourceDirectoryFile = sourceDirectoryFile; + _SourceDirectoryFileHolder = sourceDirectoryFileHolder; _LastWriteTimeChanged = lastWriteTimeChanged; _ValidImageFormatExtension = validImageFormatExtension; } - public Item(string sourceDirectoryFile, string relativePath, FileHolder imageFileInfo, bool validImageFormatExtension, Property? property, bool? abandoned, bool? fileSizeChanged, bool? lastWriteTimeChanged) : - this(abandoned, new(), fileSizeChanged, imageFileInfo, lastWriteTimeChanged, null, abandoned is null, property, relativePath, null, sourceDirectoryFile, validImageFormatExtension) + public Item(FileHolder sourceDirectoryFileHolder, string relativePath, FileHolder imageFileInfo, bool validImageFormatExtension, Property? property, bool? abandoned, bool? fileSizeChanged, bool? lastWriteTimeChanged) : + this(abandoned, new(), fileSizeChanged, imageFileInfo, lastWriteTimeChanged, null, abandoned is null, property, relativePath, null, sourceDirectoryFileHolder, validImageFormatExtension) { if (relativePath.EndsWith(".json")) throw new ArgumentException("Can not be a *.json file!"); @@ -57,8 +57,8 @@ public class Item : Properties.IItem throw new ArgumentException("Can not be a *.json file!"); } - public Item(string sourceDirectoryFile, string relativePath, bool isValidImageFormatExtension) : - this(sourceDirectoryFile, relativePath, new(sourceDirectoryFile), isValidImageFormatExtension, null, null, null, null) + public Item(FileHolder sourceDirectoryFileHolder, string relativePath, bool isValidImageFormatExtension) : + this(sourceDirectoryFileHolder, relativePath, sourceDirectoryFileHolder, isValidImageFormatExtension, null, null, null, null) { } public override string ToString() diff --git a/Shared/Models/Location.cs b/Shared/Models/Location.cs index 13149be..d78d3ef 100644 --- a/Shared/Models/Location.cs +++ b/Shared/Models/Location.cs @@ -20,7 +20,7 @@ public class Location : Properties.ILocation, IEquatable Left = left; Right = right; Top = top; - Stateless.Methods.Location.Check(bottom, left, right, top, zCount: 1); + _ = Stateless.Methods.Location.Check(bottom, left, right, top, zCount: 1, throwException: true); } public Location(double confidence, int height, Location location, int locationDigits, int locationFactor, int width, int zCount) : @@ -30,7 +30,7 @@ public class Location : Properties.ILocation, IEquatable location.Left, location.Right, location.Top) => - Stateless.Methods.Location.Check(Bottom, height, Left, Right, Top, width, zCount); + Stateless.Methods.Location.Check(Bottom, height, Left, Right, Top, width, zCount, throwException: true); public Location(int bottom, double confidence, int height, int left, int locationDigits, int locationFactor, int right, int top, int width, int zCount) : this( @@ -39,7 +39,7 @@ public class Location : Properties.ILocation, IEquatable left, right, top) => - Stateless.Methods.Location.Check(Bottom, height, Left, Right, Top, width, zCount); + Stateless.Methods.Location.Check(Bottom, height, Left, Right, Top, width, zCount, throwException: true); public Location(int height, Location location, int locationDigits, int locationFactor, int width, int zCount) : this( @@ -48,7 +48,7 @@ public class Location : Properties.ILocation, IEquatable location.Left, location.Right, location.Top) => - Stateless.Methods.Location.Check(Bottom, height, Left, Right, Top, width, zCount); + Stateless.Methods.Location.Check(Bottom, height, Left, Right, Top, width, zCount, throwException: true); public Location(double confidence, int factor, int height, Location location, int locationDigits, int locationFactor, int width, int zCount) { @@ -58,7 +58,7 @@ public class Location : Properties.ILocation, IEquatable int left = Math.Max(location.Left - x, 0); int right = Math.Min(location.Right + x, width); int top = Math.Max(location.Top - y, 0); - Stateless.Methods.Location.Check(Bottom, height, Left, Right, Top, width, zCount); + _ = Stateless.Methods.Location.Check(Bottom, height, Left, Right, Top, width, zCount, throwException: true); Confidence = confidence; Bottom = bottom; Left = left; diff --git a/Shared/Models/Mapping.cs b/Shared/Models/Mapping.cs index c906660..db2edde 100644 --- a/Shared/Models/Mapping.cs +++ b/Shared/Models/Mapping.cs @@ -6,6 +6,7 @@ namespace View_by_Distance.Shared.Models; public class MappingFromItem : Properties.IMappingFromItem { + public DateTime[] ContainerDateTimes { init; get; } public int Id { init; get; } public FileHolder ImageFileHolder { init; get; } public bool? IsWrongYear { init; get; } @@ -14,8 +15,9 @@ public class MappingFromItem : Properties.IMappingFromItem public FileHolder ResizedFileHolder { init; get; } [JsonConstructor] - public MappingFromItem(int id, FileHolder imageFileHolder, bool? isWrongYear, DateTime minimumDateTime, string relativePath, FileHolder resizedFileHolder) + public MappingFromItem(DateTime[] containerDateTimes, int id, FileHolder imageFileHolder, bool? isWrongYear, DateTime minimumDateTime, string relativePath, FileHolder resizedFileHolder) { + ContainerDateTimes = containerDateTimes; Id = id; ImageFileHolder = imageFileHolder; IsWrongYear = isWrongYear; @@ -30,7 +32,7 @@ public class MappingFromItem : Properties.IMappingFromItem return result; } - internal static MappingFromItem GetMappingFromItem(Item item, FileHolder? resizedFileHolder) + internal static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Item item, FileHolder? resizedFileHolder) { MappingFromItem result; bool? isWrongYear; @@ -41,7 +43,7 @@ public class MappingFromItem : Properties.IMappingFromItem throw new NotSupportedException(); minimumDateTime = Stateless.Methods.IProperty.GetMinimumDateTime(item.Property); (isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder, minimumDateTime); - result = new(item.Property.Id.Value, item.ImageFileHolder, isWrongYear, minimumDateTime, item.RelativePath, resizedFileHolder); + result = new(containerDateTimes, item.Property.Id.Value, item.ImageFileHolder, isWrongYear, minimumDateTime, item.RelativePath, resizedFileHolder); return result; } @@ -53,15 +55,15 @@ public class MappingFromLocation : Properties.IMappingFromLocation public int AreaPermille { init; get; } public int ConfidencePercent { init; get; } public string DeterministicHashCodeKey { init; get; } - public int NormalizedPixelPercentage { init; get; } + public int NormalizedRectangle { init; get; } [JsonConstructor] - public MappingFromLocation(int areaPermille, int confidencePercent, string deterministicHashCodeKey, int normalizedPixelPercentage) + public MappingFromLocation(int areaPermille, int confidencePercent, string deterministicHashCodeKey, int normalizedRectangle) { AreaPermille = areaPermille; ConfidencePercent = confidencePercent; DeterministicHashCodeKey = deterministicHashCodeKey; - NormalizedPixelPercentage = normalizedPixelPercentage; + NormalizedRectangle = normalizedRectangle; } public override string ToString() @@ -102,17 +104,20 @@ public class Mapping : Properties.IMapping protected int? _By; protected MappingFromPerson? _MappingFromPerson; + public string? _SegmentC; protected SortingContainer? _SortingContainer; public int? By => _By; public MappingFromItem MappingFromItem { init; get; } public MappingFromLocation MappingFromLocation { init; get; } public MappingFromPerson? MappingFromPerson => _MappingFromPerson; + public string? SegmentC => _SegmentC; public SortingContainer? SortingContainer => _SortingContainer; [JsonConstructor] - public Mapping(int? by, MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation, MappingFromPerson? mappingFromPerson, SortingContainer? sortingContainer) + public Mapping(int? by, MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation, MappingFromPerson? mappingFromPerson, string? segmentC, SortingContainer? sortingContainer) { _By = by; + _SegmentC = segmentC; MappingFromItem = mappingFromItem; MappingFromLocation = mappingFromLocation; _MappingFromPerson = mappingFromPerson; @@ -120,7 +125,7 @@ public class Mapping : Properties.IMapping } public Mapping(MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation) : - this(null, mappingFromItem, mappingFromLocation, null, null) + this(null, mappingFromItem, mappingFromLocation, null, null, null) { } public override string ToString() @@ -142,9 +147,10 @@ public class Mapping : Properties.IMapping _MappingFromPerson = new(approximateYears, displayDirectoryName, personBirthday, segmentB); } - public void UpdateMappingFromPerson(int? approximateYears, int? by, string displayDirectoryName, PersonBirthday personBirthday, string segmentB, SortingContainer sortingContainer) + public void UpdateMappingFromPerson(int? approximateYears, int? by, string displayDirectoryName, PersonBirthday personBirthday, string segmentB, string segmentC, SortingContainer sortingContainer) { _By = by; + _SegmentC = segmentC; _SortingContainer = sortingContainer; _MappingFromPerson = new(approximateYears, displayDirectoryName, personBirthday, segmentB); } diff --git a/Shared/Models/Marker.cs b/Shared/Models/Marker.cs new file mode 100644 index 0000000..bafd9d8 --- /dev/null +++ b/Shared/Models/Marker.cs @@ -0,0 +1,30 @@ +using System.Text.Json.Serialization; + +namespace View_by_Distance.Shared.Models; + +public record Marker( + [property: JsonPropertyName("marker_uid")] string MarkerUid, + [property: JsonPropertyName("file_uid")] string FileUid, + [property: JsonPropertyName("marker_type")] string MarkerType, + [property: JsonPropertyName("marker_src")] string MarkerSrc, + [property: JsonPropertyName("marker_name")] string MarkerName, + [property: JsonPropertyName("marker_review")] int MarkerReview, + [property: JsonPropertyName("marker_invalid")] int MarkerInvalid, + [property: JsonPropertyName("subj_uid")] string SubjUid, + [property: JsonPropertyName("subj_src")] string SubjSrc, + [property: JsonPropertyName("face_id")] string FaceId, + [property: JsonPropertyName("face_dist")] double FaceDist, + [property: JsonPropertyName("embeddings_json")] string EmbeddingsJson, + [property: JsonPropertyName("landmarks_json")] string LandmarksJson, + [property: JsonPropertyName("x")] double X, + [property: JsonPropertyName("y")] double Y, + [property: JsonPropertyName("w")] double W, + [property: JsonPropertyName("h")] double H, + [property: JsonPropertyName("q")] int Q, + [property: JsonPropertyName("size")] int Size, + [property: JsonPropertyName("score")] int Score, + [property: JsonPropertyName("thumb")] string Thumb, + [property: JsonPropertyName("matched_at")] string MatchedAt, + [property: JsonPropertyName("created_at")] string CreatedAt, + [property: JsonPropertyName("updated_at")] string UpdatedAt +); \ No newline at end of file diff --git a/Shared/Models/MarkerWith.cs b/Shared/Models/MarkerWith.cs new file mode 100644 index 0000000..51e5acb --- /dev/null +++ b/Shared/Models/MarkerWith.cs @@ -0,0 +1,36 @@ +namespace View_by_Distance.Shared.Models; + +public record MarkerWith( + string MarkerUid, + string FileUid, + string MarkerType, + string MarkerSrc, + string MarkerName, + int MarkerReview, + int MarkerInvalid, + string SubjUid, + string SubjSrc, + string FaceId, + double FaceDist, + string EmbeddingsJson, + string LandmarksJson, + double X, + double Y, + double W, + double H, + int Q, + int Size, + int Score, + string Thumb, + string MatchedAt, + string CreatedAt, + string UpdatedAt, + int FileId, + string FileName, + int? DlibId, + int? Count, + double? Percent, + int? NormalizedRectangle, + long? PersonKey, + string PersonKeyFormatted +); \ No newline at end of file diff --git a/Shared/Models/Properties/IFaceDistance.cs b/Shared/Models/Properties/IFaceDistance.cs index 0e8f6fd..542b79b 100644 --- a/Shared/Models/Properties/IFaceDistance.cs +++ b/Shared/Models/Properties/IFaceDistance.cs @@ -9,6 +9,6 @@ public interface IFaceDistance public bool? IsWrongYear { init; get; } public double? Length { init; get; } public DateTime? MinimumDateTime { init; get; } - public int? NormalizedPixelPercentage { init; get; } + public int? NormalizedRectangle { init; get; } } \ No newline at end of file diff --git a/Shared/Models/Properties/IItem.cs b/Shared/Models/Properties/IItem.cs index 3eee95b..d94a3dd 100644 --- a/Shared/Models/Properties/IItem.cs +++ b/Shared/Models/Properties/IItem.cs @@ -12,7 +12,7 @@ public interface IItem public Property? Property { get; } public string RelativePath { get; } public FileHolder? ResizedFileHolder { get; } - public string SourceDirectoryFile { get; } + public FileHolder SourceDirectoryFileHolder { get; } public bool ValidImageFormatExtension { get; } } \ No newline at end of file diff --git a/Shared/Models/Properties/IMapping.cs b/Shared/Models/Properties/IMapping.cs index a317e65..069e6d7 100644 --- a/Shared/Models/Properties/IMapping.cs +++ b/Shared/Models/Properties/IMapping.cs @@ -3,6 +3,7 @@ namespace View_by_Distance.Shared.Models.Properties; public interface IMappingFromItem { + public DateTime[] ContainerDateTimes { init; get; } public int Id { init; get; } public FileHolder ImageFileHolder { init; get; } public bool? IsWrongYear { init; get; } @@ -18,7 +19,7 @@ public interface IMappingFromLocation public int AreaPermille { init; get; } public int ConfidencePercent { init; get; } public string DeterministicHashCodeKey { init; get; } - public int NormalizedPixelPercentage { init; get; } + public int NormalizedRectangle { init; get; } } @@ -36,6 +37,7 @@ public interface IMapping { public int? By { get; } + public string? SegmentC { get; } public MappingFromItem MappingFromItem { init; get; } public MappingFromLocation MappingFromLocation { init; get; } public MappingFromPerson? MappingFromPerson { get; } diff --git a/Shared/Models/Properties/IProperty.cs b/Shared/Models/Properties/IProperty.cs index 5049e11..5c4fcdf 100644 --- a/Shared/Models/Properties/IProperty.cs +++ b/Shared/Models/Properties/IProperty.cs @@ -12,7 +12,6 @@ public interface IProperty public DateTime? GPSDateStamp { get; } public int? Height { get; } public int? Id { get; } - public int[] Indices { get; } public DateTime LastWriteTime { get; } public string Make { get; } public string Model { get; } diff --git a/Shared/Models/Properties/IPropertyConfiguration.cs b/Shared/Models/Properties/IPropertyConfiguration.cs index 726ef0c..00b95ac 100644 --- a/Shared/Models/Properties/IPropertyConfiguration.cs +++ b/Shared/Models/Properties/IPropertyConfiguration.cs @@ -4,16 +4,17 @@ public interface IPropertyConfiguration { public string DateGroup { init; get; } - public string? ModelName { get; } - public int? NumberOfJitters { get; } - public int? NumberOfTimesToUpsample { get; } - public string? PredictorModelName { get; } + public string[] IgnoreExtensions { init; get; } public string[] PropertyContentCollectionFiles { init; get; } public string ResultAllInOne { init; get; } public string ResultCollection { init; get; } public string ResultContent { init; get; } public string ResultSingleton { init; get; } - public string RootDirectory { get; } public string[] VerifyToSeason { init; get; } + public string? ModelName { get; } + public int? NumberOfJitters { get; } + public int? NumberOfTimesToUpsample { get; } + public string? PredictorModelName { get; } + public string RootDirectory { get; } } \ No newline at end of file diff --git a/Shared/Models/Properties/IRelativeLocation.cs b/Shared/Models/Properties/IRelativeLocation.cs new file mode 100644 index 0000000..e122db0 --- /dev/null +++ b/Shared/Models/Properties/IRelativeLocation.cs @@ -0,0 +1,12 @@ +namespace View_by_Distance.Shared.Models.Properties; + +public interface IRelativeLocation +{ + + public double Confidence { init; get; } + public string Height { init; get; } + public string Left { init; get; } + public string Top { init; get; } + public string Width { init; get; } + +} \ No newline at end of file diff --git a/Shared/Models/Properties/ISorting.cs b/Shared/Models/Properties/ISorting.cs index ac28ff1..082a845 100644 --- a/Shared/Models/Properties/ISorting.cs +++ b/Shared/Models/Properties/ISorting.cs @@ -6,7 +6,7 @@ public interface ISorting public int DaysDelta { init; get; } public int DistancePermyriad { init; get; } public int Id { init; get; } - public int NormalizedPixelPercentage { init; get; } + public int NormalizedRectangle { init; get; } public int WithinRange { init; get; } } \ No newline at end of file diff --git a/Shared/Models/Property.cs b/Shared/Models/Property.cs index 90b7fe6..5c48358 100644 --- a/Shared/Models/Property.cs +++ b/Shared/Models/Property.cs @@ -15,7 +15,6 @@ public class Property : Properties.IProperty protected DateTime? _GPSDateStamp; protected int? _Height; protected int? _Id; - protected int[] _Indices; protected DateTime _LastWriteTime; protected string _Make; protected string _Model; @@ -30,7 +29,6 @@ public class Property : Properties.IProperty public DateTime? GPSDateStamp => _GPSDateStamp; public int? Height => _Height; public int? Id => _Id; - public int[] Indices => _Indices; public DateTime LastWriteTime => _LastWriteTime; public string Make => _Make; public string Model => _Model; @@ -38,7 +36,7 @@ public class Property : Properties.IProperty public int? Width => _Width; [JsonConstructor] - public Property(DateTime creationTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, long fileSize, DateTime? gpsDateStamp, int? height, int? id, int[] indices, DateTime lastWriteTime, string make, string model, string orientation, int? width) + public Property(DateTime creationTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, long fileSize, DateTime? gpsDateStamp, int? height, int? id, DateTime lastWriteTime, string make, string model, string orientation, int? width) { _DateTimeFromName = dateTimeFromName; _CreationTime = creationTime; @@ -49,7 +47,6 @@ public class Property : Properties.IProperty _GPSDateStamp = gpsDateStamp; _Height = height; _Id = id; - _Indices = indices; _LastWriteTime = lastWriteTime; _Make = make; _Model = model; diff --git a/Shared/Models/RelativeLocation.cs b/Shared/Models/RelativeLocation.cs new file mode 100644 index 0000000..317d742 --- /dev/null +++ b/Shared/Models/RelativeLocation.cs @@ -0,0 +1,43 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace View_by_Distance.Shared.Models; + +public class RelativeLocation : Properties.IRelativeLocation +{ + + public double Confidence { init; get; } + public string Height { init; get; } + public string Left { init; get; } + public string Top { init; get; } + public string Width { init; get; } + + [JsonConstructor] + public RelativeLocation(double confidence, string height, string left, string top, string width) + { + Confidence = confidence; + Height = height; + Left = left; + Top = top; + Width = width; + } + + public bool Match(decimal? height, decimal? left, decimal? top, decimal? width) + { + bool result; + if (height is null || left is null || top is null || width is null) + result = false; + else if (height.Value.ToString() == Height && left.Value.ToString() == Left && top.Value.ToString() == Top && width.Value.ToString() == Width) + result = false; + else + result = true; + return result; + } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + +} \ No newline at end of file diff --git a/Shared/Models/Sorting.cs b/Shared/Models/Sorting.cs index c2d4644..b7e89a1 100644 --- a/Shared/Models/Sorting.cs +++ b/Shared/Models/Sorting.cs @@ -9,17 +9,17 @@ public record class Sorting : Properties.ISorting public int DaysDelta { init; get; } public int DistancePermyriad { init; get; } public int Id { init; get; } - public int NormalizedPixelPercentage { init; get; } + public int NormalizedRectangle { init; get; } public bool Older { init; get; } public int WithinRange { init; get; } [JsonConstructor] - public Sorting(int daysDelta, int distancePermyriad, int id, int normalizedPixelPercentage, bool older, int withinRange) + public Sorting(int daysDelta, int distancePermyriad, int id, int normalizedRectangle, bool older, int withinRange) { DaysDelta = daysDelta; DistancePermyriad = distancePermyriad; Id = id; - NormalizedPixelPercentage = normalizedPixelPercentage; + NormalizedRectangle = normalizedRectangle; Older = older; WithinRange = withinRange; } diff --git a/Shared/Models/SortingContainer.cs b/Shared/Models/SortingContainer.cs index fbe83d1..bb30eab 100644 --- a/Shared/Models/SortingContainer.cs +++ b/Shared/Models/SortingContainer.cs @@ -17,7 +17,7 @@ public record class SortingContainer : Properties.ISortingContainer public override string ToString() { - string result = string.Concat(Mapping.MappingFromItem.Id, '\t', Mapping.MappingFromLocation.NormalizedPixelPercentage, '\t', Sorting.Id, '\t', Sorting.NormalizedPixelPercentage, '\t', Sorting.Older, '\t', Sorting.WithinRange, '\t', Sorting.DistancePermyriad, '\t', Sorting.DaysDelta); + string result = string.Concat(Mapping.MappingFromItem.Id, '\t', Mapping.MappingFromLocation.NormalizedRectangle, '\t', Sorting.Id, '\t', Sorting.NormalizedRectangle, '\t', Sorting.Older, '\t', Sorting.WithinRange, '\t', Sorting.DistancePermyriad, '\t', Sorting.DaysDelta); return result; } diff --git a/Shared/Models/Stateless/Methods/Container.cs b/Shared/Models/Stateless/Methods/Container.cs index 4cfd380..4f7ff4c 100644 --- a/Shared/Models/Stateless/Methods/Container.cs +++ b/Shared/Models/Stateless/Methods/Container.cs @@ -3,6 +3,93 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class Container { - internal static double GetDefaultValue() => throw new Exception(); + internal static DateTime[] GetContainerDateTimes(Models.Item[] filteredItems) + { + DateTime[] results; + DateTime? containerMinimumDateTime; + DateTime? containerMaximumDateTime; + containerMinimumDateTime = (from l in filteredItems select l.ImageFileHolder.LastWriteTime).Min(); + if (containerMinimumDateTime is null) + containerMaximumDateTime = null; + else + containerMaximumDateTime = (from l in filteredItems select l.ImageFileHolder.LastWriteTime).Max(); + if (containerMinimumDateTime is null || containerMaximumDateTime is null) + results = Array.Empty(); + else + results = new DateTime[] { containerMinimumDateTime.Value, containerMaximumDateTime.Value }; + return results; + } + + internal static Models.Item[] GetFilterItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container container) + { + List results = new(); + foreach (Models.Item item in container.Items) + { + if (item.ImageFileHolder is not null + && (item.Abandoned is null || !item.Abandoned.Value) + && item.ValidImageFormatExtension + && !propertyConfiguration.IgnoreExtensions.Contains(item.ImageFileHolder.ExtensionLowered)) + results.Add(item); + } + return results.ToArray(); + } + + internal static bool IsIgnoreRelativePath(Properties.IPropertyConfiguration propertyConfiguration, string[] ignoreRelativePaths, string directory) + { + bool result = false; + string? checkDirectory = Path.GetFullPath(directory); + for (int i = 0; i < int.MaxValue; i++) + { + if (ignoreRelativePaths.Contains(Path.GetFileName(checkDirectory))) + { + result = true; + break; + } + checkDirectory = Path.GetDirectoryName(checkDirectory); + if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == propertyConfiguration.RootDirectory) + break; + } + return result; + } + + internal static Models.Container[] SortContainers(Properties.IPropertyConfiguration propertyConfiguration, string[] ignoreRelativePaths, bool argZeroIsConfigurationRootDirectory, string argZero, Models.Container[] containers) + { + List results = new(); + Models.Item[] filteredItems; + bool isIgnoreRelativePath; + List collection = new(); + for (int i = 1; i < 3; i++) + { + foreach (Models.Container container in containers) + { + if (!container.Items.Any()) + continue; + if (!argZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) + continue; + filteredItems = GetFilterItems(propertyConfiguration, container); + if (!filteredItems.Any()) + continue; + isIgnoreRelativePath = ignoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && IsIgnoreRelativePath(propertyConfiguration, ignoreRelativePaths, container.SourceDirectory); + if (i == 1 && isIgnoreRelativePath) + continue; + if (i == 2 && !isIgnoreRelativePath) + continue; + foreach (Models.Item item in filteredItems) + { + if (item.Property?.Id is null) + continue; + if (collection.Contains(item.Property.Id.Value)) + { + if (i == 1) + continue; + continue; + } + collection.Add(item.Property.Id.Value); + } + results.Add(container); + } + } + return results.ToArray(); + } } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/FileHolder.cs b/Shared/Models/Stateless/Methods/FileHolder.cs index f68c80e..b8917c3 100644 --- a/Shared/Models/Stateless/Methods/FileHolder.cs +++ b/Shared/Models/Stateless/Methods/FileHolder.cs @@ -3,6 +3,129 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class FileHolder { - internal static double GetDefaultValue() => throw new Exception(); + internal static List GetFileHolders((string, string[])[] collection) + { + List results = new(); + foreach ((string _, string[] files) in collection) + results.AddRange(files.Select(l => new Models.FileHolder(l))); + return results; + } + + internal static IEnumerable GetFileHolders(IEnumerable<(string, string)> collection) + { + foreach ((string _, string file) in collection) + yield return new(file); + } + + internal static IEnumerable<(string, string[])> GetFiles(string root, string searchPattern) + { + Stack pending = new(); + pending.Push(root); + while (pending.Count != 0) + { + string[]? next = null; + string path = pending.Pop(); + try + { + next = Directory.GetFiles(path, searchPattern); + } + catch { } + if (next is not null && next.Any()) + yield return new(path, next); + try + { + next = Directory.GetDirectories(path); + foreach (string subDirectory in next) + pending.Push(subDirectory); + } + catch { } + } + } + + internal static (int t, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)>) GetGroupCollection(string rootDirectory, int maxImagesInDirectoryForTopLevelFirstPass, bool reverse, string searchPattern, List topDirectories) + { + int result = 0; + List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> results = new(); + string? parentDirectory; + string[] subDirectories; + string[] sourceDirectoryFiles; + List fileCollections = new(); + if (!topDirectories.Any()) + { + if (!Directory.Exists(rootDirectory)) + _ = Directory.CreateDirectory(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) + { + for (int i = fileCollections.Count - 1; i > -1; i--) + { + parentDirectory = Path.GetDirectoryName(fileCollections[i][0]); + if (string.IsNullOrEmpty(parentDirectory)) + continue; + results.Add(new(g, parentDirectory, fileCollections[i])); + fileCollections.RemoveAt(i); + } + } + else if (g == 2) + { + for (int i = fileCollections.Count - 1; i > -1; i--) + { + if (fileCollections[i].Length > maxImagesInDirectoryForTopLevelFirstPass * g) + break; + parentDirectory = Path.GetDirectoryName(fileCollections[i][0]); + if (string.IsNullOrEmpty(parentDirectory)) + continue; + results.Add(new(g, parentDirectory, fileCollections[i])); + fileCollections.RemoveAt(i); + } + } + else if (g == 3) + { + subDirectories = Directory.GetDirectories(rootDirectory, "*", SearchOption.AllDirectories); + if (reverse) + subDirectories = subDirectories.Reverse().ToArray(); + foreach (string subDirectory in subDirectories) + { + sourceDirectoryFiles = Directory.GetFiles(subDirectory, "*", SearchOption.TopDirectoryOnly); + result += sourceDirectoryFiles.Length; + if (!topDirectories.Contains(subDirectory)) + results.Add(new(g, subDirectory, sourceDirectoryFiles)); + } + } + else if (g == 1) + { + sourceDirectoryFiles = Directory.GetFiles(rootDirectory, searchPattern, SearchOption.TopDirectoryOnly); + result += sourceDirectoryFiles.Length; + if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass) + fileCollections.Add(sourceDirectoryFiles); + else + results.Add(new(g, rootDirectory, sourceDirectoryFiles)); + if (reverse) + topDirectories.Reverse(); + subDirectories = topDirectories.ToArray(); + foreach (string subDirectory in subDirectories) + { + sourceDirectoryFiles = Directory.GetFiles(subDirectory, searchPattern, SearchOption.TopDirectoryOnly); + result += sourceDirectoryFiles.Length; + if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass) + fileCollections.Add(sourceDirectoryFiles); + else + { + if (sourceDirectoryFiles.Any() || Directory.GetDirectories(subDirectory, "*", SearchOption.TopDirectoryOnly).Any()) + results.Add(new(g, subDirectory, sourceDirectoryFiles)); + else if (searchPattern == "*" && subDirectory != rootDirectory) + Directory.Delete(subDirectory); + } + } + fileCollections.Reverse(); + } + else + throw new Exception(); + } + return new(result, results); + } } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IContainer.cs b/Shared/Models/Stateless/Methods/IContainer.cs index 5cc804b..05bbd5c 100644 --- a/Shared/Models/Stateless/Methods/IContainer.cs +++ b/Shared/Models/Stateless/Methods/IContainer.cs @@ -1,10 +1,26 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; public interface IContainer -{ // ... +{ - double TestStatic_GetDefaultValue(); + DateTime[] TestStatic_GetContainerDateTimes(Models.Item[] filteredItems) => + GetContainerDateTimes(filteredItems); + static DateTime[] GetContainerDateTimes(Models.Item[] filteredItems) => + Container.GetContainerDateTimes(filteredItems); - static double GetDefaultValue() => Container.GetDefaultValue(); + Models.Item[] TestStatic_GetFilterItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container container) => + GetFilterItems(propertyConfiguration, container); + static Models.Item[] GetFilterItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container container) => + Container.GetFilterItems(propertyConfiguration, container); + + bool TestStatic_IsIgnoreRelativePath(Properties.IPropertyConfiguration propertyConfiguration, string[] ignoreRelativePaths, string directory) => + IsIgnoreRelativePath(propertyConfiguration, ignoreRelativePaths, directory); + static bool IsIgnoreRelativePath(Properties.IPropertyConfiguration propertyConfiguration, string[] ignoreRelativePaths, string directory) => + Container.IsIgnoreRelativePath(propertyConfiguration, ignoreRelativePaths, directory); + + Models.Container[] TestStatic_SortContainers(Properties.IPropertyConfiguration propertyConfiguration, string[] ignoreRelativePaths, bool argZeroIsConfigurationRootDirectory, string argZero, Models.Container[] containers) => + SortContainers(propertyConfiguration, ignoreRelativePaths, argZeroIsConfigurationRootDirectory, argZero, containers); + static Models.Container[] SortContainers(Properties.IPropertyConfiguration propertyConfiguration, string[] ignoreRelativePaths, bool argZeroIsConfigurationRootDirectory, string argZero, Models.Container[] containers) => + Container.SortContainers(propertyConfiguration, ignoreRelativePaths, argZeroIsConfigurationRootDirectory, argZero, containers); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IFileHolder.cs b/Shared/Models/Stateless/Methods/IFileHolder.cs index 6537e08..580b492 100644 --- a/Shared/Models/Stateless/Methods/IFileHolder.cs +++ b/Shared/Models/Stateless/Methods/IFileHolder.cs @@ -1,9 +1,31 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; public interface IFileHolder -{ // ... +{ - Models.FileHolder TestStatic_Refresh(); - static Models.FileHolder Refresh(Models.FileHolder fileHolder) => new(fileHolder.FullName); + IEnumerable<(string, string[])> TestStatic_GetFiles(string root, string searchPattern) => + GetFiles(root, searchPattern); + static IEnumerable<(string, string[])> GetFiles(string root, string searchPattern) => + FileHolder.GetFiles(root, searchPattern); + + List TestStatic_GetFileHolders((string, string[])[] collection) => + GetFileHolders(collection); + static List GetFileHolders((string, string[])[] collection) => + FileHolder.GetFileHolders(collection); + + IEnumerable TestStatic_GetFileHolders(IEnumerable<(string, string)> collection) => + GetFileHolders(collection); + static IEnumerable GetFileHolders(IEnumerable<(string, string)> collection) => + FileHolder.GetFileHolders(collection); + + Models.FileHolder TestStatic_Refresh(Models.FileHolder fileHolder) => + Refresh(fileHolder); + static Models.FileHolder Refresh(Models.FileHolder fileHolder) => + new(fileHolder.FullName); + + (int t, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)>) TestStatic_GetGroupCollection(string rootDirectory, int maxImagesInDirectoryForTopLevelFirstPass, bool reverse, string searchPattern, List topDirectories) => + GetGroupCollection(rootDirectory, maxImagesInDirectoryForTopLevelFirstPass, reverse, searchPattern, topDirectories); + static (int t, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)>) GetGroupCollection(string rootDirectory, int maxImagesInDirectoryForTopLevelFirstPass, bool reverse, string searchPattern, List topDirectories) => + FileHolder.GetGroupCollection(rootDirectory, maxImagesInDirectoryForTopLevelFirstPass, reverse, searchPattern, topDirectories); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/ILocation.cs b/Shared/Models/Stateless/Methods/ILocation.cs index 5736cb0..33edb18 100644 --- a/Shared/Models/Stateless/Methods/ILocation.cs +++ b/Shared/Models/Stateless/Methods/ILocation.cs @@ -18,10 +18,10 @@ public interface ILocation static string GetLeftPadded(int locationDigits, int value) => GetLeftPadded(locationDigits, value.ToString()); - (int?, int?) TestStatic_GetXY(int locationDigits, int locationFactor, int width, int height, string normalizedPixelPercentage) => - GetXY(locationDigits, locationFactor, width, height, normalizedPixelPercentage); - static (int?, int?) GetXY(int locationDigits, int locationFactor, int width, int height, string normalizedPixelPercentage) => - Location.GetXY(locationDigits, locationFactor, width, height, normalizedPixelPercentage); + (int?, int?) TestStatic_GetXY(int locationDigits, int locationFactor, int width, int height, string normalizedRectangle) => + GetXY(locationDigits, locationFactor, width, height, normalizedRectangle); + static (int?, int?) GetXY(int locationDigits, int locationFactor, int width, int height, string normalizedRectangle) => + Location.GetXY(locationDigits, locationFactor, width, height, normalizedRectangle); Models.Location? TestStatic_GetLocation(Models.Location? location, int locationDigits, int locationFactor, int height, int width, int zCount) => GetLocation(location, locationDigits, locationFactor, height, width, zCount); @@ -33,15 +33,35 @@ public interface ILocation static Models.Location? GetLocation(int factor, Models.Location? location, int locationDigits, int locationFactor, int height, int width, int zCount) => location is null ? null : new(location.Confidence, factor, height, location, locationDigits, locationFactor, width, zCount); - int TestStatic_GetNormalizedPixelPercentage(Models.Location location, int locationDigits, int locationFactor, OutputResolution outputResolution) => - GetNormalizedPixelPercentage(location, locationDigits, locationFactor, outputResolution); - static int GetNormalizedPixelPercentage(Models.Location location, int locationDigits, int locationFactor, OutputResolution outputResolution) => - Location.GetNormalizedPixelPercentage(location.Bottom, outputResolution.Height, location.Left, locationDigits, locationFactor, location.Right, location.Top, outputResolution.Width, zCount: 1); + (int?, int?) TestStatic_GetCenterRoundedXY(int bottom, int height, int left, int locationFactor, int right, int top, int width) => + GetCenterRoundedXY(bottom, height, left, locationFactor, right, top, width); + static (int?, int?) GetCenterRoundedXY(int bottom, int height, int left, int locationFactor, int right, int top, int width) => + Location.GetCenterRoundedXY(bottom, height, left, locationFactor, right, top, width, zCount: 1); - int TestStatic_GetNormalizedPixelPercentage(int bottom, int height, int left, int locationDigits, int locationFactor, int right, int top, int width) => - GetNormalizedPixelPercentage(bottom, height, left, locationDigits, locationFactor, right, top, width); - static int GetNormalizedPixelPercentage(int bottom, int height, int left, int locationDigits, int locationFactor, int right, int top, int width) => - Location.GetNormalizedPixelPercentage(bottom, height, left, locationDigits, locationFactor, right, top, width, zCount: 1); + (decimal?, decimal?, decimal?, decimal?) TestStatic_GetHeightLeftTopWidth(int bottom, int height, int left, int right, int top, int width) => + GetHeightLeftTopWidth(bottom, height, left, right, top, width); + static (decimal?, decimal?, decimal?, decimal?) GetHeightLeftTopWidth(int bottom, int height, int left, int right, int top, int width) => + Location.GetHeightLeftTopWidth(bottom, height, left, right, top, width, zCount: 1); + + (decimal?, decimal?, decimal?, decimal?) TestStatic_GetHeightLeftTopWidth(int height, int left, int top, int width) => + GetHeightLeftTopWidth(height, left, top, width); + static (decimal?, decimal?, decimal?, decimal?) GetHeightLeftTopWidth(int height, int left, int top, int width) => + Location.GetHeightLeftTopWidth(top + height, height, left, left + width, top, width, zCount: 1); + + (decimal?, decimal?, decimal?, decimal?) TestStatic_GetHeightLeftTopWidth(Models.Location location, Models.OutputResolution outputResolution) => + GetHeightLeftTopWidth(location, outputResolution); + static (decimal?, decimal?, decimal?, decimal?) GetHeightLeftTopWidth(Models.Location location, Models.OutputResolution outputResolution) => + Location.GetHeightLeftTopWidth(location.Bottom, OutputResolution.Get(outputResolution).Height, location.Left, location.Right, location.Top, OutputResolution.Get(outputResolution).Width, zCount: 1); + + int TestStatic_GetNormalizedRectangle(Models.Location location, int locationDigits, Models.OutputResolution outputResolution) => + GetNormalizedRectangle(location, locationDigits, outputResolution); + static int GetNormalizedRectangle(Models.Location location, int locationDigits, Models.OutputResolution outputResolution) => + Location.GetNormalizedRectangle(location.Bottom, OutputResolution.Get(outputResolution).Height, location.Left, locationDigits, location.Right, location.Top, OutputResolution.Get(outputResolution).Width, zCount: 1); + + int TestStatic_GetNormalizedRectangle(int bottom, int height, int left, int locationDigits, int right, int top, int width) => + GetNormalizedRectangle(bottom, height, left, locationDigits, right, top, width); + static int GetNormalizedRectangle(int bottom, int height, int left, int locationDigits, int right, int top, int width) => + Location.GetNormalizedRectangle(bottom, height, left, locationDigits, right, top, width, zCount: 1); Models.Location TestStatic_GetTrimBound(double detectionConfidence, System.Drawing.Rectangle rectangle, int width, int height, int facesCount) => TrimBound(detectionConfidence, rectangle, width, height, facesCount); diff --git a/Shared/Models/Stateless/Methods/IMapping.cs b/Shared/Models/Stateless/Methods/IMapping.cs index 57fa8df..e687a5d 100644 --- a/Shared/Models/Stateless/Methods/IMapping.cs +++ b/Shared/Models/Stateless/Methods/IMapping.cs @@ -18,24 +18,24 @@ public interface IMapping static int GetAreaPermille(int faceAreaPermille, int bottom, int height, int left, int right, int top, int width) => Mapping.GetAreaPermille(faceAreaPermille, bottom, height, left, right, top, width); - int TestStatic_GetAreaPermille(int faceAreaPermille, Models.Location location, OutputResolution outputResolution) + int TestStatic_GetAreaPermille(int faceAreaPermille, Models.Location location, Models.OutputResolution outputResolution) => GetAreaPermille(faceAreaPermille, location, outputResolution); - static int GetAreaPermille(int faceAreaPermille, Models.Location location, OutputResolution outputResolution) + static int GetAreaPermille(int faceAreaPermille, Models.Location location, Models.OutputResolution outputResolution) => Mapping.GetAreaPermille(faceAreaPermille, location.Bottom, outputResolution.Height, location.Left, location.Right, location.Top, outputResolution.Width); - string TestStatic_GetDeterministicHashCodeKey(int id, Models.Location location, int locationDigits, int locationFactor, OutputResolution outputResolution) - => GetDeterministicHashCodeKey(id, location, locationDigits, locationFactor, outputResolution); - static string GetDeterministicHashCodeKey(int id, Models.Location location, int locationDigits, int locationFactor, OutputResolution outputResolution) - => $"{id}.{ILocation.GetLeftPadded(locationDigits, ILocation.GetNormalizedPixelPercentage(location, locationDigits, locationFactor, outputResolution))}"; + string TestStatic_GetDeterministicHashCodeKey(int id, Models.Location location, int locationDigits, Models.OutputResolution outputResolution) + => GetDeterministicHashCodeKey(id, location, locationDigits, outputResolution); + static string GetDeterministicHashCodeKey(int id, Models.Location location, int locationDigits, Models.OutputResolution outputResolution) + => $"{id}.{ILocation.GetLeftPadded(locationDigits, ILocation.GetNormalizedRectangle(location, locationDigits, outputResolution))}"; - (int?, int?, List?) TestStatic_GetReversedDeterministicHashCodeKey(string facesFileNameExtension, string file) => - GetReversedDeterministicHashCodeKey(facesFileNameExtension, file); - static (int?, int?, List?) GetReversedDeterministicHashCodeKey(string facesFileNameExtension, string file) => - Mapping.GetReversedDeterministicHashCodeKey(facesFileNameExtension, false, new(), file); + (int?, int?, List?) TestStatic_GetConverted(string facesFileNameExtension, string file) => + GetConverted(facesFileNameExtension, file); + static (int?, int?, List?) GetConverted(string facesFileNameExtension, string file) => + Mapping.GetConverted(facesFileNameExtension, false, new(), file); - (int?, int?, List?) TestStatic_GetReversedDeterministicHashCodeKey(string facesFileNameExtension, bool idToMappingCollectionAny, Dictionary> idToMappingCollection, string file) => - GetReversedDeterministicHashCodeKey(facesFileNameExtension, idToMappingCollectionAny, idToMappingCollection, file); - static (int?, int?, List?) GetReversedDeterministicHashCodeKey(string facesFileNameExtension, bool idToMappingCollectionAny, Dictionary> idToMappingCollection, string file) => - Mapping.GetReversedDeterministicHashCodeKey(facesFileNameExtension, idToMappingCollectionAny, idToMappingCollection, file); + (int?, int?, List?) TestStatic_GetConverted(string facesFileNameExtension, bool idToMappingCollectionAny, Dictionary> idToMappingCollection, string file) => + GetConverted(facesFileNameExtension, idToMappingCollectionAny, idToMappingCollection, file); + static (int?, int?, List?) GetConverted(string facesFileNameExtension, bool idToMappingCollectionAny, Dictionary> idToMappingCollection, string file) => + Mapping.GetConverted(facesFileNameExtension, idToMappingCollectionAny, idToMappingCollection, file); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IMappingFromItem.cs b/Shared/Models/Stateless/Methods/IMappingFromItem.cs index 91932bc..0ed6a86 100644 --- a/Shared/Models/Stateless/Methods/IMappingFromItem.cs +++ b/Shared/Models/Stateless/Methods/IMappingFromItem.cs @@ -3,14 +3,19 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; public interface IMappingFromItem { // ... - MappingFromItem TestStatic_GetMappingFromItem(Models.Item item, Models.FileHolder? resizedFileHolder) - => GetMappingFromItem(item, resizedFileHolder); - static MappingFromItem GetMappingFromItem(Models.Item item, Models.FileHolder? resizedFileHolder) - => MappingFromItem.GetMappingFromItem(item, resizedFileHolder); + MappingFromItem TestStatic_GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, Models.FileHolder? resizedFileHolder) + => GetMappingFromItem(containerDateTimes, item, resizedFileHolder); + static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, Models.FileHolder? resizedFileHolder) + => MappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); + + MappingFromItem TestStatic_GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item) + => GetMappingFromItem(containerDateTimes, item); + static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item) + => GetMappingFromItem(containerDateTimes, item, item.ResizedFileHolder); MappingFromItem TestStatic_GetMappingFromItem(Models.Item item) => GetMappingFromItem(item); static MappingFromItem GetMappingFromItem(Models.Item item) - => GetMappingFromItem(item, item.ResizedFileHolder); + => GetMappingFromItem(containerDateTimes: Array.Empty(), item, item.ResizedFileHolder); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IOutputResolution.cs b/Shared/Models/Stateless/Methods/IOutputResolution.cs new file mode 100644 index 0000000..9248612 --- /dev/null +++ b/Shared/Models/Stateless/Methods/IOutputResolution.cs @@ -0,0 +1,16 @@ +namespace View_by_Distance.Shared.Models.Stateless.Methods; + +public interface IOutputResolution +{ // ... + + int TestStatic_GetHeight(Models.OutputResolution outputResolution) => + GetHeight(outputResolution); + static int GetHeight(Models.OutputResolution outputResolution) => + OutputResolution.Get(outputResolution).Height; + + int TestStatic_GetWidth(Models.OutputResolution outputResolution) => + GetWidth(outputResolution); + static int GetWidth(Models.OutputResolution outputResolution) => + OutputResolution.Get(outputResolution).Width; + +} \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/Location.cs b/Shared/Models/Stateless/Methods/Location.cs index 3445c0a..46a05eb 100644 --- a/Shared/Models/Stateless/Methods/Location.cs +++ b/Shared/Models/Stateless/Methods/Location.cs @@ -3,37 +3,46 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class Location { - internal static void Check(int bottom, int left, int right, int top, int zCount) + internal static bool Check(int bottom, int left, int right, int top, int zCount, bool throwException) { + bool result = true; if (left < 0) - throw new Exception(); + result = false; if (right < 0) - throw new Exception(); + result = false; if (right < left) - throw new Exception(); + result = false; if (top < 0) - throw new Exception(); + result = false; if (bottom < 0) - throw new Exception(); + result = false; if (bottom < top) - throw new Exception(); + result = false; if (zCount < 0) + result = false; + if (throwException && !result) throw new Exception(); + return result; } - internal static void Check(int bottom, int height, int left, int right, int top, int width, int zCount) + internal static bool Check(int bottom, int height, int left, int right, int top, int width, int zCount, bool throwException) { + bool result = true; if (bottom > height) - throw new Exception(); + result = false; if (left > width) - throw new Exception(); + result = false; if (right > width) - throw new Exception(); + result = false; if (top > height) - throw new Exception(); + result = false; if (zCount < 0) + result = false; + if (result) + result = Check(bottom, left, right, top, zCount, throwException); + if (throwException && !result) throw new Exception(); - Check(bottom, left, right, top, zCount); + return result; } internal static string GetLeftPadded(int locationDigits, string value) @@ -48,54 +57,89 @@ internal abstract class Location return result; } - internal static int GetNormalizedPixelPercentage(int bottom, int height, int left, int locationDigits, int locationFactor, int right, int top, int width, int zCount) + internal static (decimal?, decimal?, decimal?, decimal?) GetHeightLeftTopWidth(int bottom, int height, int left, int right, int top, int width, int zCount) { - int result; - Check(bottom, height, left, right, top, width, zCount); - long check; - int checksum; + (decimal?, decimal?, decimal?, decimal?) result; + bool verified = Check(bottom, height, left, right, top, width, zCount, throwException: false); + decimal t = top; + decimal l = left; + decimal w = right - l; + decimal h = bottom - t; + decimal xHeightPercentageFactored = h / height; + decimal xLeftPercentageFactored = l / width; + decimal xTopPercentageFactored = t / height; + decimal xWidthPercentageFactored = w / width; + if (!verified) + result = new(null, null, null, null); + else + result = new(xHeightPercentageFactored, xLeftPercentageFactored, xTopPercentageFactored, xWidthPercentageFactored); + return result; + } + + internal static (int?, int?) GetCenterRoundedXY(int bottom, int height, int left, int locationFactor, int right, int top, int width, int zCount) + { + (int?, int?) result; + bool verified = Check(bottom, height, left, right, top, width, zCount, throwException: false); decimal center = 2m; - string yCenterPadded; decimal factor = locationFactor; - // int.MaxPercentage = 21 4748 3647; - int length = (locationDigits - 1) / 2; decimal xCenterValue = (left + right) / center; decimal yCenterValue = (top + bottom) / center; if (xCenterValue < left || xCenterValue > right) throw new Exception(); if (yCenterValue < top || yCenterValue > bottom) throw new Exception(); - if (xCenterValue > yCenterValue) - checksum = 1; - else - checksum = 2; decimal xCenterPercentageFactored = xCenterValue / width * factor; decimal yCenterPercentageFactored = yCenterValue / height * factor; int xCenterRounded = (int)Math.Round(xCenterPercentageFactored, 0); int yCenterRounded = (int)Math.Round(yCenterPercentageFactored, 0); - if (yCenterRounded != factor) - yCenterPadded = ILocation.GetLeftPadded(length, yCenterRounded); + if (!verified) + result = new(null, null); else - yCenterPadded = ILocation.GetLeftPadded(length, yCenterRounded - 1); - if (xCenterRounded != factor) - check = long.Parse(string.Concat(xCenterRounded, yCenterPadded, checksum)); - else - check = long.Parse(string.Concat(xCenterRounded - 1, yCenterPadded, checksum)); - if (check > int.MaxValue) - throw new Exception(); - result = (int)check; + result = new(xCenterRounded, yCenterRounded); return result; } - internal static (int?, int?) GetXY(int locationDigits, int locationFactor, int width, int height, string normalizedPixelPercentage) + internal static int GetNormalizedRectangle(int bottom, int height, int left, int locationDigits, int right, int top, int width, int zCount) + { + int result; + string check; + bool verified = Check(bottom, height, left, right, top, width, zCount, throwException: false); + int checksum = left > top ? 4 : 8; + if (!verified) + check = string.Concat(checksum, new string('0', locationDigits - 1)); + else + { + decimal factor = 100; + int factorMinusOne = (int)factor - 1; + // int.MaxPercentage = 21 47 48 36 47; + int length = (locationDigits - 1) / 4; + // Rectangle rectangle=new(x, y, width, h); + decimal x = left / (decimal)width * factor; + decimal y = top / (decimal)height * factor; + decimal w = (right - left) / (decimal)width * factor; + decimal h = (bottom - top) / (decimal)height * factor; + string xPadded = x < factor ? ILocation.GetLeftPadded(length, (int)x) : ILocation.GetLeftPadded(length, factorMinusOne); + string yPadded = y < factor ? ILocation.GetLeftPadded(length, (int)y) : ILocation.GetLeftPadded(length, factorMinusOne); + string widthPadded = w < factor ? ILocation.GetLeftPadded(length, (int)w) : ILocation.GetLeftPadded(length, factorMinusOne); + string heightPadded = h < factor ? ILocation.GetLeftPadded(length, (int)h) : ILocation.GetLeftPadded(length, factorMinusOne); + check = string.Concat(checksum, xPadded, yPadded, widthPadded, heightPadded); + } + long value = long.Parse(check); + if (value > int.MaxValue) + throw new Exception(); + result = (int)value; + return result; + } + + internal static (int?, int?) GetXY(int locationDigits, int locationFactor, int width, int height, string normalizedRectangle) { int? x; int? y; int center = 2; decimal factor = locationFactor; int each = (locationDigits - 1) / center; - string segmentA = normalizedPixelPercentage[..each]; - string segmentB = normalizedPixelPercentage[each..^1]; + string segmentA = normalizedRectangle[..each]; + string segmentB = normalizedRectangle[each..^1]; if (!int.TryParse(segmentA, out int xNormalized) || !int.TryParse(segmentB, out int yNormalized)) { x = null; diff --git a/Shared/Models/Stateless/Methods/Mapping.cs b/Shared/Models/Stateless/Methods/Mapping.cs index 9e91f35..b6fc7ef 100644 --- a/Shared/Models/Stateless/Methods/Mapping.cs +++ b/Shared/Models/Stateless/Methods/Mapping.cs @@ -9,69 +9,69 @@ internal abstract class Mapping string? id; string? extensionLowered; bool? needsFacesFileNameExtension; - string? normalizedPixelPercentage; + string? normalizedRectangle; if (segments.Length < 4 || $".{segments[3]}" != facesFileNameExtension) { id = null; extensionLowered = null; - normalizedPixelPercentage = null; + normalizedRectangle = null; needsFacesFileNameExtension = null; } else { id = segments[0]; extensionLowered = $".{segments[2]}"; - normalizedPixelPercentage = segments[1]; + normalizedRectangle = segments[1]; needsFacesFileNameExtension = segments.Length == 3; } - return new(id, normalizedPixelPercentage, extensionLowered, needsFacesFileNameExtension); + return new(id, normalizedRectangle, extensionLowered, needsFacesFileNameExtension); } - private static (int?, int?, List?) GetReversedDeterministicHashCodeKeysFromSegments(string facesFileNameExtension, bool idToMappingCollectionAny, Dictionary> idToMappingCollection, string fileName) + private static (int?, int?, List?) GetConvertedsFromSegments(string facesFileNameExtension, bool idToMappingCollectionAny, Dictionary> idToMappingCollection, string fileName) { int? id; - int? normalizedPixelPercentage; + int? normalizedRectangle; List? mappingCollection; - (string? Id, string? NormalizedPixelPercentage, string? ExtensionLowered, bool? Check) segments = GetSegments(facesFileNameExtension, fileName); - if (string.IsNullOrEmpty(segments.Id) || string.IsNullOrEmpty(segments.NormalizedPixelPercentage) || string.IsNullOrEmpty(segments.ExtensionLowered) || segments.Check is null) + (string? Id, string? NormalizedRectangle, string? ExtensionLowered, bool? Check) segments = GetSegments(facesFileNameExtension, fileName); + if (string.IsNullOrEmpty(segments.Id) || string.IsNullOrEmpty(segments.NormalizedRectangle) || string.IsNullOrEmpty(segments.ExtensionLowered) || segments.Check is null) { id = null; mappingCollection = null; - normalizedPixelPercentage = null; + normalizedRectangle = null; } - else if (!int.TryParse(segments.Id, out int idValue) || !int.TryParse(segments.NormalizedPixelPercentage, out int normalizedPixelPercentageValue)) + else if (!int.TryParse(segments.Id, out int idValue) || !int.TryParse(segments.NormalizedRectangle, out int normalizedRectangleValue)) { id = null; mappingCollection = null; - normalizedPixelPercentage = null; + normalizedRectangle = null; } else { id = idValue; - normalizedPixelPercentage = normalizedPixelPercentageValue; + normalizedRectangle = normalizedRectangleValue; if (!idToMappingCollectionAny || !idToMappingCollection.ContainsKey(idValue)) mappingCollection = null; else mappingCollection = idToMappingCollection[idValue]; } - return new(id, normalizedPixelPercentage, mappingCollection); + return new(id, normalizedRectangle, mappingCollection); } - internal static (int?, int?, List?) GetReversedDeterministicHashCodeKey(string facesFileNameExtension, bool idToMappingCollectionAny, Dictionary> idToMappingCollection, string file) + internal static (int?, int?, List?) GetConverted(string facesFileNameExtension, bool idToMappingCollectionAny, Dictionary> idToMappingCollection, string file) { int? id; - int? normalizedPixelPercentage; + int? normalizedRectangle; List? mappingCollection; string fileName = Path.GetFileName(file); - if (fileName.Length < 2 || fileName[1..].Contains('-')) + if (fileName.Length >= 2 && !fileName[1..].Contains('-')) + (id, normalizedRectangle, mappingCollection) = GetConvertedsFromSegments(facesFileNameExtension, idToMappingCollectionAny, idToMappingCollection, fileName); + else { id = null; mappingCollection = null; - normalizedPixelPercentage = null; + normalizedRectangle = null; } - else - (id, normalizedPixelPercentage, mappingCollection) = GetReversedDeterministicHashCodeKeysFromSegments(facesFileNameExtension, idToMappingCollectionAny, idToMappingCollection, fileName); - return new(id, normalizedPixelPercentage, mappingCollection); + return new(id, normalizedRectangle, mappingCollection); } internal static int GetAreaPermille(int faceAreaPermille, int bottom, int height, int left, int right, int top, int width) diff --git a/Shared/Models/Stateless/Methods/OutputResolution.cs b/Shared/Models/Stateless/Methods/OutputResolution.cs new file mode 100644 index 0000000..1c5d64a --- /dev/null +++ b/Shared/Models/Stateless/Methods/OutputResolution.cs @@ -0,0 +1,28 @@ +namespace View_by_Distance.Shared.Models.Stateless.Methods; + +internal abstract class OutputResolution +{ + + internal static (int Width, int Height) Get(Models.OutputResolution outputResolution) + { + // (int, int) result = outputResolution.Orientation switch // exif 274 + // { + // 0 => new(outputResolution.Width, outputResolution.Height), + // 1 => new(outputResolution.Width, outputResolution.Height), // 1 = Horizontal (normal) + // 2 => new(outputResolution.Width, outputResolution.Height), // 2 = Mirror horizontal + // 3 => new(outputResolution.Width, outputResolution.Height), // 3 = Rotate 180 + // 4 => new(outputResolution.Width, outputResolution.Height), // 4 = Mirror vertical + // 5 => new(outputResolution.Height, outputResolution.Width), // 5 = Mirror horizontal and rotate 270 CW + // 6 => new(outputResolution.Height, outputResolution.Width), // 6 = Rotate 90 CW + // 7 => new(outputResolution.Height, outputResolution.Width), // 7 = Mirror horizontal and rotate 90 CW + // 8 => new(outputResolution.Height, outputResolution.Width), // 8 = Rotate 270 CW + // _ => throw new Exception() + // }; + (int, int) result = outputResolution.Orientation switch // exif 274 + { + _ => new(outputResolution.Width, outputResolution.Height) + }; + return result; + } + +} \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/PersonContainer.cs b/Shared/Models/Stateless/Methods/PersonContainer.cs index 4218b44..2257602 100644 --- a/Shared/Models/Stateless/Methods/PersonContainer.cs +++ b/Shared/Models/Stateless/Methods/PersonContainer.cs @@ -9,13 +9,13 @@ internal abstract class PersonContainer int? id; string checkFile; string? checkDirectory; - int? normalizedPixelPercentage; + int? normalizedRectangle; foreach (string personDisplayDirectoryAllFile in results) { if (personDisplayDirectoryAllFile.EndsWith(".lnk")) continue; - (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(facesFileNameExtension, personDisplayDirectoryAllFile); - if (id is not null && normalizedPixelPercentage is not null && !personDisplayDirectoryAllFile.EndsWith(".json")) + (id, normalizedRectangle, _) = IMapping.GetConverted(facesFileNameExtension, personDisplayDirectoryAllFile); + if (id is not null && normalizedRectangle is not null && !personDisplayDirectoryAllFile.EndsWith(".json")) continue; checkDirectory = Path.GetDirectoryName(personDisplayDirectoryAllFile); if (string.IsNullOrEmpty(checkDirectory)) diff --git a/Shared/Models/Stateless/Methods/Property.cs b/Shared/Models/Stateless/Methods/Property.cs index a0a73a4..644b333 100644 --- a/Shared/Models/Stateless/Methods/Property.cs +++ b/Shared/Models/Stateless/Methods/Property.cs @@ -99,12 +99,18 @@ internal abstract class Property string format; string fullFormat; StringBuilder value = new(); + const string ticksExample = "##################"; string[][] dateFormats = new string[][] { new string[] { string.Empty, "yyyyMMdd_HHmmss", string.Empty }, + new string[] { string.Empty, "yyyyMMddHHmmssfff", string.Empty }, + new string[] { string.Empty, "yyyyMMdd_", ticksExample }, + new string[] { string.Empty, "yyyy-MM-dd_", ticksExample }, + new string[] { string.Empty, "yyyy-MM-dd.", ticksExample }, new string[] { string.Empty, "yyyy-MM-dd HH.mm.ss", string.Empty }, new string[] { string.Empty, "yyyyMMdd_HHmmss", "_LLS" }, new string[] { string.Empty, "yyyyMMdd_HHmmss", "_HDR" }, + new string[] { "WIN_", "yyyyMMdd_HH_mm_ss", "_Pro" }, new string[] { "IMG_", "yyyyMMdd_HHmmss", string.Empty }, new string[] { "IMG#####-", "yyyyMMdd-HHmm", string.Empty }, new string[] { "CameraZOOM-", "yyyyMMddHHmmss", string.Empty }, @@ -113,6 +119,8 @@ internal abstract class Property foreach (string[] dateFormat in dateFormats) { _ = value.Clear(); + if (dateFormat.Length != 3) + throw new Exception(); fullFormat = string.Join(string.Empty, dateFormat); if (fileHolder.NameWithoutExtension.Length != fullFormat.Length) continue; @@ -124,7 +132,10 @@ internal abstract class Property continue; if (DateTime.TryParseExact(value.ToString(), format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime checkDateTime)) { - result = checkDateTime; + if (fileHolder.NameWithoutExtension.Length < ticksExample.Length || !long.TryParse(fileHolder.NameWithoutExtension[^ticksExample.Length..], out long ticks)) + result = checkDateTime; + else + result = new DateTime(ticks); break; } } diff --git a/Shared/Models/Stateless/Methods/Sorting.cs b/Shared/Models/Stateless/Methods/Sorting.cs index 432ba2a..edece51 100644 --- a/Shared/Models/Stateless/Methods/Sorting.cs +++ b/Shared/Models/Stateless/Methods/Sorting.cs @@ -8,7 +8,7 @@ internal abstract class Sorting Models.Sorting result; if (faceDistanceLength.Length is null) throw new NotSupportedException(); - if (faceDistanceLength.NormalizedPixelPercentage is null) + if (faceDistanceLength.NormalizedRectangle is null) throw new NotSupportedException(); if (faceDistanceEncoding.MinimumDateTime is null || faceDistanceLength.MinimumDateTime is null) throw new NotSupportedException(); @@ -33,7 +33,7 @@ internal abstract class Sorting } } int withinRange = withinRanges.Max(); - result = new(daysDelta, distancePermyriad, faceDistanceLength.Id, faceDistanceLength.NormalizedPixelPercentage.Value, older, withinRange); + result = new(daysDelta, distancePermyriad, faceDistanceLength.Id, faceDistanceLength.NormalizedRectangle.Value, older, withinRange); return result; } diff --git a/Shared/View-by-Distance.Shared.csproj b/Shared/View-by-Distance.Shared.csproj index 50047bb..93f5579 100644 --- a/Shared/View-by-Distance.Shared.csproj +++ b/Shared/View-by-Distance.Shared.csproj @@ -34,7 +34,7 @@ - + \ No newline at end of file diff --git a/Tests/Models/Binder/Configuration.cs b/Tests/Models/Binder/Configuration.cs index 52c3a14..8acfc8e 100644 --- a/Tests/Models/Binder/Configuration.cs +++ b/Tests/Models/Binder/Configuration.cs @@ -186,7 +186,7 @@ public class Configuration configuration = configurationSection.Get(); } result = Get(configuration); - result.SetAndUpdate(propertyConfiguration, null, null, null, null); + result.SetAndUpdate(propertyConfiguration); return result; } diff --git a/Tests/Models/Configuration.cs b/Tests/Models/Configuration.cs index 99166f7..af5c742 100644 --- a/Tests/Models/Configuration.cs +++ b/Tests/Models/Configuration.cs @@ -142,10 +142,10 @@ public class Configuration return result; } - public void SetAndUpdate(Property.Models.Configuration configuration, int? numberOfJitters, int? numberOfTimesToUpsample, string? modelName, string? predictorModelName) + public void SetAndUpdate(Property.Models.Configuration configuration) { _PropertyConfiguration = configuration; - _PropertyConfiguration.Update(numberOfJitters, numberOfTimesToUpsample, modelName, predictorModelName); + _PropertyConfiguration.Update(); } } \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 5211145..dde36dc 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -33,8 +33,8 @@ - - + + diff --git a/Tests/UnitTestCalculations.cs b/Tests/UnitTestCalculations.cs index 4da7ba5..bbad3f3 100644 --- a/Tests/UnitTestCalculations.cs +++ b/Tests/UnitTestCalculations.cs @@ -12,7 +12,7 @@ using View_by_Distance.Tests.Models; namespace View_by_Distance.Tests; [TestClass] -public class UnitTestCalculations +public partial class UnitTestCalculations { private readonly ILogger _Logger; @@ -38,9 +38,11 @@ public class UnitTestCalculations isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() - .AddJsonFile(isEnvironment.AppSettingsFileName); + .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); configurationRoot = configurationBuilder.Build(); appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); @@ -240,229 +242,26 @@ public class UnitTestCalculations } [TestMethod] - public void TestGetPixelPercentageA() + public void TestNormalizedRectangle() { int? x, y; - int normalizedPixelPercentage; + int normalizedRectangle; int bottom, height, left, right, top, width; - string normalizedPixelPercentagePadded; - left = 7678; - right = 7680; - top = 4318; - bottom = 4320; - width = 7680; - height = 4320; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 999999981); - normalizedPixelPercentagePadded = ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - Assert.IsTrue(x.HasValue && x.Value == 7679); - Assert.IsTrue(y.HasValue && y.Value == 4319); - left = 7680; - right = 7680; - top = 4320; - bottom = 4320; - width = 7680; - height = 4320; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 999999991); - normalizedPixelPercentagePadded = ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - Assert.IsTrue(x.HasValue && x.Value == 7679); - Assert.IsTrue(y.HasValue && y.Value == 4320); - } - - [TestMethod] - public void TestGetPixelPercentageB() - { - int? x, y; - int normalizedPixelPercentage; - int bottom, height, left, right, top, width; - string normalizedPixelPercentagePadded; - left = 20; - right = 60; - top = 40; - bottom = 80; - width = 100; - height = 100; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 400060002); - normalizedPixelPercentagePadded = ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - Assert.IsTrue(x.HasValue && x.Value == 40); - Assert.IsTrue(y.HasValue && y.Value == 60); - left = 45; - right = 55; - top = 45; - bottom = 55; - width = 100; - height = 100; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 500050002); - normalizedPixelPercentagePadded = ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - Assert.IsTrue(x.HasValue && x.Value == 50); - Assert.IsTrue(y.HasValue && y.Value == 50); - } - - [TestMethod] - public void TestGetPixelPercentageC() - { - int? x, y; - int normalizedPixelPercentage; - string normalizedPixelPercentagePadded; - int bottom, height, left, right, top, width; - left = 1; - right = 3; - top = 1; - bottom = 3; - width = 100; - height = 100; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 20002002); - normalizedPixelPercentagePadded = ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - Assert.IsTrue(x.HasValue && x.Value == 2); - Assert.IsTrue(y.HasValue && y.Value == 2); - left = 50; - right = 60; - top = 50; - bottom = 60; - width = 100; - height = 100; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 550055002); - normalizedPixelPercentagePadded = ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - Assert.IsTrue(x.HasValue && x.Value == 55); - Assert.IsTrue(y.HasValue && y.Value == 55); - } - - [TestMethod] - public void TestGetPixelPercentageD() - { - int? x, y; - int normalizedPixelPercentage; - int bottom, height, left, right, top, width; - string normalizedPixelPercentagePadded; - left = 240; - right = 260; - top = 240; - bottom = 260; - width = 500; - height = 500; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 500050002); - normalizedPixelPercentagePadded = ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - Assert.IsTrue(x.HasValue && x.Value == 250); - Assert.IsTrue(y.HasValue && y.Value == 250); - left = 490; - right = 510; - top = 490; - bottom = 510; - width = 1000; - height = 1000; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 500050002); - normalizedPixelPercentagePadded = ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - Assert.IsTrue(x.HasValue && x.Value == 500); - Assert.IsTrue(y.HasValue && y.Value == 500); - left++; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 500550001); - normalizedPixelPercentagePadded = ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - Assert.IsTrue(x.HasValue && x.Value == 500); - Assert.IsTrue(y.HasValue && y.Value == 500); - left++; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 501050001); - normalizedPixelPercentagePadded = ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - Assert.IsTrue(x.HasValue && x.Value == 501); - Assert.IsTrue(y.HasValue && y.Value == 500); - } - - [TestMethod] - public void TestGetPixelPercentageE() - { - int? x, y; - int normalizedPixelPercentage; - int bottom, height, left, right, top, width; - string normalizedPixelPercentagePadded; - left = 1477; - right = 1477; - top = 641; - bottom = 641; - width = 2408; - height = 2077; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 613430861); - normalizedPixelPercentagePadded = ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - Assert.IsTrue(x.HasValue && x.Value == 1477); - Assert.IsTrue(y.HasValue && y.Value == 641); - } - - [TestMethod] - public void TestGetPixelPercentageF() - { - int? x, y; - int normalizedPixelPercentage; - int bottom, height, left, right, top, width; - string normalizedPixelPercentagePadded; + string normalizedRectanglePadded; width = 2048; height = 1365; - normalizedPixelPercentagePadded = "617214031"; - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); + normalizedRectanglePadded = "617214031"; + (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedRectanglePadded); if (x is null || y is null) throw new Exception(); Assert.IsTrue(x.Value == 1264); Assert.IsTrue(y.Value == 192); left = x.Value; - right = x.Value; + right = x.Value + 125; top = y.Value; - bottom = y.Value; - normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); - Assert.IsTrue(normalizedPixelPercentage == 617214071); - double x1, x2, y1, y2; - x1 = x.Value; - x2 = x.Value; - y1 = y.Value; - y2 = y.Value - 3; - double distance = Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2)); - Assert.IsTrue(distance == 3); - } - - [TestMethod] - public void TestGetPixelPercentageG() - { - int? x, y; - double x1, x2, y1, y2; - int height, width; - string normalizedPixelPercentagePadded; - width = 4608; - height = 3072; - normalizedPixelPercentagePadded = "683152331"; - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - if (x is null || y is null) - throw new Exception(); - Assert.IsTrue(x.Value == 3148); - Assert.IsTrue(y.Value == 1608); - x1 = x.Value; - y1 = y.Value; - normalizedPixelPercentagePadded = "234431671"; - (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); - if (x is null || y is null) - throw new Exception(); - Assert.IsTrue(x.Value == 1080); - Assert.IsTrue(y.Value == 973); - x2 = x.Value; - y2 = y.Value; - double distance = Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2)); - Assert.IsTrue(distance == 2163.2958651095323); + bottom = y.Value + 100; + normalizedRectangle = ILocation.GetNormalizedRectangle(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, right, top, width); + Assert.IsTrue(normalizedRectangle == 461140607); } [TestMethod] diff --git a/Tests/UnitTestExample.cs b/Tests/UnitTestExample.cs index ca752f0..b678aa7 100644 --- a/Tests/UnitTestExample.cs +++ b/Tests/UnitTestExample.cs @@ -36,9 +36,11 @@ public class UnitTestExample isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() - .AddJsonFile(isEnvironment.AppSettingsFileName); + .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); configurationRoot = configurationBuilder.Build(); appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); diff --git a/Tests/UnitTestIsEnvironment.cs b/Tests/UnitTestIsEnvironment.cs index da8f3e2..060c367 100644 --- a/Tests/UnitTestIsEnvironment.cs +++ b/Tests/UnitTestIsEnvironment.cs @@ -32,6 +32,8 @@ public class UnitTestIsEnvironment .AddJsonFile("appsettings.Development.json"); configurationRoot = configurationBuilder.Build(); appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); diff --git a/Tests/UnitTestResize.cs b/Tests/UnitTestResize.cs index 81fb848..d778153 100644 --- a/Tests/UnitTestResize.cs +++ b/Tests/UnitTestResize.cs @@ -40,9 +40,11 @@ public class UnitTestResize isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() - .AddJsonFile(isEnvironment.AppSettingsFileName); + .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); configurationRoot = configurationBuilder.Build(); appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); @@ -126,14 +128,14 @@ public class UnitTestResize (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(_Configuration.OutputExtension, _Configuration.OutputQuality); C_Resize resize = new(_Configuration.ForceResizeLastWriteTimeToCreationTime, _Configuration.OverrideForResizeImages, _Configuration.PropertiesChangedForResize, _Configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension); _ = resize.ToString(); - string sourceDirectoryFile = ".json"; + FileHolder sourceDirectoryFileHolder = new(".json"); FileHolder fileHolder = new(Path.Combine(sourceDirectory, sourceFileName)); string relativePath = IPath.GetRelativePath(fileHolder.FullName, length); sourceDirectory = Path.Combine(aPropertySingletonDirectory, sourceDirectoryName); propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory); resize.SetAngleBracketCollection(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, sourceDirectory); metadata.SetAngleBracketCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, sourceDirectory); - item = new(sourceDirectoryFile, relativePath, fileHolder, isValidImageFormatExtension, property, false, false, false); + item = new(sourceDirectoryFileHolder, relativePath, fileHolder, isValidImageFormatExtension, property, false, false, false); Assert.IsNotNull(item.ImageFileHolder); if (item.Property is null) { diff --git a/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs b/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs index 2c03aab..d3acd6e 100644 --- a/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs +++ b/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs @@ -60,7 +60,7 @@ public class Configuration [Display(Name = "Face Area Permille Tolerance"), Required] public int[] RangeFaceAreaPermilleTolerance { get; set; } [Display(Name = "Location Minimum Confidence"), Required] public double[] RangeFaceConfidence { get; set; } [Display(Name = "Face Distance Tolerance"), Required] public double[] RangeDistanceTolerance { get; set; } - [Display(Name = "Retry Images Without a Face"), Required] public bool? RetryImagesWithoutAFace { get; set; } + [Display(Name = "Retry Images Without a Face"), Required] public bool? RetryImagesWithoutAFaceLocation { get; set; } [Display(Name = "Reverse"), Required] public bool? Reverse { get; set; } [Display(Name = "Save Face Landmark For Output Resolutions"), Required] public string[] SaveFaceLandmarkForOutputResolutions { get; set; } [Display(Name = "Save Full Year Of Random Files"), Required] public bool? SaveFullYearOfRandomFiles { get; set; } @@ -171,8 +171,8 @@ public class Configuration throw new NullReferenceException(nameof(configuration.RangeFaceConfidence)); if (configuration.RangeDistanceTolerance is null || configuration.RangeDistanceTolerance.Length != 3) throw new NullReferenceException(nameof(configuration.RangeDistanceTolerance)); - if (configuration.RetryImagesWithoutAFace is null) - throw new NullReferenceException(nameof(configuration.RetryImagesWithoutAFace)); + if (configuration.RetryImagesWithoutAFaceLocation is null) + throw new NullReferenceException(nameof(configuration.RetryImagesWithoutAFaceLocation)); if (configuration.Reverse is null) throw new NullReferenceException(nameof(configuration.Reverse)); configuration.SaveFaceLandmarkForOutputResolutions ??= Array.Empty(); @@ -245,7 +245,7 @@ public class Configuration configuration.RangeFaceAreaPermilleTolerance, configuration.RangeFaceConfidence, configuration.RangeDistanceTolerance, - configuration.RetryImagesWithoutAFace.Value, + configuration.RetryImagesWithoutAFaceLocation.Value, configuration.Reverse.Value, configuration.SaveFaceLandmarkForOutputResolutions, configuration.SaveFullYearOfRandomFiles.Value, @@ -275,7 +275,7 @@ public class Configuration configuration = configurationSection.Get(); } result = Get(configuration); - result.SetAndUpdate(propertyConfiguration, null, null, null, null); + result.SetAndUpdate(propertyConfiguration, configuration?.NumberOfJitters, configuration?.NumberOfTimesToUpsample, configuration?.ModelName, configuration?.PredictorModelName); return result; } diff --git a/TestsWithFaceRecognitionDotNet/Models/Configuration.cs b/TestsWithFaceRecognitionDotNet/Models/Configuration.cs index 50ab873..52163d8 100644 --- a/TestsWithFaceRecognitionDotNet/Models/Configuration.cs +++ b/TestsWithFaceRecognitionDotNet/Models/Configuration.cs @@ -58,7 +58,7 @@ public class Configuration public int[] RangeFaceAreaPermilleTolerance { init; get; } public double[] RangeFaceConfidence { init; get; } public double[] RangeDistanceTolerance { init; get; } - public bool RetryImagesWithoutAFace { init; get; } + public bool RetryImagesWithoutAFaceLocation { init; get; } public bool Reverse { init; get; } public string[] SaveFaceLandmarkForOutputResolutions { init; get; } public bool SaveFullYearOfRandomFiles { init; get; } @@ -123,7 +123,7 @@ public class Configuration int[] rangeFaceAreaPermilleTolerance, double[] rangeFaceConfidence, double[] rangeDistanceTolerance, - bool retryImagesWithoutAFace, + bool retryImagesWithoutAFaceLocation, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, @@ -187,7 +187,7 @@ public class Configuration RangeFaceAreaPermilleTolerance = rangeFaceAreaPermilleTolerance; RangeFaceConfidence = rangeFaceConfidence; RangeDistanceTolerance = rangeDistanceTolerance; - RetryImagesWithoutAFace = retryImagesWithoutAFace; + RetryImagesWithoutAFaceLocation = retryImagesWithoutAFaceLocation; Reverse = reverse; SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions; SaveFullYearOfRandomFiles = saveFullYearOfRandomFiles; diff --git a/TestsWithFaceRecognitionDotNet/TestsWithFaceRecognitionDotNet.csproj b/TestsWithFaceRecognitionDotNet/TestsWithFaceRecognitionDotNet.csproj index bda122a..5279226 100644 --- a/TestsWithFaceRecognitionDotNet/TestsWithFaceRecognitionDotNet.csproj +++ b/TestsWithFaceRecognitionDotNet/TestsWithFaceRecognitionDotNet.csproj @@ -32,8 +32,8 @@ - - + + diff --git a/TestsWithFaceRecognitionDotNet/UnitTestExample.cs b/TestsWithFaceRecognitionDotNet/UnitTestExample.cs index ca752f0..b678aa7 100644 --- a/TestsWithFaceRecognitionDotNet/UnitTestExample.cs +++ b/TestsWithFaceRecognitionDotNet/UnitTestExample.cs @@ -36,9 +36,11 @@ public class UnitTestExample isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() - .AddJsonFile(isEnvironment.AppSettingsFileName); + .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); configurationRoot = configurationBuilder.Build(); appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); diff --git a/TestsWithFaceRecognitionDotNet/UnitTestFace.cs b/TestsWithFaceRecognitionDotNet/UnitTestFace.cs index d6689e6..016ed16 100644 --- a/TestsWithFaceRecognitionDotNet/UnitTestFace.cs +++ b/TestsWithFaceRecognitionDotNet/UnitTestFace.cs @@ -42,9 +42,11 @@ public class UnitTestFace isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() - .AddJsonFile(isEnvironment.AppSettingsFileName); + .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); configurationRoot = configurationBuilder.Build(); appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); @@ -167,8 +169,10 @@ public class UnitTestFace // string sourceDirectoryName = "Disneyland 2014"; // string sourceFileName = "Logan Michael Sept 08 (193).jpg"; // string sourceDirectoryName = "=2008.2 Summer Logan Michael"; - string sourceFileName = "Halloween 2006 (112).jpg"; - string sourceDirectoryName = "Halloween 2006"; + // string sourceFileName = "Halloween 2006 (112).jpg"; + // string sourceDirectoryName = "Halloween 2006"; + string sourceFileName = "1384160978.jpg"; + string sourceDirectoryName = "zzz Portrait Innovations Files 2007"; Item item; bool reverse = false; string original = "Original"; @@ -199,14 +203,14 @@ public class UnitTestFace (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(_Configuration.OutputExtension, _Configuration.OutputQuality); C_Resize resize = new(_Configuration.ForceResizeLastWriteTimeToCreationTime, _Configuration.OverrideForResizeImages, _Configuration.PropertiesChangedForResize, _Configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension); _ = resize.ToString(); - string sourceDirectoryFile = ".json"; + FileHolder sourceDirectoryFileHolder = new(".json"); FileHolder fileHolder = new(Path.Combine(sourceDirectory, sourceFileName)); string relativePath = IPath.GetRelativePath(fileHolder.FullName, length); sourceDirectory = Path.Combine(aPropertySingletonDirectory, sourceDirectoryName); propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory); resize.SetAngleBracketCollection(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, sourceDirectory); metadata.SetAngleBracketCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, sourceDirectory); - item = new(sourceDirectoryFile, relativePath, fileHolder, isValidImageFormatExtension, property, false, false, false); + item = new(sourceDirectoryFileHolder, relativePath, fileHolder, isValidImageFormatExtension, property, false, false, false); Assert.IsNotNull(item.ImageFileHolder); if (item.Property is null) { @@ -225,7 +229,7 @@ public class UnitTestFace Image image = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName); Assert.IsNotNull(image); (Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(_Configuration); - FaceRecognition faceRecognition = new(_Configuration.NumberOfTimesToUpsample, _Configuration.NumberOfJitters, predictorModel, model, modelParameter); + FaceRecognition faceRecognition = new(_Configuration.NumberOfJitters, _Configuration.NumberOfTimesToUpsample, model, modelParameter, predictorModel); List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary? FaceParts)> collection; collection = faceRecognition.GetCollection(image, includeFaceEncoding: true, includeFaceParts: true); Assert.IsTrue(collection.Count == 2); diff --git a/View-by-Distance-MKLink-Console.sln b/View-by-Distance-MKLink-Console.sln index 8a93968..4eb53a2 100644 --- a/View-by-Distance-MKLink-Console.sln +++ b/View-by-Distance-MKLink-Console.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.30114.105 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "View-by-Distance.Shared", "shared\View-by-Distance.Shared.csproj", "{1D231660-33B4-4763-9C9F-C6ACC8BA600D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compare", "Compare\Compare.csproj", "{372BFEDC-8E9C-4DDE-AD8D-66D9CE0670E1}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Date-Group", "Date-Group\Date-Group.csproj", "{DFEDB5F9-AFFC-40A2-9FEC-9B84C83B63D9}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metadata", "Metadata\Metadata.csproj", "{961D11A0-44C8-48CD-BEEE-A6E6903AE58F}" @@ -39,6 +37,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FaceParts", "FaceParts\Face EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drag-Drop", "Drag-Drop\Drag-Drop.csproj", "{87EB76BC-32A9-4FD0-922A-BD7E9B6E7D8B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicate-Search", "Duplicate-Search\Duplicate-Search.csproj", "{48E87D9B-B802-467A-BDC7-E86F7FD01D5C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Delete-By-Relative", "Delete-By-Relative\Delete-By-Relative.csproj", "{9DFCA595-80AA-4E78-A9AF-5B4AB4D737C4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -52,10 +54,6 @@ Global {1D231660-33B4-4763-9C9F-C6ACC8BA600D}.Debug|Any CPU.Build.0 = Debug|Any CPU {1D231660-33B4-4763-9C9F-C6ACC8BA600D}.Release|Any CPU.ActiveCfg = Release|Any CPU {1D231660-33B4-4763-9C9F-C6ACC8BA600D}.Release|Any CPU.Build.0 = Release|Any CPU - {372BFEDC-8E9C-4DDE-AD8D-66D9CE0670E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {372BFEDC-8E9C-4DDE-AD8D-66D9CE0670E1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {372BFEDC-8E9C-4DDE-AD8D-66D9CE0670E1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {372BFEDC-8E9C-4DDE-AD8D-66D9CE0670E1}.Release|Any CPU.Build.0 = Release|Any CPU {DFEDB5F9-AFFC-40A2-9FEC-9B84C83B63D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DFEDB5F9-AFFC-40A2-9FEC-9B84C83B63D9}.Debug|Any CPU.Build.0 = Debug|Any CPU {DFEDB5F9-AFFC-40A2-9FEC-9B84C83B63D9}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -120,5 +118,13 @@ Global {87EB76BC-32A9-4FD0-922A-BD7E9B6E7D8B}.Debug|Any CPU.Build.0 = Debug|Any CPU {87EB76BC-32A9-4FD0-922A-BD7E9B6E7D8B}.Release|Any CPU.ActiveCfg = Release|Any CPU {87EB76BC-32A9-4FD0-922A-BD7E9B6E7D8B}.Release|Any CPU.Build.0 = Release|Any CPU + {48E87D9B-B802-467A-BDC7-E86F7FD01D5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48E87D9B-B802-467A-BDC7-E86F7FD01D5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48E87D9B-B802-467A-BDC7-E86F7FD01D5C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48E87D9B-B802-467A-BDC7-E86F7FD01D5C}.Release|Any CPU.Build.0 = Release|Any CPU + {9DFCA595-80AA-4E78-A9AF-5B4AB4D737C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DFCA595-80AA-4E78-A9AF-5B4AB4D737C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DFCA595-80AA-4E78-A9AF-5B4AB4D737C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DFCA595-80AA-4E78-A9AF-5B4AB4D737C4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal