Drag-Drop-Move

This commit is contained in:
Mike Phares 2023-05-03 18:12:50 -07:00
parent 07ecbeb76c
commit e6acce3852
24 changed files with 853 additions and 160 deletions

17
.vscode/launch.json vendored
View File

@ -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",

26
Drag-Drop-Move/.vscode/launch.json vendored Normal file
View File

@ -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"
}
]
}

41
Drag-Drop-Move/.vscode/tasks.json vendored Normal file
View File

@ -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"
}
]
}

View File

@ -0,0 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>WinExe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net7.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

39
Drag-Drop-Move/DragDropMove.Designer.cs generated Normal file
View File

@ -0,0 +1,39 @@
namespace View_by_Distance.Drag_Drop_Explorer;
partial class DragDropMove
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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
}

View File

@ -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<DragDropMove>();
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;
}
}
}

View File

@ -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;
}
}

View File

@ -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<AppSettings>();
result = Get(appSettings);
return result;
}
}

15
Drag-Drop-Move/Program.cs Normal file
View File

@ -0,0 +1,15 @@
namespace View_by_Distance.Drag_Drop_Explorer;
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
Application.Run(new DragDropMove());
}
}

View File

@ -0,0 +1,11 @@
{
"Logging": {
"LogLevel": {
"Log4netProvider": "Debug"
}
},
"MaxDegreeOfParallelism": 6,
"Serilog": {
"MinimumLevel": "Debug"
}
}

View File

@ -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"
}

View File

@ -271,26 +271,18 @@ public partial class DlibDotNet
return result;
}
private void SetMapping(ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection, List<Shared.Models.Face> faces)
private bool? GetIsFocusModel(ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> 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<MetadataExtractor.Directory> directories;
List<LocationContainer<MetadataExtractor.Directory>>? locationContainers;
IReadOnlyList<MetadataExtractor.Directory> 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<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection, List<Shared.Models.Face> 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<int, List<LocationContainer<MetadataExtractor.Directory>>> 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<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers,
@ -677,61 +712,6 @@ public partial class DlibDotNet
}
}
private List<Shared.Models.Face> GetFilteredDistinct(string argZero, Container[] containers)
{
List<Shared.Models.Face> results = new();
Item[] filteredItems;
List<int> 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<Item> GetItems(string argZero, Container[] containers)
{
List<Item> 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<int, Dictionary<int, Mapping>> idToNormalizedRectangleToMapping, List<FaceDistance> 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<long, List<int>> personKeyToIds, List<Shared.Models.Face> 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<long, List<int>> personKeyToIds, List<Shared.Models.Face> 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<int, Dictionary<int, Mapping>> idToNormalizedRectangleToMapping = Map.Models.Stateless.Methods.IMapLogic.GetIdToNormalizedRectangleToFace(mappingCollection);
Dictionary<int, Dictionary<int, Mapping>> 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<Item> 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<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, List<int> distinctFilteredIds)
{
List<string> renameCollection = new();
foreach (KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> idToCollection in idToLocationContainers)
{
if (distinctFilteredIds.Contains(idToCollection.Key))
continue;
foreach (LocationContainer<MetadataExtractor.Directory> 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<int> 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<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers)
private static void LookForAbandoned(string bResultsFullGroupDirectory, List<int> 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<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, List<int> distinctFilteredIds)
{
List<string> renameCollection = new();
foreach (KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> idToCollection in idToLocationContainers)
{
if (distinctFilteredIds.Contains(idToCollection.Key))
continue;
foreach (LocationContainer<MetadataExtractor.Directory> 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<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers)
{
string[] directories;
string? directoryName;
string cResultsFullGroupDirectory;
string dResultsFullGroupDirectory;
string d2ResultsFullGroupDirectory;
List<int> distinctFilteredIds = Shared.Models.Stateless.Methods.IContainer.GetFilteredDistinct(_Configuration.PropertyConfiguration, containers);
List<int> 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<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, bool distinctItems)
{
Mapping[] results;
int count = 0;
Mapping mapping;
bool anyValidFaces;
string focusRelativePath;
bool? isFocusRelativePath;
bool? isIgnoreRelativePath;
List<int> distinct = new();
DateTime[] containerDateTimes;
IEnumerable<Item> filteredItems;
MappingFromItem mappingFromItem;
List<Mapping> 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<int, List<LocationContainer<MetadataExtractor.Directory>>> 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<Shared.Models.Face> 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<Item> distinctFilteredItems = Shared.Models.Stateless.Methods.IContainer.GetItems(_Configuration.PropertyConfiguration, containers, distinctItems: true, filterItems: true);
List<Shared.Models.Face> 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)

View File

@ -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<SaveShortcutsForOutputResolutions> GetCollectionForSaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, Dictionary<long, List<int>> personKeyToIds, ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, Mapping[] mappingCollection)
private List<SaveShortcutsForOutputResolutions> GetCollectionForSaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, Dictionary<long, List<int>> personKeyToIds, Mapping[] mappingCollection)
{
List<SaveShortcutsForOutputResolutions> 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<long>? personKeys;
string personKeyFormatted;
Calendar calendar = new CultureInfo("en-US").Calendar;
IReadOnlyList<MetadataExtractor.Directory> directories;
List<LocationContainer<MetadataExtractor.Directory>>? locationContainers;
Dictionary<int, List<long>> 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<long, List<int>> personKeyToIds, ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, Mapping[] mappingCollection)
public void SaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, Dictionary<long, List<int>> personKeyToIds, Mapping[] mappingCollection)
{
string hiddenFile;
WindowsShortcut windowsShortcut;
List<SaveShortcutsForOutputResolutions> 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<long, List<int>> personKeyToIds, string dFacesContentDirectory, List<Item> filteredItems, Mapping[] mappingCollection)
public void SaveShortcutsForOutputResolutionsDuringMapLogic(Container[] containers, Dictionary<long, List<int>> personKeyToIds, string dFacesContentDirectory, Mapping[] mappingCollection)
{
if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration));
WindowsShortcut windowsShortcut;
List<(string, DateTime[])> directoriesAndDateTimes;
List<SaveShortcutsForOutputResolutions> collection;
List<Item> 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)

View File

@ -993,14 +993,39 @@ internal abstract class MapLogic
return results;
}
internal static Mapping[] GetSelectedMappingCollection(List<Face> distinctFilteredFaces)
internal static Mapping[] GetSelectedMappingCollection(List<Face> faces)
{
Mapping[] results;
IEnumerable<Mapping> collection = from l in distinctFilteredFaces orderby l.Mapping?.MappingFromItem.Id select l.Mapping;
IEnumerable<Mapping> 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<Face> GetFaces(List<Item> items)
{
List<Face> 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<Item> items)
{
Mapping[] results;
List<Face> faces = GetFaces(items);
results = GetSelectedMappingCollection(faces);
return results;
}
internal static Dictionary<int, Dictionary<int, Mapping>> GetIdToNormalizedRectangleToFace(Mapping[] mappingCollection)
{
Dictionary<int, Dictionary<int, Mapping>> results = new();

View File

@ -8,10 +8,20 @@ public interface IMapLogic
static Dictionary<int, List<long>> GetIdToPersonKeys(Dictionary<long, List<int>> personKeyToIds) =>
MapLogic.GetIdToPersonKeys(personKeyToIds);
Shared.Models.Mapping[] TestStatic_GetSelectedMappingCollection(List<Shared.Models.Face> distinctFilteredFaces) =>
GetSelectedMappingCollection(distinctFilteredFaces);
static Shared.Models.Mapping[] GetSelectedMappingCollection(List<Shared.Models.Face> distinctFilteredFaces) =>
MapLogic.GetSelectedMappingCollection(distinctFilteredFaces);
List<Shared.Models.Face> TestStatic_GetFaces(List<Shared.Models.Item> items) =>
GetFaces(items);
static List<Shared.Models.Face> GetFaces(List<Shared.Models.Item> items) =>
MapLogic.GetFaces(items);
Shared.Models.Mapping[] TestStatic_GetSelectedMappingCollection(List<Shared.Models.Item> items) =>
GetSelectedMappingCollection(items);
static Shared.Models.Mapping[] GetSelectedMappingCollection(List<Shared.Models.Item> items) =>
MapLogic.GetSelectedMappingCollection(items);
Shared.Models.Mapping[] TestStatic_GetSelectedMappingCollection(List<Shared.Models.Face> faces) =>
GetSelectedMappingCollection(faces);
static Shared.Models.Mapping[] GetSelectedMappingCollection(List<Shared.Models.Face> faces) =>
MapLogic.GetSelectedMappingCollection(faces);
Dictionary<int, Dictionary<int, Shared.Models.Mapping>> TestStatic_GetIdToNormalizedRectangleToFace(Shared.Models.Mapping[] mappingCollection) =>
GetIdToNormalizedRectangleToFace(mappingCollection);

View File

@ -3,10 +3,15 @@ namespace View_by_Distance.Metadata.Models.Stateless.Methods;
public interface IMetadata
{
DateTime TestStatic_GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList<MetadataExtractor.Directory> directories) =>
DateTime? TestStatic_GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList<MetadataExtractor.Directory> directories) =>
GetMinimumDateTime(dateTimes, year, directories);
static DateTime GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList<MetadataExtractor.Directory> directories) =>
Metadata.GetMinimumDateTime(dateTimes, year, directories);
static DateTime? GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList<MetadataExtractor.Directory> directories) =>
Metadata.GetMinimumDateTime(directories, dateTimes, year);
DateTime? TestStatic_GetMinimumDateTime(IReadOnlyList<MetadataExtractor.Directory> directories) =>
GetMinimumDateTime(directories);
static DateTime? GetMinimumDateTime(IReadOnlyList<MetadataExtractor.Directory> directories) =>
Metadata.GetMinimumDateTime(directories, dateTimes: null, year: null);
string? TestStatic_GetModel(IReadOnlyList<MetadataExtractor.Directory> directories) =>
GetModel(directories);

View File

@ -53,11 +53,11 @@ internal class Metadata
return result;
}
internal static DateTime GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList<MetadataExtractor.Directory> directories)
internal static DateTime? GetMinimumDateTime(IReadOnlyList<MetadataExtractor.Directory> directories, DateTime?[]? dateTimes, int? year)
{
DateTime result;
DateTime? result;
DateTime dateTime;
List<DateTime> results = (from l in dateTimes where l is not null select l.Value).ToList();
List<DateTime> results = dateTimes is null ? new() : (from l in dateTimes where l is not null select l.Value).ToList();
ExifDirectoryBase? exifDirectoryBase = directories.OfType<ExifDirectoryBase>().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;
}

View File

@ -7,16 +7,16 @@ internal abstract class Container
private record FilePair(string Path, string? Directory, bool IsUnique, List<string> Collection, Models.Item Item) { }
internal static DateTime[] GetContainerDateTimes(Models.Item[] filteredItems)
internal static DateTime[] GetContainerDateTimes(IEnumerable<Models.Item> 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<DateTime>();
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<int> GetFilteredDistinct(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers)
internal static List<int> GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers)
{
List<int> results = new();
Models.Item[] filteredItems;
@ -251,4 +248,37 @@ internal abstract class Container
return results;
}
internal static List<Models.Item> GetItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers, bool distinctItems, bool filterItems)
{
List<Models.Item> results = new();
List<int> distinct = new();
IEnumerable<Models.Item> 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;
}
}

View File

@ -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<Models.Item> items) =>
GetContainerDateTimes(items);
static DateTime[] GetContainerDateTimes(IEnumerable<Models.Item> 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<int> TestStatic_GetFilteredDistinct(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) =>
GetFilteredDistinct(propertyConfiguration, containers);
static List<int> GetFilteredDistinct(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) =>
Container.GetFilteredDistinct(propertyConfiguration, containers);
List<int> TestStatic_GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) =>
GetFilteredDistinctIds(propertyConfiguration, containers);
static List<int> GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) =>
Container.GetFilteredDistinctIds(propertyConfiguration, containers);
List<Models.Item> TestStatic_GetItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers, bool distinctItems, bool filterItems) =>
GetItems(propertyConfiguration, containers, distinctItems, filterItems);
static List<Models.Item> GetItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers, bool distinctItems, bool filterItems) =>
Container.GetItems(propertyConfiguration, containers, distinctItems, filterItems);
}

View File

@ -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) =>

View File

@ -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) =>

View File

@ -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) =>

View File

@ -138,6 +138,27 @@ internal abstract class XPath
return results;
}
internal static List<string> GetDirectories(string directory)
{
List<string> 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<string> directories) Get(string rootDirectory, string sourceDirectory)
{
int result = 0;

View File

@ -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