diff --git a/.vscode/launch.json b/.vscode/launch.json
index 3558e0d..adca1e6 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -125,6 +125,23 @@
"stopAtEntry": false,
"requireExactSource": false
},
+ {
+ "name": "Drag-Drop-Move",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build",
+ "program": "${workspaceFolder}/Drag-Drop-Move/bin/Debug/net7.0-windows/win-x64/Drag-Drop-Move.dll",
+ "args": [
+ "s"
+ ],
+ "env": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "cwd": "${workspaceFolder}",
+ "console": "integratedTerminal",
+ "stopAtEntry": false,
+ "requireExactSource": false
+ },
{
"name": "Instance",
"type": "coreclr",
diff --git a/Drag-Drop-Move/.vscode/launch.json b/Drag-Drop-Move/.vscode/launch.json
new file mode 100644
index 0000000..de44254
--- /dev/null
+++ b/Drag-Drop-Move/.vscode/launch.json
@@ -0,0 +1,26 @@
+{
+ "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/net7.0-windows/win-x64/Drag-Drop-Explorer.dll",
+ "args": [],
+ "cwd": "${workspaceFolder}",
+ // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
+ "console": "internalConsole",
+ "stopAtEntry": false
+ },
+ {
+ "name": ".NET Core Attach",
+ "type": "coreclr",
+ "request": "attach"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Drag-Drop-Move/.vscode/tasks.json b/Drag-Drop-Move/.vscode/tasks.json
new file mode 100644
index 0000000..570fdd9
--- /dev/null
+++ b/Drag-Drop-Move/.vscode/tasks.json
@@ -0,0 +1,41 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/Drag-Drop-Explorer.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "${workspaceFolder}/Drag-Drop-Explorer.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run",
+ "--project",
+ "${workspaceFolder}/Drag-Drop-Explorer.csproj"
+ ],
+ "problemMatcher": "$msCompile"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Drag-Drop-Move/Drag-Drop-Move.csproj b/Drag-Drop-Move/Drag-Drop-Move.csproj
new file mode 100644
index 0000000..3737d46
--- /dev/null
+++ b/Drag-Drop-Move/Drag-Drop-Move.csproj
@@ -0,0 +1,50 @@
+
+
+ enable
+ 10.0
+ enable
+ WinExe
+ win-x64
+ net7.0-windows
+ true
+
+
+ true
+ true
+ true
+
+
+ Windows
+
+
+ OSX
+
+
+ Linux
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+ Always
+
+
+
\ No newline at end of file
diff --git a/Drag-Drop-Move/DragDropMove.Designer.cs b/Drag-Drop-Move/DragDropMove.Designer.cs
new file mode 100644
index 0000000..e272c77
--- /dev/null
+++ b/Drag-Drop-Move/DragDropMove.Designer.cs
@@ -0,0 +1,39 @@
+namespace View_by_Distance.Drag_Drop_Explorer;
+
+partial class DragDropMove
+{
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(640, 100);
+ this.StartPosition = FormStartPosition.CenterScreen;
+ this.Text = "Drag Drop Explorer";
+ }
+
+ #endregion
+}
diff --git a/Drag-Drop-Move/DragDropMove.cs b/Drag-Drop-Move/DragDropMove.cs
new file mode 100644
index 0000000..c406f06
--- /dev/null
+++ b/Drag-Drop-Move/DragDropMove.cs
@@ -0,0 +1,195 @@
+using Microsoft.Extensions.Configuration;
+using Phares.Shared;
+using Serilog;
+using System.Diagnostics;
+using System.Reflection;
+using System.Text.Json;
+using View_by_Distance.Drag_Drop_Explorer.Models;
+using View_by_Distance.Shared.Models.Stateless.Methods;
+using WindowsShortcutFactory;
+
+namespace View_by_Distance.Drag_Drop_Explorer;
+
+public partial class DragDropMove : Form
+{
+
+ private readonly ILogger _Logger;
+ private readonly TextBox _PathTextBox;
+ private readonly TextBox _JsonTextBox;
+ private readonly TextBox _FirstTextBox;
+ private readonly AppSettings _AppSettings;
+ private readonly ProgressBar _ProgressBar;
+ private readonly string _WorkingDirectory;
+ private readonly IsEnvironment _IsEnvironment;
+
+ public DragDropMove()
+ {
+ InitializeComponent();
+ ILogger logger;
+ AppSettings appSettings;
+ string workingDirectory;
+ IsEnvironment isEnvironment;
+ IConfigurationRoot configurationRoot;
+ LoggerConfiguration loggerConfiguration = new();
+ Assembly assembly = Assembly.GetExecutingAssembly();
+ bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug");
+ 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);
+ configurationRoot = configurationBuilder.Build();
+ appSettings = Models.Binder.AppSettings.Get(configurationRoot);
+ if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
+ throw new Exception("Working path name must have parentDirectory value!");
+ workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
+ Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
+ _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
+ Log.Logger = loggerConfiguration.CreateLogger();
+ logger = Log.ForContext();
+ logger.Information("Complete");
+ _Logger = logger;
+ _AppSettings = appSettings;
+ _IsEnvironment = isEnvironment;
+ _WorkingDirectory = workingDirectory;
+ _ProgressBar = new() { TabIndex = 4, Location = new(5, 5), Dock = DockStyle.Top, Visible = false };
+ string json = JsonSerializer.Serialize(_AppSettings, new JsonSerializerOptions { WriteIndented = true });
+ _FirstTextBox = new() { TabIndex = 1, Text = _IsEnvironment.Profile, Location = new(5, 5), Dock = DockStyle.Top };
+ _PathTextBox = new() { TabIndex = 2, Text = _AppSettings.WorkingDirectoryName, Location = new(5, 5), Dock = DockStyle.Top };
+ _JsonTextBox = new() { TabIndex = 3, Text = json, Multiline = true, MinimumSize = new(1, 80), Location = new(5, 5), Dock = DockStyle.Top };
+ Load += new EventHandler(Form1_Load);
+ Controls.Add(_ProgressBar);
+ Controls.Add(_JsonTextBox);
+ Controls.Add(_PathTextBox);
+ Controls.Add(_FirstTextBox);
+ }
+
+ void Form1_Load(object? sender, EventArgs e)
+ {
+ try
+ {
+ AllowDrop = true;
+ DragDrop += new DragEventHandler(Form1_DragDrop);
+ DragEnter += new DragEventHandler(Form1_DragEnter);
+ _FirstTextBox.LostFocus += new EventHandler(TextBox_LostFocus);
+ _PathTextBox.LostFocus += new EventHandler(TextBox_LostFocus);
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+
+ private static string GetConverted(string value)
+ {
+ string result = value.Length < 2 || value[1] != ':' ? value : value.Replace("\\\\", "/").Replace('\\', '/');
+ return result;
+ }
+
+ void TextBox_LostFocus(object? sender, EventArgs e)
+ {
+ try
+ {
+ if (sender is TextBox textBox)
+ {
+ textBox.Text = GetConverted(textBox.Text);
+ if (textBox.Text == "ps")
+ throw new NotImplementedException();
+
+ }
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+
+ void Form1_DragEnter(object? sender, DragEventArgs e)
+ {
+ try
+ {
+ if (e.Data is not null && e.Data.GetDataPresent(DataFormats.FileDrop))
+ e.Effect = DragDropEffects.Copy;
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+
+ private void MovePaths(string[] paths)
+ {
+ string file;
+ string checkFile;
+ string? directory;
+ string? relativePath;
+ string[] directories;
+ string? checkDirectory;
+ string? shellDirectory;
+ int rootDirectoryLength;
+ WindowsShortcut windowsShortcut;
+ _PathTextBox.Text = string.Empty;
+ _FirstTextBox.Text = GetConverted(paths[0]);
+ foreach (string path in paths.OrderBy(l => l))
+ {
+ relativePath = null;
+ shellDirectory = null;
+ if (!path.EndsWith(".lnk"))
+ file = path;
+ else
+ {
+ windowsShortcut = WindowsShortcut.Load(path);
+ if (windowsShortcut.Path is null)
+ continue;
+ file = windowsShortcut.Path;
+ windowsShortcut.Dispose();
+ }
+ directory = Path.GetDirectoryName(file);
+ if (string.IsNullOrEmpty(directory))
+ continue;
+ directories = IPath.GetDirectories(directory);
+ foreach (string directoryName in directories)
+ {
+ checkDirectory = $"{directoryName}-Shell";
+ if (!Directory.Exists(checkDirectory))
+ continue;
+ shellDirectory = checkDirectory;
+ rootDirectoryLength = directoryName.Length;
+ relativePath = file[rootDirectoryLength..];
+ break;
+ }
+ if (string.IsNullOrEmpty(shellDirectory) || string.IsNullOrEmpty(relativePath))
+ continue;
+ checkFile = string.Concat(shellDirectory, relativePath);
+ checkDirectory = Path.GetDirectoryName(checkFile);
+ if (string.IsNullOrEmpty(checkDirectory))
+ continue;
+ if (!Directory.Exists(checkDirectory))
+ _ = Directory.CreateDirectory(checkDirectory);
+ if (File.Exists(checkFile))
+ continue;
+ File.Move(file, checkFile);
+ }
+ }
+
+ void Form1_DragDrop(object? sender, DragEventArgs e)
+ {
+ try
+ {
+ if (e.Data is not null && e.Data.GetData(DataFormats.FileDrop) is string[] paths && paths.Any())
+ MovePaths(paths);
+ else
+ {
+ _FirstTextBox.Text = string.Empty;
+ _PathTextBox.Text = string.Empty;
+ _JsonTextBox.Text = string.Empty;
+ _Logger.Information("No data");
+ }
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Drag-Drop-Move/Models/AppSettings.cs b/Drag-Drop-Move/Models/AppSettings.cs
new file mode 100644
index 0000000..e7114a7
--- /dev/null
+++ b/Drag-Drop-Move/Models/AppSettings.cs
@@ -0,0 +1,27 @@
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace View_by_Distance.Drag_Drop_Explorer.Models;
+
+public class AppSettings
+{
+
+ public string Company { init; get; }
+ public int MaxDegreeOfParallelism { init; get; }
+ public string WorkingDirectoryName { init; get; }
+
+ [JsonConstructor]
+ public AppSettings(string company, int maxDegreeOfParallelism, string workingDirectoryName)
+ {
+ Company = company;
+ MaxDegreeOfParallelism = maxDegreeOfParallelism;
+ 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/Drag-Drop-Move/Models/Binder/AppSettings.cs b/Drag-Drop-Move/Models/Binder/AppSettings.cs
new file mode 100644
index 0000000..3f35cb0
--- /dev/null
+++ b/Drag-Drop-Move/Models/Binder/AppSettings.cs
@@ -0,0 +1,44 @@
+using Microsoft.Extensions.Configuration;
+using System.Text.Json;
+
+namespace View_by_Distance.Drag_Drop_Explorer.Models.Binder;
+
+public class AppSettings
+{
+
+#nullable disable
+
+ public string Company { get; set; }
+ public int? MaxDegreeOfParallelism { 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.MaxDegreeOfParallelism.Value,
+ appSettings.WorkingDirectoryName
+ );
+ return result;
+ }
+
+ public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
+ {
+ Models.AppSettings result;
+ AppSettings? appSettings = configurationRoot.Get();
+ result = Get(appSettings);
+ return result;
+ }
+
+}
\ No newline at end of file
diff --git a/Drag-Drop-Move/Program.cs b/Drag-Drop-Move/Program.cs
new file mode 100644
index 0000000..a50a30d
--- /dev/null
+++ b/Drag-Drop-Move/Program.cs
@@ -0,0 +1,15 @@
+namespace View_by_Distance.Drag_Drop_Explorer;
+
+static class Program
+{
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ ApplicationConfiguration.Initialize();
+ Application.Run(new DragDropMove());
+ }
+
+}
\ No newline at end of file
diff --git a/Drag-Drop-Move/appsettings.Development.json b/Drag-Drop-Move/appsettings.Development.json
new file mode 100644
index 0000000..be482be
--- /dev/null
+++ b/Drag-Drop-Move/appsettings.Development.json
@@ -0,0 +1,11 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Log4netProvider": "Debug"
+ }
+ },
+ "MaxDegreeOfParallelism": 6,
+ "Serilog": {
+ "MinimumLevel": "Debug"
+ }
+}
\ No newline at end of file
diff --git a/Drag-Drop-Move/appsettings.json b/Drag-Drop-Move/appsettings.json
new file mode 100644
index 0000000..4be1117
--- /dev/null
+++ b/Drag-Drop-Move/appsettings.json
@@ -0,0 +1,50 @@
+{
+ "Company": "Mike Phares",
+ "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"
+}
\ No newline at end of file
diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs
index b230b1f..45d5aa9 100644
--- a/Instance/DlibDotNet.cs
+++ b/Instance/DlibDotNet.cs
@@ -271,26 +271,18 @@ public partial class DlibDotNet
return result;
}
- private void SetMapping(ReadOnlyDictionary>> idToLocationContainers, MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem, List? mappingFromPhotoPrismCollection, List faces)
+ private bool? GetIsFocusModel(ReadOnlyDictionary>> idToLocationContainers, MappingFromItem mappingFromItem)
{
+ bool? result;
string? model;
- Mapping mapping;
- bool? isFocusModel;
- int faceAreaPermyriad;
- int confidencePercent;
- bool? inSkipCollection;
- int normalizedRectangle;
- string deterministicHashCodeKey;
- MappingFromFilter mappingFromFilter;
- MappingFromLocation? mappingFromLocation;
- IReadOnlyList directories;
List>? locationContainers;
+ IReadOnlyList directories;
if (string.IsNullOrEmpty(_Configuration.FocusModel))
- isFocusModel = null;
+ result = null;
else
{
if (!idToLocationContainers.TryGetValue(mappingFromItem.Id, out locationContainers) || !locationContainers.Any())
- isFocusModel = false;
+ result = false;
else
{
directories = locationContainers.First().Directories;
@@ -298,11 +290,25 @@ public partial class DlibDotNet
if (model is null)
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mappingFromItem.ResizedFileHolder.FullName);
model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(directories);
- isFocusModel = model is not null && model.Contains(_Configuration.FocusModel);
- if (isFocusModel.Value)
- isFocusModel = true;
+ result = model is not null && model.Contains(_Configuration.FocusModel);
+ if (result.Value)
+ result = true;
}
}
+ return result;
+ }
+
+ private void SetMapping(ReadOnlyDictionary>> idToLocationContainers, MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem, List? mappingFromPhotoPrismCollection, List faces)
+ {
+ Mapping mapping;
+ int faceAreaPermyriad;
+ int confidencePercent;
+ bool? inSkipCollection;
+ int normalizedRectangle;
+ string deterministicHashCodeKey;
+ MappingFromFilter mappingFromFilter;
+ MappingFromLocation? mappingFromLocation;
+ bool? isFocusModel = GetIsFocusModel(idToLocationContainers, mappingFromItem);
foreach (Shared.Models.Face face in faces)
{
if (item.Property?.Id is null || face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
@@ -327,6 +333,35 @@ public partial class DlibDotNet
}
}
+ private Mapping GetMapping(ReadOnlyDictionary>> idToLocationContainers, MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem)
+ {
+ Mapping result;
+ bool? inSkipCollection;
+ int normalizedRectangle;
+ int faceAreaPermyriad = 0;
+ int confidencePercent = 0;
+ string deterministicHashCodeKey;
+ MappingFromFilter mappingFromFilter;
+ MappingFromLocation? mappingFromLocation;
+ bool? isFocusModel = GetIsFocusModel(idToLocationContainers, mappingFromItem);
+ if (item.Property?.Id is null)
+ {
+ inSkipCollection = null;
+ mappingFromLocation = null;
+ mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection);
+ }
+ else
+ {
+ normalizedRectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(Shared.Models.Stateless.ILocation.Digits);
+ deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, Shared.Models.Stateless.ILocation.Digits);
+ mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, normalizedRectangle);
+ inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation);
+ mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection);
+ }
+ result = new(mappingFromItem, mappingFromFilter, mappingFromLocation, mappingFromPhotoPrismCollection: null);
+ return result;
+ }
+
private void FullParallelForWork(A_Property propertyLogic,
B_Metadata metadata,
ReadOnlyDictionary>> idToLocationContainers,
@@ -677,61 +712,6 @@ public partial class DlibDotNet
}
}
- private List GetFilteredDistinct(string argZero, Container[] containers)
- {
- List results = new();
- Item[] filteredItems;
- List distinct = 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;
- foreach (Item item in filteredItems)
- {
- if (item.Property?.Id is null || item.ResizedFileHolder is null)
- continue;
- if (distinct.Contains(item.Property.Id.Value))
- continue;
- distinct.Add(item.Property.Id.Value);
- foreach (Shared.Models.Face face in item.Faces)
- {
- if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
- continue;
- results.Add(face);
- }
- }
- }
- return results;
- }
-
- private List- GetItems(string argZero, Container[] containers)
- {
- List
- items = new();
- Item[] filteredItems;
- 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;
- foreach (Item item in filteredItems)
- {
- if (item.Property?.Id is null || item.ResizedFileHolder is null)
- continue;
- items.Add(item);
- }
- }
- return items;
- }
-
private void SaveFaceDistances(long ticks, MapLogic mapLogic, Mapping[] mappingCollection, string dFacesContentDirectory, string d2FacePartsContentDirectory, string d2FacePartsContentCollectionDirectory, Dictionary> idToNormalizedRectangleToMapping, List faceDistanceEncodings, FaceDistanceContainer[] faceDistanceContainers)
{
if (_Log is null)
@@ -785,36 +765,33 @@ public partial class DlibDotNet
SaveFaceDistances(ticks, mapLogic, mappingCollection, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, idToNormalizedRectangleToMapping, faceDistanceEncodings, faceDistanceContainers);
}
- private void MapLogic(string argZero, long ticks, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string fPhotoPrismContentDirectory, MapLogic mapLogic, string outputResolution, Dictionary> personKeyToIds, List distinctFilteredFaces, Mapping[] mappingCollection, int totalNotMapped)
+ private void MapLogic(long ticks, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string fPhotoPrismContentDirectory, MapLogic mapLogic, string outputResolution, Dictionary> personKeyToIds, List distinctFilteredFaces, Mapping[] distinctFilteredMappingCollection, int totalNotMapped)
{
string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()");
string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, "()");
string d2FacePartsContentCollectionDirectory = Path.Combine(d2ResultsFullGroupDirectory, "[()]");
string dFacesCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.PropertyConfiguration.ResultAllInOne);
- if (mappingCollection.Any())
+ if (distinctFilteredMappingCollection.Any())
{
Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(d2FacePartsContentDirectory, ticks);
Shared.Models.Stateless.Methods.IPath.MakeHiddenIfAllItemsAreHidden(d2FacePartsContentCollectionDirectory);
}
- Dictionary> idToNormalizedRectangleToMapping = Map.Models.Stateless.Methods.IMapLogic.GetIdToNormalizedRectangleToFace(mappingCollection);
+ Dictionary> idToNormalizedRectangleToMapping = Map.Models.Stateless.Methods.IMapLogic.GetIdToNormalizedRectangleToFace(distinctFilteredMappingCollection);
if (Directory.Exists(fPhotoPrismContentDirectory))
F_PhotoPrism.WriteMatches(fPhotoPrismContentDirectory, _Configuration.PersonBirthdayFormat, ticks, distinctFilteredFaces, mapLogic);
if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution))
- {
- List
- filteredItems = GetItems(argZero, containers);
- mapLogic.SaveShortcutsForOutputResolutionsDuringMapLogic(personKeyToIds, dFacesContentDirectory, filteredItems, mappingCollection);
- }
+ mapLogic.SaveShortcutsForOutputResolutionsDuringMapLogic(containers, personKeyToIds, dFacesContentDirectory, distinctFilteredMappingCollection);
if (!string.IsNullOrEmpty(_Configuration.PersonCharacters))
{
if (_Configuration.PersonCharactersCopyCount > 0)
- mapLogic.CopyAtLeastOneMappedFiles(_Configuration.PersonCharactersCopyCount, dFacesContentDirectory, a2PeopleSingletonDirectory, mappingCollection);
- mapLogic.SavePersonKeyToCount(dFacesContentDirectory, a2PeopleSingletonDirectory, mappingCollection);
+ mapLogic.CopyAtLeastOneMappedFiles(_Configuration.PersonCharactersCopyCount, dFacesContentDirectory, a2PeopleSingletonDirectory, distinctFilteredMappingCollection);
+ mapLogic.SavePersonKeyToCount(dFacesContentDirectory, a2PeopleSingletonDirectory, distinctFilteredMappingCollection);
}
mapLogic.CopyManualFiles(dFacesContentDirectory, idToNormalizedRectangleToMapping);
if (_Configuration.SaveMappedForOutputResolutions.Contains(outputResolution))
- mapLogic.SaveMapped(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, personKeyToIds, mappingCollection, idToNormalizedRectangleToMapping, totalNotMapped);
+ mapLogic.SaveMapped(dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, personKeyToIds, distinctFilteredMappingCollection, idToNormalizedRectangleToMapping, totalNotMapped);
if (_Configuration.SaveFaceDistancesForOutputResolutions.Contains(outputResolution))
- SaveFaceDistances(ticks, mapLogic, distinctFilteredFaces, mappingCollection, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, dFacesCollectionDirectory, idToNormalizedRectangleToMapping);
+ SaveFaceDistances(ticks, mapLogic, distinctFilteredFaces, distinctFilteredMappingCollection, dFacesContentDirectory, d2FacePartsContentDirectory, d2FacePartsContentCollectionDirectory, dFacesCollectionDirectory, idToNormalizedRectangleToMapping);
}
private string SaveUrlAndGetNewRootDirectory(Container container)
@@ -860,24 +837,6 @@ public partial class DlibDotNet
return result;
}
- private static void LookForAbandoned(ReadOnlyDictionary>> idToLocationContainers, List distinctFilteredIds)
- {
- List renameCollection = new();
- foreach (KeyValuePair>> idToCollection in idToLocationContainers)
- {
- if (distinctFilteredIds.Contains(idToCollection.Key))
- continue;
- foreach (LocationContainer locationContainer in idToCollection.Value)
- {
- if (locationContainer.File.Contains('!'))
- continue;
- renameCollection.Add(locationContainer.File);
- }
- }
- if (renameCollection.Any())
- Shared.Models.Stateless.Methods.IDirectory.MoveFiles(renameCollection, "()", "(abd)");
- }
-
private static void LookForAbandoned(List distinctFilteredIds, string directory, string directoryName)
{
string fileNameWithoutExtension;
@@ -898,21 +857,52 @@ public partial class DlibDotNet
if (directoryName.Length == 2)
Shared.Models.Stateless.Methods.IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[0]}abd{directoryName[^1]}");
else if (directoryName.Length == 4)
- Shared.Models.Stateless.Methods.IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[..2]}abd{directoryName[^2]}");
+ Shared.Models.Stateless.Methods.IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[..2]}abd{directoryName[^2..]}");
else
throw new NotSupportedException();
}
}
- private void LookForAbandoned(Container[] containers, ReadOnlyDictionary>> idToLocationContainers)
+ private static void LookForAbandoned(string bResultsFullGroupDirectory, List distinctFilteredIds)
+ {
+ string[] directories = Directory.GetDirectories(bResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
+ foreach (string directory in directories)
+ {
+ string? directoryName = Path.GetFileName(directory);
+ if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4))
+ continue;
+ LookForAbandoned(distinctFilteredIds, directory, directoryName);
+ }
+ }
+
+ private static void LookForAbandoned(ReadOnlyDictionary>> idToLocationContainers, List distinctFilteredIds)
+ {
+ List renameCollection = new();
+ foreach (KeyValuePair>> idToCollection in idToLocationContainers)
+ {
+ if (distinctFilteredIds.Contains(idToCollection.Key))
+ continue;
+ foreach (LocationContainer locationContainer in idToCollection.Value)
+ {
+ if (locationContainer.File.Contains('!'))
+ continue;
+ renameCollection.Add(locationContainer.File);
+ }
+ }
+ if (renameCollection.Any())
+ Shared.Models.Stateless.Methods.IDirectory.MoveFiles(renameCollection, "()", "(abd)");
+ }
+
+ private void LookForAbandoned(string bResultsFullGroupDirectory, Container[] containers, ReadOnlyDictionary>> idToLocationContainers)
{
string[] directories;
string? directoryName;
string cResultsFullGroupDirectory;
string dResultsFullGroupDirectory;
string d2ResultsFullGroupDirectory;
- List distinctFilteredIds = Shared.Models.Stateless.Methods.IContainer.GetFilteredDistinct(_Configuration.PropertyConfiguration, containers);
+ List distinctFilteredIds = Shared.Models.Stateless.Methods.IContainer.GetFilteredDistinctIds(_Configuration.PropertyConfiguration, containers);
LookForAbandoned(idToLocationContainers, distinctFilteredIds);
+ LookForAbandoned(bResultsFullGroupDirectory, distinctFilteredIds);
foreach (string outputResolution in _Configuration.OutputResolutions)
{
(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution);
@@ -943,6 +933,62 @@ public partial class DlibDotNet
}
}
+ private Mapping[] GetMappings(Property.Models.Configuration propertyConfiguration, Container[] containers, MapLogic mapLogic, ReadOnlyDictionary>> idToLocationContainers, bool distinctItems)
+ {
+ Mapping[] results;
+ int count = 0;
+ Mapping mapping;
+ bool anyValidFaces;
+ string focusRelativePath;
+ bool? isFocusRelativePath;
+ bool? isIgnoreRelativePath;
+ List distinct = new();
+ DateTime[] containerDateTimes;
+ IEnumerable
- filteredItems;
+ MappingFromItem mappingFromItem;
+ List mappingCollection = new();
+ foreach (Container container in containers)
+ {
+ if (!container.Items.Any())
+ continue;
+ filteredItems = Shared.Models.Stateless.Methods.IContainer.GetFilterItems(propertyConfiguration, container);
+ if (!filteredItems.Any())
+ continue;
+ containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems);
+ focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory));
+ isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
+ isIgnoreRelativePath = !_Configuration.IgnoreRelativePaths.Any() ? null : _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, item.ResizedFileHolder);
+ if (distinctItems)
+ {
+ if (distinct.Contains(item.Property.Id.Value))
+ continue;
+ distinct.Add(item.Property.Id.Value);
+ }
+ count++;
+ anyValidFaces = false;
+ foreach (Shared.Models.Face face in item.Faces)
+ {
+ if (face.Mapping is null)
+ continue;
+ anyValidFaces = true;
+ mappingCollection.Add(face.Mapping);
+ }
+ if (!anyValidFaces)
+ {
+ mapping = GetMapping(idToLocationContainers, mapLogic, item, isFocusRelativePath, isIgnoreRelativePath, mappingFromItem);
+ mappingCollection.Add(mapping);
+ }
+ }
+ }
+ results = (from l in mappingCollection orderby l.MappingFromItem.Id select l).ToArray();
+ return results;
+ }
+
private void Search(long ticks, string argZero, string propertyRoot)
{
int t;
@@ -1006,14 +1052,15 @@ public partial class DlibDotNet
ReadOnlyDictionary>> idToLocationContainers = mapLogic.GetIdToLocationContainers();
fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = new() : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory);
FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, eDistanceContentDirectory, fileNameToCollection, idToLocationContainers, mapLogic);
- LookForAbandoned(containers, idToLocationContainers);
+ LookForAbandoned(bResultsFullGroupDirectory, containers, idToLocationContainers);
_Distance.Clear();
if (!personKeyToIds.Any())
personKeyToIds = mapLogic.GetPersonKeyToIds();
- List distinctFilteredFaces = GetFilteredDistinct(argZero, containers);
- Mapping[] mappingCollection = Map.Models.Stateless.Methods.IMapLogic.GetSelectedMappingCollection(distinctFilteredFaces);
- int totalNotMapped = mapLogic.UpdateMappingFromPerson(mappingCollection);
- string json = System.Text.Json.JsonSerializer.Serialize(mappingCollection);
+ Mapping[] distinctFilteredMappingCollection = GetMappings(_Configuration.PropertyConfiguration, containers, mapLogic, idToLocationContainers, distinctItems: true);
+ List
- distinctFilteredItems = Shared.Models.Stateless.Methods.IContainer.GetItems(_Configuration.PropertyConfiguration, containers, distinctItems: true, filterItems: true);
+ List distinctFilteredFaces = Map.Models.Stateless.Methods.IMapLogic.GetFaces(distinctFilteredItems);
+ int totalNotMapped = mapLogic.UpdateMappingFromPerson(distinctFilteredMappingCollection);
+ string json = System.Text.Json.JsonSerializer.Serialize(distinctFilteredMappingCollection);
File.WriteAllText(Path.Combine(eDistanceContentDirectory, $"{ticks}.json"), json);
for (int i = 1; i < 5; i++)
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
@@ -1022,18 +1069,18 @@ public partial class DlibDotNet
if (_PropertyRootExistedBefore)
break;
if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && _Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution))
- mapLogic.SaveShortcutsForOutputResolutionsPreMapLogic(eDistanceContentDirectory, personKeyToIds, idToLocationContainers, mappingCollection);
+ mapLogic.SaveShortcutsForOutputResolutionsPreMapLogic(eDistanceContentDirectory, personKeyToIds, distinctFilteredMappingCollection);
if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && _Configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions.Contains(outputResolution))
- mapLogic.SaveFilteredOriginalImagesFromJLinks(_Configuration.JLinks, _PersonContainers, a2PeopleContentDirectory, personKeyToIds, mappingCollection, totalNotMapped);
+ mapLogic.SaveFilteredOriginalImagesFromJLinks(_Configuration.JLinks, _PersonContainers, a2PeopleContentDirectory, personKeyToIds, distinctFilteredMappingCollection, totalNotMapped);
(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution);
if (_ArgZeroIsConfigurationRootDirectory
&& _Configuration.SaveResizedSubfiles
&& outputResolution == _Configuration.OutputResolutions[0]
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
&& _Exceptions.Count == 0)
- MapLogic(argZero, ticks, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, fPhotoPrismContentDirectory, mapLogic, outputResolution, personKeyToIds, distinctFilteredFaces, mappingCollection, totalNotMapped);
- if (_Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Any() && mappingCollection.Any())
- _Random.Random(_Configuration.PropertyConfiguration, outputResolution, personKeyToIds, mappingCollection);
+ MapLogic(ticks, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, fPhotoPrismContentDirectory, mapLogic, outputResolution, personKeyToIds, distinctFilteredFaces, distinctFilteredMappingCollection, totalNotMapped);
+ if (_Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Any() && distinctFilteredMappingCollection.Any())
+ _Random.Random(_Configuration.PropertyConfiguration, outputResolution, personKeyToIds, distinctFilteredMappingCollection);
if (_IsEnvironment.Development)
continue;
if (!_IsEnvironment.Development)
diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs
index c83133c..0f84b74 100644
--- a/Map/Models/MapLogic.cs
+++ b/Map/Models/MapLogic.cs
@@ -1,6 +1,7 @@
using Humanizer;
using ShellProgressBar;
using System.Collections.ObjectModel;
+using System.Globalization;
using System.Text.Json;
using System.Text.RegularExpressions;
using View_by_Distance.Shared.Models;
@@ -1122,35 +1123,43 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
SaveContainers(saveIndividually, totalNotMapped, null, saveContainers);
}
- private List GetCollectionForSaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, Dictionary> personKeyToIds, ReadOnlyDictionary>> idToLocationContainers, Mapping[] mappingCollection)
+ private List GetCollectionForSaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, Dictionary> personKeyToIds, Mapping[] mappingCollection)
{
List results = new();
if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration));
+ int season;
string? model;
long personKey;
string fileName;
string directory;
+ int dateCount = 0;
+ string weekOfYear;
+ string description;
+ DateTime? dateTime;
string directoryName;
List? personKeys;
string personKeyFormatted;
+ Calendar calendar = new CultureInfo("en-US").Calendar;
IReadOnlyList directories;
- List>? locationContainers;
Dictionary> idToPersonKeys = Stateless.Methods.IMapLogic.GetIdToPersonKeys(personKeyToIds);
foreach (Mapping mapping in mappingCollection)
{
- if (mapping.MappingFromLocation is null || mapping.MappingFromItem.ImageFileHolder.DirectoryName is null || mapping.MappingFromPerson is null)
- continue;
- if (!idToLocationContainers.TryGetValue(mapping.MappingFromItem.Id, out locationContainers) || !locationContainers.Any())
- directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mapping.MappingFromItem.ResizedFileHolder.FullName);
- else
+ directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mapping.MappingFromItem.ResizedFileHolder.FullName);
+ dateTime = Metadata.Models.Stateless.Methods.IMetadata.GetMinimumDateTime(directories);
+ description = mapping.MappingFromLocation is null ? mapping.MappingFromItem.Id.ToString() : mapping.MappingFromLocation.DeterministicHashCodeKey;
+ if (dateTime is not null)
{
- directories = locationContainers.First().Directories;
- model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(directories);
- if (model is null)
- directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mapping.MappingFromItem.ResizedFileHolder.FullName);
+ dateCount++;
+ (season, _) = IProperty.GetSeason(dateTime.Value.DayOfYear);
+ weekOfYear = calendar.GetWeekOfYear(dateTime.Value, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
+ directory = Path.Combine($"{eDistanceContentDirectory}---", "Date Shortcuts", $"{dateTime.Value.Year}.{season}-MM{dateTime.Value.Month:00}-WW{weekOfYear}");
+ fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk");
+ results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, description, MakeAllHidden: false));
}
model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(directories);
+ if (mapping.MappingFromItem.ImageFileHolder.DirectoryName is null)
+ continue;
directoryName = Path.GetFileName(mapping.MappingFromItem.ImageFileHolder.DirectoryName);
if (!string.IsNullOrEmpty(model) && !string.IsNullOrEmpty(model.Trim()))
{
@@ -1158,8 +1167,10 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
model = Regex.Replace(model.Trim(), @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]", "_");
directory = Path.Combine($"{eDistanceContentDirectory}---", "Model Shortcuts", model, directoryName);
fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk");
- results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey, MakeAllHidden: false));
+ results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, description, MakeAllHidden: false));
}
+ if (mapping.MappingFromPerson is null)
+ continue;
if (!idToPersonKeys.TryGetValue(mapping.MappingFromItem.Id, out personKeys))
continue;
personKey = mapping.MappingFromPerson.PersonBirthday.Value.Ticks;
@@ -1168,22 +1179,22 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday);
directory = Path.Combine($"{eDistanceContentDirectory}---", "Person Key Shortcuts", personKeyFormatted, directoryName);
fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk");
- results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey, MakeAllHidden: false));
+ results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, description, MakeAllHidden: false));
if (IPerson.IsDefaultName(_Configuration.MappingDefaultName, mapping.MappingFromPerson.DisplayDirectoryName))
continue;
directory = Path.Combine($"{eDistanceContentDirectory}---", "Name Shortcuts", mapping.MappingFromPerson.DisplayDirectoryName, directoryName);
fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk");
- results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey, MakeAllHidden: false));
+ results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, description, MakeAllHidden: false));
}
return results;
}
- public void SaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, Dictionary> personKeyToIds, ReadOnlyDictionary>> idToLocationContainers, Mapping[] mappingCollection)
+ public void SaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, Dictionary> personKeyToIds, Mapping[] mappingCollection)
{
string hiddenFile;
WindowsShortcut windowsShortcut;
List collection = new();
- collection = GetCollectionForSaveShortcutsForOutputResolutionsPreMapLogic(eDistanceContentDirectory, personKeyToIds, idToLocationContainers, mappingCollection);
+ collection = GetCollectionForSaveShortcutsForOutputResolutionsPreMapLogic(eDistanceContentDirectory, personKeyToIds, mappingCollection);
string[] distinctDirectories = (from l in collection select l.Directory).Distinct().ToArray();
foreach (string directory in distinctDirectories)
{
@@ -1308,13 +1319,14 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
return new(directoriesAndDateTimes, collection);
}
- public void SaveShortcutsForOutputResolutionsDuringMapLogic(Dictionary> personKeyToIds, string dFacesContentDirectory, List
- filteredItems, Mapping[] mappingCollection)
+ public void SaveShortcutsForOutputResolutionsDuringMapLogic(Container[] containers, Dictionary> personKeyToIds, string dFacesContentDirectory, Mapping[] mappingCollection)
{
if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration));
WindowsShortcut windowsShortcut;
List<(string, DateTime[])> directoriesAndDateTimes;
List collection;
+ List
- filteredItems = IContainer.GetItems(_PropertyConfiguration, containers, distinctItems: true, filterItems: true);
(directoriesAndDateTimes, collection) = GetCollectionForSaveShortcutsForOutputResolutionsDuringMapLogic(personKeyToIds, dFacesContentDirectory, filteredItems, mappingCollection);
string[] directories = (from l in collection select l.Directory).Distinct().ToArray();
foreach (string directory in directories)
diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs
index 26ae7d6..71e1871 100644
--- a/Map/Models/Stateless/MapLogic.cs
+++ b/Map/Models/Stateless/MapLogic.cs
@@ -993,14 +993,39 @@ internal abstract class MapLogic
return results;
}
- internal static Mapping[] GetSelectedMappingCollection(List distinctFilteredFaces)
+ internal static Mapping[] GetSelectedMappingCollection(List faces)
{
Mapping[] results;
- IEnumerable collection = from l in distinctFilteredFaces orderby l.Mapping?.MappingFromItem.Id select l.Mapping;
+ IEnumerable collection = from l in faces orderby l.Mapping?.MappingFromItem.Id select l.Mapping;
results = (from l in collection where l is not null select l).ToArray();
return results;
}
+ internal static List GetFaces(List
- items)
+ {
+ List results = new();
+ foreach (Item item in items)
+ {
+ if (item.Property?.Id is null || item.ResizedFileHolder is null)
+ continue;
+ foreach (Face face in item.Faces)
+ {
+ if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
+ continue;
+ results.Add(face);
+ }
+ }
+ return results;
+ }
+
+ internal static Mapping[] GetSelectedMappingCollection(List
- items)
+ {
+ Mapping[] results;
+ List faces = GetFaces(items);
+ results = GetSelectedMappingCollection(faces);
+ return results;
+ }
+
internal static Dictionary> GetIdToNormalizedRectangleToFace(Mapping[] mappingCollection)
{
Dictionary> results = new();
diff --git a/Map/Models/Stateless/Methods/IMapLogic.cs b/Map/Models/Stateless/Methods/IMapLogic.cs
index 6947c9b..84f322b 100644
--- a/Map/Models/Stateless/Methods/IMapLogic.cs
+++ b/Map/Models/Stateless/Methods/IMapLogic.cs
@@ -8,10 +8,20 @@ public interface IMapLogic
static Dictionary> GetIdToPersonKeys(Dictionary> personKeyToIds) =>
MapLogic.GetIdToPersonKeys(personKeyToIds);
- Shared.Models.Mapping[] TestStatic_GetSelectedMappingCollection(List distinctFilteredFaces) =>
- GetSelectedMappingCollection(distinctFilteredFaces);
- static Shared.Models.Mapping[] GetSelectedMappingCollection(List distinctFilteredFaces) =>
- MapLogic.GetSelectedMappingCollection(distinctFilteredFaces);
+ List TestStatic_GetFaces(List items) =>
+ GetFaces(items);
+ static List GetFaces(List items) =>
+ MapLogic.GetFaces(items);
+
+ Shared.Models.Mapping[] TestStatic_GetSelectedMappingCollection(List items) =>
+ GetSelectedMappingCollection(items);
+ static Shared.Models.Mapping[] GetSelectedMappingCollection(List items) =>
+ MapLogic.GetSelectedMappingCollection(items);
+
+ Shared.Models.Mapping[] TestStatic_GetSelectedMappingCollection(List faces) =>
+ GetSelectedMappingCollection(faces);
+ static Shared.Models.Mapping[] GetSelectedMappingCollection(List faces) =>
+ MapLogic.GetSelectedMappingCollection(faces);
Dictionary> TestStatic_GetIdToNormalizedRectangleToFace(Shared.Models.Mapping[] mappingCollection) =>
GetIdToNormalizedRectangleToFace(mappingCollection);
diff --git a/Metadata/Models/Stateless/Methods/IMetadata.cs b/Metadata/Models/Stateless/Methods/IMetadata.cs
index eb4926b..0fd4c02 100644
--- a/Metadata/Models/Stateless/Methods/IMetadata.cs
+++ b/Metadata/Models/Stateless/Methods/IMetadata.cs
@@ -3,10 +3,15 @@ namespace View_by_Distance.Metadata.Models.Stateless.Methods;
public interface IMetadata
{
- DateTime TestStatic_GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList directories) =>
+ DateTime? TestStatic_GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList directories) =>
GetMinimumDateTime(dateTimes, year, directories);
- static DateTime GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList directories) =>
- Metadata.GetMinimumDateTime(dateTimes, year, directories);
+ static DateTime? GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList directories) =>
+ Metadata.GetMinimumDateTime(directories, dateTimes, year);
+
+ DateTime? TestStatic_GetMinimumDateTime(IReadOnlyList directories) =>
+ GetMinimumDateTime(directories);
+ static DateTime? GetMinimumDateTime(IReadOnlyList directories) =>
+ Metadata.GetMinimumDateTime(directories, dateTimes: null, year: null);
string? TestStatic_GetModel(IReadOnlyList directories) =>
GetModel(directories);
diff --git a/Metadata/Models/Stateless/Methods/Metadata.cs b/Metadata/Models/Stateless/Methods/Metadata.cs
index 1e8b15f..8894774 100644
--- a/Metadata/Models/Stateless/Methods/Metadata.cs
+++ b/Metadata/Models/Stateless/Methods/Metadata.cs
@@ -53,11 +53,11 @@ internal class Metadata
return result;
}
- internal static DateTime GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList directories)
+ internal static DateTime? GetMinimumDateTime(IReadOnlyList directories, DateTime?[]? dateTimes, int? year)
{
- DateTime result;
+ DateTime? result;
DateTime dateTime;
- List results = (from l in dateTimes where l is not null select l.Value).ToList();
+ List results = dateTimes is null ? new() : (from l in dateTimes where l is not null select l.Value).ToList();
ExifDirectoryBase? exifDirectoryBase = directories.OfType().FirstOrDefault();
if (exifDirectoryBase is not null)
{
@@ -86,11 +86,13 @@ internal class Metadata
if (quickTimeTrackHeaderDirectory.TryGetDateTime(QuickTimeTrackHeaderDirectory.TagCreated, out dateTime))
results.Add(dateTime);
}
- DateTime[] filtered = (from l in results where l.Year >= year select l).ToArray();
- if (!filtered.Any())
+ DateTime[] filtered = year is null ? results.ToArray() : (from l in results where l.Year >= year select l).ToArray();
+ if (filtered.Any())
+ result = filtered.Min();
+ else if (results.Any())
result = results.Min();
else
- result = filtered.Min();
+ result = null;
return result;
}
diff --git a/Shared/Models/Stateless/Methods/Container.cs b/Shared/Models/Stateless/Methods/Container.cs
index 79eaa56..158794a 100644
--- a/Shared/Models/Stateless/Methods/Container.cs
+++ b/Shared/Models/Stateless/Methods/Container.cs
@@ -7,16 +7,16 @@ internal abstract class Container
private record FilePair(string Path, string? Directory, bool IsUnique, List Collection, Models.Item Item) { }
- internal static DateTime[] GetContainerDateTimes(Models.Item[] filteredItems)
+ internal static DateTime[] GetContainerDateTimes(IEnumerable items)
{
DateTime[] results;
DateTime? containerMinimumDateTime;
DateTime? containerMaximumDateTime;
- containerMinimumDateTime = (from l in filteredItems select l.ImageFileHolder.LastWriteTime).Min();
+ containerMinimumDateTime = (from l in items select l.ImageFileHolder.LastWriteTime).Min();
if (containerMinimumDateTime is null)
containerMaximumDateTime = null;
else
- containerMaximumDateTime = (from l in filteredItems select l.ImageFileHolder.LastWriteTime).Max();
+ containerMaximumDateTime = (from l in items select l.ImageFileHolder.LastWriteTime).Max();
if (containerMinimumDateTime is null || containerMaximumDateTime is null)
results = Array.Empty();
else
@@ -94,10 +94,7 @@ internal abstract class Container
filePairs = IDirectory.GetFiles(filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles);
renamed += IDirectory.MaybeMove(propertyConfiguration.RootDirectory, propertyConfiguration.ResultAllInOne, filePairs, aPropertySingletonDirectory, extension);
if (renamed == 0)
- {
- _ = IPath.DeleteEmptyDirectories(aPropertySingletonDirectory);
break;
- }
}
if (filePairs is null || jsonFilesCollection is null || compareFileNamesToFiles is null)
throw new NullReferenceException(nameof(filePairs));
@@ -228,7 +225,7 @@ internal abstract class Container
return (collection.Count, results.ToArray());
}
- internal static List GetFilteredDistinct(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers)
+ internal static List GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers)
{
List results = new();
Models.Item[] filteredItems;
@@ -251,4 +248,37 @@ internal abstract class Container
return results;
}
+ internal static List GetItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers, bool distinctItems, bool filterItems)
+ {
+ List results = new();
+ List distinct = new();
+ IEnumerable filteredItems;
+ foreach (Models.Container container in containers)
+ {
+ if (!container.Items.Any())
+ continue;
+ if (!filterItems)
+ filteredItems = container.Items;
+ else
+ {
+ filteredItems = GetFilterItems(propertyConfiguration, container);
+ if (!filteredItems.Any())
+ continue;
+ }
+ foreach (Models.Item item in filteredItems)
+ {
+ if (item.Property?.Id is null || item.ResizedFileHolder is null)
+ continue;
+ if (distinctItems)
+ {
+ if (distinct.Contains(item.Property.Id.Value))
+ continue;
+ distinct.Add(item.Property.Id.Value);
+ }
+ results.Add(item);
+ }
+ }
+ return results;
+ }
+
}
\ No newline at end of file
diff --git a/Shared/Models/Stateless/Methods/IContainer.cs b/Shared/Models/Stateless/Methods/IContainer.cs
index 6a5b59d..df4a141 100644
--- a/Shared/Models/Stateless/Methods/IContainer.cs
+++ b/Shared/Models/Stateless/Methods/IContainer.cs
@@ -3,10 +3,10 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IContainer
{
- DateTime[] TestStatic_GetContainerDateTimes(Models.Item[] filteredItems) =>
- GetContainerDateTimes(filteredItems);
- static DateTime[] GetContainerDateTimes(Models.Item[] filteredItems) =>
- Container.GetContainerDateTimes(filteredItems);
+ DateTime[] TestStatic_GetContainerDateTimes(IEnumerable items) =>
+ GetContainerDateTimes(items);
+ static DateTime[] GetContainerDateTimes(IEnumerable items) =>
+ Container.GetContainerDateTimes(items);
Models.Item[] TestStatic_GetFilterItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container container) =>
GetFilterItems(propertyConfiguration, container);
@@ -33,9 +33,14 @@ public interface IContainer
static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory);
- List TestStatic_GetFilteredDistinct(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) =>
- GetFilteredDistinct(propertyConfiguration, containers);
- static List GetFilteredDistinct(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) =>
- Container.GetFilteredDistinct(propertyConfiguration, containers);
+ List TestStatic_GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) =>
+ GetFilteredDistinctIds(propertyConfiguration, containers);
+ static List GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) =>
+ Container.GetFilteredDistinctIds(propertyConfiguration, containers);
+
+ List TestStatic_GetItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers, bool distinctItems, bool filterItems) =>
+ GetItems(propertyConfiguration, containers, distinctItems, filterItems);
+ static List GetItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers, bool distinctItems, bool filterItems) =>
+ Container.GetItems(propertyConfiguration, containers, distinctItems, filterItems);
}
\ No newline at end of file
diff --git a/Shared/Models/Stateless/Methods/ILocation.cs b/Shared/Models/Stateless/Methods/ILocation.cs
index 95a1bec..09dc0b7 100644
--- a/Shared/Models/Stateless/Methods/ILocation.cs
+++ b/Shared/Models/Stateless/Methods/ILocation.cs
@@ -95,6 +95,11 @@ public interface ILocation
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 locationDigits) =>
+ GetNormalizedRectangle(locationDigits);
+ static int GetNormalizedRectangle(int locationDigits) =>
+ Location.GetNormalizedRectangle(1, 1, 0, locationDigits, 1, 0, 1, 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) =>
diff --git a/Shared/Models/Stateless/Methods/IMapping.cs b/Shared/Models/Stateless/Methods/IMapping.cs
index 8f92099..e988ffd 100644
--- a/Shared/Models/Stateless/Methods/IMapping.cs
+++ b/Shared/Models/Stateless/Methods/IMapping.cs
@@ -28,6 +28,11 @@ public interface IMapping
static string GetDeterministicHashCodeKey(int id, Models.Location location, int locationDigits, Models.OutputResolution outputResolution)
=> $"{id}.{ILocation.GetLeftPadded(locationDigits, ILocation.GetNormalizedRectangle(location, locationDigits, outputResolution))}";
+ string TestStatic_GetDeterministicHashCodeKey(int id, int locationDigits)
+ => GetDeterministicHashCodeKey(id, locationDigits);
+ static string GetDeterministicHashCodeKey(int id, int locationDigits)
+ => $"{id}.{ILocation.GetLeftPadded(locationDigits, ILocation.GetNormalizedRectangle(locationDigits))}";
+
(int?, int?) TestStatic_GetConverted(string facesFileNameExtension, string file) =>
GetConverted(facesFileNameExtension, file);
static (int?, int?) GetConverted(string facesFileNameExtension, string file) =>
diff --git a/Shared/Models/Stateless/Methods/IPath.cs b/Shared/Models/Stateless/Methods/IPath.cs
index 47c6a36..164f727 100644
--- a/Shared/Models/Stateless/Methods/IPath.cs
+++ b/Shared/Models/Stateless/Methods/IPath.cs
@@ -34,6 +34,11 @@ public interface IPath
static string[] GetDirectoryNames(string directory) =>
XPath.GetDirectoryNames(directory).ToArray();
+ string[] TestStatic_GetDirectories(string directory) =>
+ GetDirectories(directory);
+ static string[] GetDirectories(string directory) =>
+ XPath.GetDirectories(directory).ToArray();
+
string TestStatic_GetRelativePath(string path, int length, bool forceExtensionToLower) =>
GetRelativePath(path, length, forceExtensionToLower);
static string GetRelativePath(string path, int length, bool forceExtensionToLower) =>
diff --git a/Shared/Models/Stateless/Methods/XPath.cs b/Shared/Models/Stateless/Methods/XPath.cs
index 8a41e6b..12f4395 100644
--- a/Shared/Models/Stateless/Methods/XPath.cs
+++ b/Shared/Models/Stateless/Methods/XPath.cs
@@ -138,6 +138,27 @@ internal abstract class XPath
return results;
}
+ internal static List GetDirectories(string directory)
+ {
+ List results = new();
+ string? checkDirectory = directory;
+ string? pathRoot = Path.GetPathRoot(directory);
+ if (string.IsNullOrEmpty(pathRoot))
+ throw new NullReferenceException(nameof(pathRoot));
+ if (Directory.Exists(directory))
+ results.Add(directory);
+ for (int i = 0; i < int.MaxValue; i++)
+ {
+ checkDirectory = Path.GetDirectoryName(checkDirectory);
+ if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == pathRoot)
+ break;
+ results.Add(checkDirectory);
+ }
+ results.Add(pathRoot);
+ results.Reverse();
+ return results;
+ }
+
internal static (int level, List directories) Get(string rootDirectory, string sourceDirectory)
{
int result = 0;
diff --git a/View-by-Distance-MKLink-Console.sln b/View-by-Distance-MKLink-Console.sln
index 41c9d4d..e14d3af 100644
--- a/View-by-Distance-MKLink-Console.sln
+++ b/View-by-Distance-MKLink-Console.sln
@@ -51,6 +51,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Move-By-Id", "Move-By-Id\Mo
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Person", "Person\Person.csproj", "{C5003A39-334B-444B-9873-39B26E58D667}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drag-Drop-Move", "Drag-Drop-Move\Drag-Drop-Move.csproj", "{CF05EFAC-C212-4EE0-A644-3F728991AA54}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -160,5 +162,9 @@ Global
{C5003A39-334B-444B-9873-39B26E58D667}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5003A39-334B-444B-9873-39B26E58D667}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5003A39-334B-444B-9873-39B26E58D667}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CF05EFAC-C212-4EE0-A644-3F728991AA54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CF05EFAC-C212-4EE0-A644-3F728991AA54}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CF05EFAC-C212-4EE0-A644-3F728991AA54}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CF05EFAC-C212-4EE0-A644-3F728991AA54}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal