diff --git a/.gitignore b/.gitignore
index ae27aae..6588c57 100644
--- a/.gitignore
+++ b/.gitignore
@@ -470,4 +470,7 @@ globalStorage/
Shared/.kanbn
.Immich/immich-assets.json
+Tests/.vscode/.UserSecrets/*
Instance/.vscode/.UserSecrets/*
+Drag-Drop-Set-Property-Item/.vscode/.UserSecrets/*
+TestsWithFaceRecognitionDotNet/.vscode/.UserSecrets/*
diff --git a/.vscode/mklink.md b/.vscode/mklink.md
index c086128..150885e 100644
--- a/.vscode/mklink.md
+++ b/.vscode/mklink.md
@@ -18,3 +18,14 @@ mklink /J "L:\Git\View-by-Distance-MKLink-Console\.Immich" "D:\1-Images-A\Images
mklink /J "V:\Tmp\Phares\Pictures-Results" "V:\6-Other-Large-Z\Current-Results-Test"
mklink /J "V:\1-Images-A\Images-0b793904-Results" "V:\6-Other-Large-Z\Current-Results"
```
+
+```bash 1742827407172 = 638784242071720000 = 2025-1.Spring = Mon Mar 24 2025 07:43:26 GMT-0700 (Mountain Standard Time)
+mkdir "L:\Git\View-by-Distance-MKLink-Console\Instance\.vscode"
+mklink /J "L:\Git\View-by-Distance-MKLink-Console\Instance\.vscode\.UserSecrets" "C:\Users\mikep\AppData\Roaming\Microsoft\UserSecrets\2999dda1-5329-4d9f-9d68-cccfabe0e47f"
+mkdir "L:\Git\View-by-Distance-MKLink-Console\Tests\.vscode"
+mklink /J "L:\Git\View-by-Distance-MKLink-Console\Tests\.vscode\.UserSecrets" "C:\Users\mikep\AppData\Roaming\Microsoft\UserSecrets\e8c3d25d-9715-4b35-9010-1cdc74840190"
+mkdir "L:\Git\View-by-Distance-MKLink-Console\TestsWithFaceRecognitionDotNet\.vscode"
+mklink /J "L:\Git\View-by-Distance-MKLink-Console\TestsWithFaceRecognitionDotNet\.vscode\.UserSecrets" "C:\Users\mikep\AppData\Roaming\Microsoft\UserSecrets\ecbdc76d-6037-4046-86a4-1a7626a3d342"
+mkdir "L:\Git\View-by-Distance-MKLink-Console\Drag-Drop-Set-Property-Item\.vscode"
+mklink /J "L:\Git\View-by-Distance-MKLink-Console\Drag-Drop-Set-Property-Item\.vscode\.UserSecrets" "C:\Users\mikep\AppData\Roaming\Microsoft\UserSecrets\c64a15ed-0ba3-4378-8f80-0c19d0531747"
+```
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index cc276e3..0b85cfb 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -100,6 +100,54 @@
],
"problemMatcher": "$msCompile"
},
+ {
+ "label": "buildTests",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/Tests/Tests.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "buildTestsWithFaceRecognitionDotNet",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/TestsWithFaceRecognitionDotNet/TestsWithFaceRecognitionDotNet.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "buildCopyDistinct",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/Copy-Distinct/Copy-Distinct.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "buildDragDropSetPropertyItem",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/Drag-Drop-Set-Property-Item/Drag-Drop-Set-Property-Item.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
{
"label": "File-Folder-Helper AOT s X Day-Helper-2025-03-20",
"type": "shell",
diff --git a/Container/Container.csproj b/Container/Container.csproj
index bc45f6b..ddd1afe 100644
--- a/Container/Container.csproj
+++ b/Container/Container.csproj
@@ -47,5 +47,6 @@
+
\ No newline at end of file
diff --git a/Container/Models/Stateless/Methods/Container.cs b/Container/Models/Stateless/Methods/Container.cs
index 8fae951..e3a2e6d 100644
--- a/Container/Models/Stateless/Methods/Container.cs
+++ b/Container/Models/Stateless/Methods/Container.cs
@@ -1,5 +1,4 @@
using System.Collections.ObjectModel;
-using System.Text.Json;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless.Methods;
@@ -10,7 +9,7 @@ internal abstract class Container
{
private record FilePair(bool IsUnique,
- List Collection,
+ List Collection,
FilePath FilePath,
Item Item);
@@ -48,11 +47,11 @@ internal abstract class Container
continue;
foreach (Item item in filteredItems)
{
- if (item.Property?.Id is null || item.ResizedFileHolder is null)
+ if (item.ExifDirectory?.FilePath.Id is null || item.ResizedFileHolder is null)
continue;
- if (results.Contains(item.Property.Id.Value))
+ if (results.Contains(item.ExifDirectory.FilePath.Id.Value))
continue;
- results.Add(item.Property.Id.Value);
+ results.Add(item.ExifDirectory.FilePath.Id.Value);
}
}
return results;
@@ -62,21 +61,23 @@ internal abstract class Container
{
int count;
Models.Container[] results;
+ bool useIgnoreExtensions = true;
const bool useCeilingAverage = true;
const string fileSearchFilter = "*";
IDlibDotNet dlibDotNet = GetDlibDotNet();
const string directorySearchFilter = "*";
+ ReadOnlyDictionary? exifDirectoriesById = null;
ReadOnlyDictionary>? keyValuePairs = null;
ReadOnlyCollection filesCollection = IDirectory.GetFilesCollection(propertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
- ReadOnlyCollection> filePathsCollection = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
- (count, results) = GetContainers(dlibDotNet, propertyConfiguration, propertyConfiguration.RootDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
+ ReadOnlyCollection> filePathsCollection = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection, useIgnoreExtensions);
+ (count, results) = GetContainers(dlibDotNet, propertyConfiguration, propertyConfiguration.RootDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, exifDirectoriesById, directorySearchFilter);
return (count, results);
}
private static IDlibDotNet GetDlibDotNet() =>
throw new NotImplementedException();
- private static (int, Models.Container[]) GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string filesCollectionDirectory, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, ReadOnlyCollection> filePathsCollection, string directorySearchFilter)
+ private static (int, Models.Container[]) GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string filesCollectionDirectory, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, ReadOnlyCollection> filePathsCollection, ReadOnlyDictionary? exifDirectoriesById, string directorySearchFilter)
{
List results = [];
string directory;
@@ -104,7 +105,7 @@ internal abstract class Container
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
if (!Directory.Exists(aPropertySingletonDirectory))
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
- List filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
+ List filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, exifDirectoriesById, directorySearchFilter);
foreach (FilePair filePair in filePairs)
{
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
@@ -125,463 +126,112 @@ internal abstract class Container
return (filePairs.Count, results.ToArray());
}
- internal static ReadOnlyCollection GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, ReadOnlyCollection> filePathsCollection)
- {
- Models.Container[] results;
- const string directorySearchFilter = "*";
- (_, results) = GetContainers(dlibDotNet, propertyConfiguration, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
- if (keyValuePairs is not null)
- DoGetFilePairsForRemaining(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filePathsCollection, directorySearchFilter);
- return results.AsReadOnly();
- }
-
- private static void DoGetFilePairsForRemaining(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, ReadOnlyCollection> filePathsCollection, string directorySearchFilter)
- {
- const string extension = ".json";
- (_, string bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
- IReadOnlyDictionary> fileNamesToFiles = GetFilesKeyValuePairs(filePathsCollection);
- string bMetaSingletonDirectory = Path.Combine(bResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
- if (!Directory.Exists(bMetaSingletonDirectory))
- _ = Directory.CreateDirectory(bMetaSingletonDirectory);
- _ = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, bMetaSingletonDirectory, filePathsCollection, fileNamesToFiles);
- (string cResultsFullGroupDirectory, _, string dResultsFullGroupDirectory, _) = dlibDotNet.GetResultsFullGroupDirectories("Original");
- string cResizeSingletonDirectory = Path.Combine(cResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
- if (!Directory.Exists(cResizeSingletonDirectory))
- _ = Directory.CreateDirectory(cResizeSingletonDirectory);
- _ = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, cResizeSingletonDirectory, filePathsCollection, fileNamesToFiles);
- string dFaceCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, propertyConfiguration.ResultCollection);
- if (!Directory.Exists(dFaceCollectionDirectory))
- _ = Directory.CreateDirectory(dFaceCollectionDirectory);
- _ = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, dFaceCollectionDirectory, filePathsCollection, fileNamesToFiles);
- string dFaceContentDirectory = Path.Combine(dResultsFullGroupDirectory, propertyConfiguration.ResultContent);
- if (!Directory.Exists(dFaceContentDirectory))
- _ = Directory.CreateDirectory(dFaceContentDirectory);
- AnyMovedFace(facesFileNameExtension, facesHiddenFileNameExtension, fileNamesToFiles, dFaceContentDirectory);
- AnyMovedDistance(facesFileNameExtension, fileNamesToFiles, eDistanceContentDirectory);
- }
-
- private static IReadOnlyDictionary> GetFilesKeyValuePairs(ReadOnlyCollection filesCollection)
- {
- Dictionary> results = [];
- string fileNameWithoutExtension;
- string fileNameWithoutExtensionSecond;
- string fileNameWithoutExtensionSecondMinusOne;
- List? collection;
- foreach (string[] files in filesCollection)
- {
- foreach (string file in files)
- {
- fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
- fileNameWithoutExtensionSecond = Path.GetFileNameWithoutExtension(fileNameWithoutExtension);
- if (string.IsNullOrEmpty(fileNameWithoutExtensionSecond) || fileNameWithoutExtensionSecond == fileNameWithoutExtension)
- continue;
- fileNameWithoutExtensionSecondMinusOne = fileNameWithoutExtensionSecond[..^1];
- if (!results.TryGetValue(fileNameWithoutExtensionSecondMinusOne, out collection))
- {
- results.Add(fileNameWithoutExtensionSecondMinusOne, []);
- if (!results.TryGetValue(fileNameWithoutExtensionSecondMinusOne, out collection))
- throw new Exception();
- }
- collection.Add(file);
- }
- }
- return results;
- }
-
- private static IReadOnlyDictionary> GetFilesKeyValuePairs(ReadOnlyCollection> filePathsCollection)
- {
- Dictionary> results = [];
- List? collection;
- string fileNameWithoutExtensionMinusOne;
- foreach (ReadOnlyCollection filePaths in filePathsCollection)
- {
- foreach (FilePath filePath in filePaths)
- {
- fileNameWithoutExtensionMinusOne = filePath.NameWithoutExtension[..^1];
- if (!results.TryGetValue(fileNameWithoutExtensionMinusOne, out collection))
- {
- results.Add(fileNameWithoutExtensionMinusOne, []);
- if (!results.TryGetValue(fileNameWithoutExtensionMinusOne, out collection))
- throw new Exception();
- }
- collection.Add(filePath.FullName);
- }
- }
- return results;
- }
-
- private static List GetFilePairs(IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string jsonGroupDirectory, ReadOnlyCollection> filePathsCollection, IReadOnlyDictionary> fileNamesToFiles)
- {
- List? results = null;
- int renamed;
- const bool useCeilingAverage = true;
- ReadOnlyCollection? jsonFilesCollection = null;
- IReadOnlyDictionary>? compareFileNamesToFiles = null;
- for (int i = 0; i < short.MaxValue; i++)
- {
- renamed = 0;
- jsonFilesCollection = IDirectory.GetFilesCollection(jsonGroupDirectory, directorySearchFilter, extension, useCeilingAverage);
- compareFileNamesToFiles = GetFilesKeyValuePairs(jsonFilesCollection);
- renamed += LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension);
- results = IDirectory.GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, compareFileNamesToFiles);
- renamed += IDirectory.MaybeMove(propertyConfiguration, results, jsonGroupDirectory, extension);
- if (renamed == 0)
- break;
- if (i > 10)
- throw new NotImplementedException();
- }
- if (results is null || jsonFilesCollection is null || compareFileNamesToFiles is null)
- throw new NullReferenceException(nameof(results));
- return results;
- }
-
- private static int LookForAbandoned(ReadOnlyCollection jsonFilesCollection, IReadOnlyDictionary> fileNamesToFiles, string extension)
- {
- int result;
- bool check;
- bool moved = false;
- List renameCollection = [];
- foreach (string[] files in jsonFilesCollection)
- {
- if (files.Length == 0)
- continue;
- check = AnyMoved(fileNamesToFiles, extension, renameCollection, files);
- if (!moved && check)
- moved = true;
- }
- if (renameCollection.Count > 0)
- IDirectory.MoveFiles(renameCollection, "{}", "{abd}");
- result = renameCollection.Count;
- if (moved && result == 0)
- result = 1;
- return result;
- }
-
- private static bool AnyMoved(IReadOnlyDictionary> fileNamesToFiles, string extension, List renameCollection, string[] files)
- {
- bool result = false;
- string checkFile;
- string directory;
- string fileNameWith;
- string checkDirectory;
- string directoryName;
- List? collection;
- string fileNameWithoutExtension;
- List directoryNames = [];
- string fileNameWithoutExtensionSecond;
- string fileNameWithoutExtensionSecondMinusOne;
- foreach (string file in files)
- {
- if (!file.EndsWith(extension))
- throw new Exception();
- fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
- fileNameWithoutExtensionSecond = Path.GetFileNameWithoutExtension(fileNameWithoutExtension);
- if (string.IsNullOrEmpty(fileNameWithoutExtensionSecond) || fileNameWithoutExtensionSecond == fileNameWithoutExtension)
- continue;
- fileNameWithoutExtensionSecondMinusOne = fileNameWithoutExtensionSecond[..^1];
- if (!fileNamesToFiles.TryGetValue(fileNameWithoutExtensionSecondMinusOne, out collection))
- renameCollection.Add(file);
- else
- {
- directoryNames.Clear();
- directoryName = Path.GetFileName(Path.GetDirectoryName(file)) ?? throw new Exception();
- foreach (string f in collection)
- directoryNames.Add(Path.GetFileName(Path.GetDirectoryName(f)) ?? throw new Exception());
- if (directoryNames.Count == 0 || directoryNames.Distinct().Count() != 1)
- continue;
- if (directoryName != directoryNames[0])
- {
- directory = Path.GetDirectoryName(Path.GetDirectoryName(file)) ?? throw new Exception();
- checkDirectory = Path.Combine(directory, directoryNames[0]);
- if (!Directory.Exists(checkDirectory))
- _ = Directory.CreateDirectory(checkDirectory);
- fileNameWith = collection.Count > 1 ? Path.GetFileName(file) : $"{Path.GetFileName(collection[0])}{extension}";
- checkFile = Path.Combine(checkDirectory, fileNameWith);
- if (!result)
- result = true;
- if (!File.Exists(checkFile))
- File.Move(file, checkFile);
- else
- {
- if (new FileInfo(file).LastWriteTime > new FileInfo(checkFile).LastWriteTime)
- File.Delete(file);
- else
- File.Move(file, checkFile, true);
- }
- }
- }
- }
- return result;
- }
-
- private static void AnyMovedFace(string extension, string hiddenExtension, IReadOnlyDictionary> fileNamesToFiles, string jsonGroupDirectory)
- {
- string directory;
- string checkFile;
- string directoryName;
- List files = [];
- string[] fileNameSegments;
- List directories = [];
- files.AddRange(Directory.GetFiles(jsonGroupDirectory, $"*{extension}", SearchOption.AllDirectories));
- files.AddRange(Directory.GetFiles(jsonGroupDirectory, $"*{hiddenExtension}", SearchOption.AllDirectories));
- foreach (string file in files)
- {
- directory = Path.GetDirectoryName(file) ?? throw new Exception();
- if (!directories.Contains(directory))
- directories.Add(directory);
- directoryName = Path.GetFileName(directory);
- fileNameSegments = Path.GetFileName(file).Split('.');
- if (fileNameSegments[0] != directoryName)
- {
- fileNameSegments[0] = string.Empty;
- checkFile = Path.Combine(directory, $"{directoryName}{string.Join('.', fileNameSegments)}");
- if (!File.Exists(checkFile))
- File.Move(file, checkFile);
- else
- {
- if (new FileInfo(file).LastWriteTime > new FileInfo(checkFile).LastWriteTime)
- File.Delete(file);
- else
- File.Move(file, checkFile, true);
- }
- }
- }
- if (directories.Count > 0)
- AnyMovedFace(fileNamesToFiles, directories);
- }
-
- private static void AnyMovedFace(IReadOnlyDictionary> fileNamesToFiles, List directories)
- {
- bool result = false;
- string checkFile;
- string subDirectory;
- string directoryName;
- string checkDirectory;
- List? collection;
- string directoryNameWith;
- string directoryNameMinusOne;
- List directoryNames = [];
- foreach (string directory in directories)
- {
- directoryNameMinusOne = Path.GetFileName(directory)[..^1];
- if (!fileNamesToFiles.TryGetValue(directoryNameMinusOne, out collection))
- throw new Exception();
- directoryNames.Clear();
- foreach (string f in collection)
- directoryNames.Add(Path.GetFileName(Path.GetDirectoryName(f)) ?? throw new Exception());
- if (directoryNames.Count == 0 || directoryNames.Distinct().Count() != 1)
- continue;
- directoryName = Path.GetFileName(Path.GetDirectoryName(directory)) ?? throw new Exception();
- if (directoryName != directoryNames[0])
- {
- subDirectory = Path.GetDirectoryName(Path.GetDirectoryName(directory)) ?? throw new Exception();
- checkDirectory = Path.Combine(subDirectory, directoryNames[0]);
- if (!Directory.Exists(checkDirectory))
- _ = Directory.CreateDirectory(checkDirectory);
- directoryNameWith = collection.Count > 1 ? directoryName : $"{Path.GetFileNameWithoutExtension(collection[0])}";
- checkFile = Path.Combine(checkDirectory, directoryNameWith);
- if (!result)
- result = true;
- if (!Directory.Exists(checkFile))
- Directory.Move(directory, checkFile);
- else
- {
- if (new DirectoryInfo(directory).LastWriteTime > new DirectoryInfo(checkFile).LastWriteTime)
- Directory.Delete(directory, recursive: true);
- else
- {
- Directory.Delete(checkFile, recursive: true);
- Directory.Move(directory, checkFile);
- }
- }
- }
- }
- }
-
- private static void AnyMovedDistance(string extension, IReadOnlyDictionary> fileNamesToFiles, string jsonGroupDirectory)
- {
- bool result = false;
- string fileName;
- string checkFile;
- string directory;
- List? collection;
- string[] fileNameSegments;
- List fileNames = [];
- string fileNameSegmentsZeroMinusOne;
- string[] files = Directory.GetFiles(jsonGroupDirectory, $"*{extension}", SearchOption.AllDirectories);
- foreach (string file in files)
- {
- fileName = Path.GetFileName(file);
- fileNameSegments = fileName.Split('.');
- fileNameSegmentsZeroMinusOne = fileNameSegments[0][..^1];
- if (!fileNamesToFiles.TryGetValue(fileNameSegmentsZeroMinusOne, out collection))
- continue;
- fileNames.Clear();
- foreach (string f in collection)
- fileNames.Add(Path.GetFileNameWithoutExtension(f) ?? throw new Exception());
- if (fileNames.Count == 0 || fileNames.Distinct().Count() != 1)
- continue;
- if (fileNameSegments[0] != fileNames[0])
- {
- fileNameSegments[0] = string.Empty;
- directory = Path.GetDirectoryName(file) ?? throw new Exception();
- checkFile = Path.Combine(directory, $"{fileNames[0]}{string.Join('.', fileNameSegments)}");
- if (!result)
- result = true;
- if (!File.Exists(checkFile))
- File.Move(file, checkFile);
- else
- {
- if (new FileInfo(file).LastWriteTime > new FileInfo(checkFile).LastWriteTime)
- File.Delete(file);
- else
- File.Move(file, checkFile, true);
- }
- }
- }
- }
-
- private static List GetFilePairs(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, ReadOnlyCollection> filePathsCollection, string directorySearchFilter)
+ private static List GetFilePairs(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, ReadOnlyCollection> filePathsCollection, ReadOnlyDictionary? exifDirectoriesById, string directorySearchFilter)
{
List results = [];
const string extension = ".json";
- List filePairs;
+ ReadOnlyCollection filePairs;
string jsonGroupDirectory = aPropertySingletonDirectory;
int maxDegreeOfParallelism = Environment.ProcessorCount;
int filesCollectionDirectoryLength = filesCollectionDirectory.Length;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
- IReadOnlyDictionary> fileNamesToFiles = GetFilesKeyValuePairs(filePathsCollection);
- filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, jsonGroupDirectory, filePathsCollection, fileNamesToFiles);
+ filePairs = IFilePair.GetFilePairs(propertyConfiguration, directorySearchFilter, extension, jsonGroupDirectory, filePathsCollection);
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) =>
- ParallelFor(dlibDotNet, propertyConfiguration, jsonGroupDirectory, extension, keyValuePairs, splatNineIdentifiers, filesCollectionDirectoryLength, filePairs[i], results));
+ ParallelFor(dlibDotNet, propertyConfiguration, jsonGroupDirectory, extension, keyValuePairs, splatNineIdentifiers, filesCollectionDirectoryLength, exifDirectoriesById, filePairs[i], results));
return results;
}
- private static void ParallelFor(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, int rootDirectoryLength, Shared.Models.FilePair filePair, List results)
+ private static void ParallelFor(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, int rootDirectoryLength, ReadOnlyDictionary? exifDirectoriesById, Shared.Models.FilePair filePair, List results)
{
dlibDotNet?.Tick();
bool abandoned = false;
FileHolder sourceDirectoryFileHolder;
- Property? property = GetProperty(filePair);
- FileHolder fileHolder = IFileHolder.Get(filePair.Path);
- ExifDirectory? exifDirectory = GetExifDirectory(filePair);
- FilePath filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
- bool? fileSizeChanged = property is not null ? property.FileSize != filePath.Length : null;
- bool isValidImageFormatExtension = propertyConfiguration.ValidImageFormatExtensions.Contains(filePath.ExtensionLowered);
- bool? shouldIgnore = property is null || property.Keywords is null ? null : propertyConfiguration.IgnoreRulesKeyWords.Any(l => property.Keywords.Contains(l));
- bool? isArchive = filePath.Id is null || splatNineIdentifiers is null ? null : splatNineIdentifiers.TryGetValue(filePath.Id.Value, out Identifier? identifier);
- if (property is not null && filePath.Id is not null && filePath.HasIgnoreKeyword is not null && filePath.HasDateTimeOriginal is not null)
+ if (exifDirectoriesById is null || filePair.FilePath.Id is null || !exifDirectoriesById.TryGetValue(filePair.FilePath.Id.Value, out ExifDirectory? exifDirectory))
+ exifDirectory = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(filePair.FilePath);
+ ReadOnlyCollection keywords = IMetaBase.GetKeywords(exifDirectory?.ExifBaseDirectories);
+ bool? shouldIgnore = propertyConfiguration.IgnoreRulesKeyWords.Any(keywords.Contains);
+ bool? fileSizeChanged = exifDirectory is not null ? exifDirectory.FilePath.Length != filePair.FilePath.Length : null;
+ bool isValidImageFormatExtension = propertyConfiguration.ValidImageFormatExtensions.Contains(filePair.FilePath.ExtensionLowered);
+ bool? isArchive = filePair.FilePath.Id is null || splatNineIdentifiers is null ? null : splatNineIdentifiers.TryGetValue(filePair.FilePath.Id.Value, out Identifier? identifier);
+ if (exifDirectory is not null && filePair.FilePath.Id is not null && filePair.FilePath.HasIgnoreKeyword is not null && filePair.FilePath.HasDateTimeOriginal is not null)
{
char? change;
ReadOnlyCollection? filePaths = null;
- char hasIgnoreKeyword = IId.GetHasIgnoreKeyword(filePath).ToString()[0];
- char hasDateTimeOriginal = IId.GetHasDateTimeOriginal(propertyConfiguration, filePath).ToString()[0];
- char missingDateTimeOriginal = IId.GetMissingDateTimeOriginal(propertyConfiguration, filePath).ToString()[0];
+ DateTime? dateTime = IDate.GetDateTimeOriginal(exifDirectory);
+ char hasIgnoreKeyword = IId.GetHasIgnoreKeyword(filePair.FilePath).ToString()[0];
+ char hasDateTimeOriginal = IId.GetHasDateTimeOriginal(propertyConfiguration, filePair.FilePath).ToString()[0];
+ char missingDateTimeOriginal = IId.GetMissingDateTimeOriginal(propertyConfiguration, filePair.FilePath).ToString()[0];
if (shouldIgnore is not null && shouldIgnore.Value)
{
- if (filePath.NameWithoutExtension[^1] == hasIgnoreKeyword)
+ if (filePair.FilePath.FileNameFirstSegment[^1] == hasIgnoreKeyword)
change = null;
else
{
change = hasIgnoreKeyword;
- if (keyValuePairs is null || !keyValuePairs.TryGetValue(filePath.Id.Value, out filePaths) || filePaths is null)
- throw new NotSupportedException($"Rename File! <{filePath.FileNameFirstSegment}>");
+ if (keyValuePairs is null || !keyValuePairs.TryGetValue(filePair.FilePath.Id.Value, out filePaths) || filePaths is null)
+ throw new NotSupportedException($"Rename File! <{filePair.FilePath.FileNameFirstSegment}>");
}
}
- else if ((shouldIgnore is null || !shouldIgnore.Value) && property.DateTimeOriginal is null)
+ else if ((shouldIgnore is null || !shouldIgnore.Value) && dateTime is null)
{
- if (filePath.NameWithoutExtension[^1] == missingDateTimeOriginal)
+ if (filePair.FilePath.FileNameFirstSegment[^1] == missingDateTimeOriginal)
change = null;
else
{
change = missingDateTimeOriginal;
- if (keyValuePairs is null || !keyValuePairs.TryGetValue(filePath.Id.Value, out filePaths) || filePaths is null)
- throw new NotSupportedException($"Rename File! <{filePath.FileNameFirstSegment}>");
+ if (keyValuePairs is null || !keyValuePairs.TryGetValue(filePair.FilePath.Id.Value, out filePaths) || filePaths is null)
+ throw new NotSupportedException($"Rename File! <{filePair.FilePath.FileNameFirstSegment}>");
}
}
- else if (filePath.NameWithoutExtension[^1] != hasDateTimeOriginal)
+ else if (filePair.FilePath.FileNameFirstSegment[^1] != hasDateTimeOriginal)
{
change = hasDateTimeOriginal;
- if (keyValuePairs is null || !keyValuePairs.TryGetValue(filePath.Id.Value, out filePaths) || filePaths is null)
- throw new NotSupportedException($"Rename File! <{filePath.FileNameFirstSegment}>");
+ if (keyValuePairs is null || !keyValuePairs.TryGetValue(filePair.FilePath.Id.Value, out filePaths) || filePaths is null)
+ throw new NotSupportedException($"Rename File! <{filePair.FilePath.FileNameFirstSegment}>");
}
else
change = null;
if (filePaths is not null && change is not null)
- RenameFile(extension, filePair, filePath, change.Value, filePaths);
+ RenameFile(filePair, filePair.FilePath, change.Value, filePaths);
}
- string relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(filePair.Path, rootDirectoryLength, forceExtensionToLower: true);
- bool? lastWriteTimeChanged = property is not null ? propertyConfiguration.PropertiesChangedForProperty || property.LastWriteTime.Ticks != filePath.LastWriteTicks : null;
+ string relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(filePair.FilePath.FullName, rootDirectoryLength, forceExtensionToLower: true);
+ bool? lastWriteTimeChanged = exifDirectory is not null ? propertyConfiguration.PropertiesChangedForProperty || exifDirectory.FilePath.LastWriteTicks != filePair.FilePath.LastWriteTicks : null;
if (filePair.Match is not null)
sourceDirectoryFileHolder = IFileHolder.Get(filePair.Match);
else if (!filePair.IsUnique)
sourceDirectoryFileHolder = IFileHolder.Get(Path.GetFullPath(string.Concat(jsonGroupDirectory, relativePath, extension)));
else
{
- string fileName = Path.GetFileName(filePair.Path);
- CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
+ string fileName = Path.GetFileName(filePair.FilePath.FullName);
+ CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(propertyConfiguration, filePair.FilePath);
string directory = Path.Combine(jsonGroupDirectory, cei.Combined);
string jsonFileName = $"{fileName}{extension}";
string fullFileName = Path.Combine(directory, jsonFileName);
MoveIf(jsonFileName, cei, directory, fullFileName);
sourceDirectoryFileHolder = IFileHolder.Get(fullFileName);
}
- if (sourceDirectoryFileHolder.CreationTime is not null && sourceDirectoryFileHolder.LastWriteTime is not null && filePath.LastWriteTicks != sourceDirectoryFileHolder.CreationTime.Value.Ticks)
+ if (sourceDirectoryFileHolder.CreationTime is not null && sourceDirectoryFileHolder.LastWriteTime is not null && filePair.FilePath.LastWriteTicks != sourceDirectoryFileHolder.CreationTime.Value.Ticks)
{
- File.SetCreationTime(sourceDirectoryFileHolder.FullName, new(filePath.LastWriteTicks));
+ File.SetCreationTime(sourceDirectoryFileHolder.FullName, new(filePair.FilePath.LastWriteTicks));
File.SetLastWriteTime(sourceDirectoryFileHolder.FullName, sourceDirectoryFileHolder.LastWriteTime.Value);
}
- Item item = Item.Get(filePath, sourceDirectoryFileHolder, relativePath, isArchive, filePair.IsNotUniqueAndNeedsReview, filePair.IsUnique, isValidImageFormatExtension, property, abandoned, fileSizeChanged, lastWriteTimeChanged);
+ Item item = Item.Get(filePair.FilePath, sourceDirectoryFileHolder, relativePath, isArchive, filePair.IsNotUniqueAndNeedsReview, filePair.IsUnique, isValidImageFormatExtension, exifDirectory, abandoned, fileSizeChanged, lastWriteTimeChanged);
lock (results)
- results.Add(new(filePair.IsUnique, filePair.Collection, filePath, item));
+ results.Add(new(filePair.IsUnique, filePair.Collection, filePair.FilePath, item));
}
- private static Property? GetProperty(Shared.Models.FilePair filePair)
- {
- Property? result;
- if (filePair.Match is null)
- result = null;
- else
- {
- string json = File.ReadAllText(filePair.Match);
- if (string.IsNullOrEmpty(json))
- result = null;
- else
- result = JsonSerializer.Deserialize(json, PropertyGenerationContext.Default.Property);
- }
- return result;
- }
-
- private static ExifDirectory? GetExifDirectory(Shared.Models.FilePair filePair)
- {
- ExifDirectory? result;
- if (filePair.Match is null)
- result = null;
- else
- {
- string json = File.ReadAllText(filePair.Match);
- if (string.IsNullOrEmpty(json))
- result = null;
- else
- result = JsonSerializer.Deserialize(json, ExifDirectorySourceGenerationContext.Default.ExifDirectory);
- }
- return result;
- }
-
- private static void RenameFile(string extension, Shared.Models.FilePair filePair, FilePath filePath, char change, ReadOnlyCollection filePaths)
+ private static void RenameFile(Shared.Models.FilePair filePair, FilePath filePath, char change, ReadOnlyCollection filePaths)
{
string checkFile;
if (filePath.DirectoryFullPath.Contains("Results") && filePath.DirectoryFullPath.Contains("Resize"))
File.Delete(filePath.FullName);
- if (!string.IsNullOrEmpty(filePair.Match))
+ if (filePair.Match is not null)
{
- string directory = Path.GetDirectoryName(filePair.Match) ?? throw new Exception();
- string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePair.Match);
- string fileNameWithoutExtensionSecond = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(filePair.Match));
- string extensionSecond = Path.GetExtension(fileNameWithoutExtension);
- checkFile = Path.Combine(directory, $"{fileNameWithoutExtensionSecond[..^1]}{change}{extensionSecond}{extension}");
+ string fileNameWithoutExtensionSecond = Path.GetFileNameWithoutExtension(filePair.Match.NameWithoutExtension);
+ string extensionSecond = Path.GetExtension(filePair.Match.Name);
+ checkFile = Path.Combine(filePair.Match.DirectoryFullPath, $"{fileNameWithoutExtensionSecond[..^1]}{change}{extensionSecond}{filePair.Match.ExtensionLowered}");
if (!File.Exists(checkFile))
- File.Move(filePair.Match, checkFile);
+ File.Move(filePair.Match.FullName, checkFile);
}
foreach (FilePath f in filePaths)
{
@@ -621,7 +271,7 @@ internal abstract class Container
continue;
foreach (Item item in filteredItems)
{
- if (item.Property?.Id is null || item.ResizedFileHolder is null)
+ if (item.ExifDirectory?.FilePath.Id is null || item.ResizedFileHolder is null)
continue;
if (results.Contains(item.FilePath.FileNameFirstSegment))
continue;
@@ -650,13 +300,13 @@ internal abstract class Container
}
foreach (Item item in filteredItems)
{
- if (item.Property?.Id is null || item.ResizedFileHolder is null)
+ if (item.ExifDirectory?.FilePath.Id is null || item.ResizedFileHolder is null)
continue;
if (distinctItems)
{
- if (distinct.Contains(item.Property.Id.Value))
+ if (distinct.Contains(item.ExifDirectory.FilePath.Id.Value))
continue;
- distinct.Add(item.Property.Id.Value);
+ distinct.Add(item.ExifDirectory.FilePath.Id.Value);
}
results.Add(item);
}
@@ -664,4 +314,174 @@ internal abstract class Container
return results.AsReadOnly();
}
+ internal static ReadOnlyCollection GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, ReadOnlyCollection> filePathsCollection, ReadOnlyDictionary exifDirectoriesById)
+ {
+ Models.Container[] results;
+ const string directorySearchFilter = "*";
+ (_, results) = GetContainers(dlibDotNet, propertyConfiguration, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, exifDirectoriesById, directorySearchFilter);
+ if (keyValuePairs is not null)
+ DoGetFilePairsForRemaining(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filePathsCollection, directorySearchFilter);
+ return results.AsReadOnly();
+ }
+
+ private static void DoGetFilePairsForRemaining(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, ReadOnlyCollection> filePathsCollection, string directorySearchFilter)
+ {
+ const string extension = ".json";
+ (_, string bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
+ ReadOnlyDictionary> fileNamesToFiles = FilePath.GetFilesKeyValuePairs(filePathsCollection);
+ string bMetaSingletonDirectory = Path.Combine(bResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
+ if (!Directory.Exists(bMetaSingletonDirectory))
+ _ = Directory.CreateDirectory(bMetaSingletonDirectory);
+ _ = IFilePair.GetFilePairs(propertyConfiguration, directorySearchFilter, extension, bMetaSingletonDirectory, filePathsCollection, fileNamesToFiles);
+ (string cResultsFullGroupDirectory, _, string dResultsFullGroupDirectory, _) = dlibDotNet.GetResultsFullGroupDirectories("Original");
+ string cResizeSingletonDirectory = Path.Combine(cResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
+ if (!Directory.Exists(cResizeSingletonDirectory))
+ _ = Directory.CreateDirectory(cResizeSingletonDirectory);
+ _ = IFilePair.GetFilePairs(propertyConfiguration, directorySearchFilter, extension, cResizeSingletonDirectory, filePathsCollection, fileNamesToFiles);
+ string dFaceCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, propertyConfiguration.ResultCollection);
+ if (!Directory.Exists(dFaceCollectionDirectory))
+ _ = Directory.CreateDirectory(dFaceCollectionDirectory);
+ _ = IFilePair.GetFilePairs(propertyConfiguration, directorySearchFilter, extension, dFaceCollectionDirectory, filePathsCollection, fileNamesToFiles);
+ string dFaceContentDirectory = Path.Combine(dResultsFullGroupDirectory, propertyConfiguration.ResultContent);
+ if (!Directory.Exists(dFaceContentDirectory))
+ _ = Directory.CreateDirectory(dFaceContentDirectory);
+ AnyMovedFace(propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, fileNamesToFiles, dFaceContentDirectory);
+ AnyMovedDistance(propertyConfiguration, facesFileNameExtension, fileNamesToFiles, eDistanceContentDirectory);
+ }
+
+ private static void AnyMovedFace(IPropertyConfiguration propertyConfiguration, string extension, string hiddenExtension, IReadOnlyDictionary> fileNamesToFiles, string jsonGroupDirectory)
+ {
+ string directory;
+ string checkFile;
+ string directoryName;
+ List files = [];
+ string[] fileNameSegments;
+ List directories = [];
+ files.AddRange(Directory.GetFiles(jsonGroupDirectory, $"*{extension}", SearchOption.AllDirectories));
+ files.AddRange(Directory.GetFiles(jsonGroupDirectory, $"*{hiddenExtension}", SearchOption.AllDirectories));
+ foreach (string file in files)
+ {
+ directory = Path.GetDirectoryName(file) ?? throw new Exception();
+ if (!directories.Contains(directory))
+ directories.Add(directory);
+ directoryName = Path.GetFileName(directory);
+ fileNameSegments = Path.GetFileName(file).Split('.');
+ if (fileNameSegments[0] != directoryName)
+ {
+ fileNameSegments[0] = string.Empty;
+ checkFile = Path.Combine(directory, $"{directoryName}{string.Join('.', fileNameSegments)}");
+ if (!File.Exists(checkFile))
+ File.Move(file, checkFile);
+ else
+ {
+ if (new FileInfo(file).LastWriteTime > new FileInfo(checkFile).LastWriteTime)
+ File.Delete(file);
+ else
+ File.Move(file, checkFile, true);
+ }
+ }
+ }
+ if (directories.Count > 0)
+ AnyMovedFace(propertyConfiguration, fileNamesToFiles, directories);
+ }
+
+ private static void AnyMovedFace(IPropertyConfiguration propertyConfiguration, IReadOnlyDictionary> fileNamesToFiles, List directories)
+ {
+ bool result = false;
+ string checkFile;
+ FilePath filePath;
+ string subDirectory;
+ string directoryName;
+ string checkDirectory;
+ FileHolder fileHolder;
+ string directoryNameWith;
+ List? collection;
+ List directoryNames = [];
+ foreach (string directory in directories)
+ {
+ fileHolder = IFileHolder.Get(Path.GetFileName(directory));
+ filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
+ if (filePath.Id is null)
+ continue;
+ if (!fileNamesToFiles.TryGetValue(filePath.Id.Value, out collection))
+ throw new Exception();
+ directoryNames.Clear();
+ foreach (FilePath f in collection)
+ directoryNames.Add(Path.GetFileName(f.DirectoryFullPath) ?? throw new Exception());
+ if (directoryNames.Count == 0 || directoryNames.Distinct().Count() != 1)
+ continue;
+ directoryName = Path.GetFileName(Path.GetDirectoryName(directory)) ?? throw new Exception();
+ if (directoryName != directoryNames[0])
+ {
+ subDirectory = Path.GetDirectoryName(Path.GetDirectoryName(directory)) ?? throw new Exception();
+ checkDirectory = Path.Combine(subDirectory, directoryNames[0]);
+ if (!Directory.Exists(checkDirectory))
+ _ = Directory.CreateDirectory(checkDirectory);
+ directoryNameWith = collection.Count > 1 ? directoryName : $"{collection[0].NameWithoutExtension}";
+ checkFile = Path.Combine(checkDirectory, directoryNameWith);
+ if (!result)
+ result = true;
+ if (!Directory.Exists(checkFile))
+ Directory.Move(directory, checkFile);
+ else
+ {
+ if (new DirectoryInfo(directory).LastWriteTime > new DirectoryInfo(checkFile).LastWriteTime)
+ Directory.Delete(directory, recursive: true);
+ else
+ {
+ Directory.Delete(checkFile, recursive: true);
+ Directory.Move(directory, checkFile);
+ }
+ }
+ }
+ }
+ }
+
+ private static void AnyMovedDistance(IPropertyConfiguration propertyConfiguration, string extension, IReadOnlyDictionary> fileNamesToFiles, string jsonGroupDirectory)
+ {
+ bool result = false;
+ string checkFile;
+ string directory;
+ FilePath filePath;
+ FileHolder fileHolder;
+ string[] fileNameSegments;
+ List? collection;
+ List fileNames = [];
+ string[] files = Directory.GetFiles(jsonGroupDirectory, $"*{extension}", SearchOption.AllDirectories);
+ foreach (string file in files)
+ {
+ fileHolder = IFileHolder.Get(file);
+ if (!fileHolder.Exists)
+ continue;
+ filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
+ if (filePath.Id is null)
+ continue;
+ fileNameSegments = filePath.Name.Split('.');
+ if (!fileNamesToFiles.TryGetValue(filePath.Id.Value, out collection))
+ continue;
+ fileNames.Clear();
+ foreach (FilePath f in collection)
+ fileNames.Add(f.NameWithoutExtension ?? throw new Exception());
+ if (fileNames.Count == 0 || fileNames.Distinct().Count() != 1)
+ continue;
+ if (filePath.FileNameFirstSegment != fileNames[0])
+ {
+ fileNameSegments[0] = string.Empty;
+ directory = Path.GetDirectoryName(file) ?? throw new Exception();
+ checkFile = Path.Combine(directory, $"{fileNames[0]}{string.Join('.', fileNameSegments)}");
+ if (!result)
+ result = true;
+ if (!File.Exists(checkFile))
+ File.Move(file, checkFile);
+ else
+ {
+ if (new FileInfo(file).LastWriteTime > new FileInfo(checkFile).LastWriteTime)
+ File.Delete(file);
+ else
+ File.Move(file, checkFile, true);
+ }
+ }
+ }
+ }
+
}
\ No newline at end of file
diff --git a/Container/Models/Stateless/Methods/IContainer.cs b/Container/Models/Stateless/Methods/IContainer.cs
index 1d3752a..d5169ac 100644
--- a/Container/Models/Stateless/Methods/IContainer.cs
+++ b/Container/Models/Stateless/Methods/IContainer.cs
@@ -29,8 +29,8 @@ public interface IContainer
public static ReadOnlyCollection- GetValidImageItems(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection containers, bool distinctItems, bool filterItems) =>
Container.GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
- public static ReadOnlyCollection GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, ReadOnlyCollection> filePathsCollection) =>
- Container.GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection);
+ public static ReadOnlyCollection GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, ReadOnlyCollection> filePathsCollection, ReadOnlyDictionary exifDirectoriesById) =>
+ Container.GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, exifDirectoriesById);
internal DateTime[] TestStatic_GetContainerDateTimes(ReadOnlyCollection
- items) =>
GetContainerDateTimes(items);
@@ -53,7 +53,7 @@ public interface IContainer
internal (int, Models.Container[]) TestStatic_GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary? splatNineIdentifiers, string aPropertySingletonDirectory) =>
GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
- internal ReadOnlyCollection TestStatic_GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, ReadOnlyCollection> filePathsCollection) =>
- GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection);
+ internal ReadOnlyCollection TestStatic_GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary>? keyValuePairs, ReadOnlyDictionary? splatNineIdentifiers, ReadOnlyCollection> filePathsCollection, ReadOnlyDictionary exifDirectoriesById) =>
+ GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, exifDirectoriesById);
}
\ No newline at end of file
diff --git a/Copy-Distinct/CopyDistinct.cs b/Copy-Distinct/CopyDistinct.cs
index dc53d50..2785c76 100644
--- a/Copy-Distinct/CopyDistinct.cs
+++ b/Copy-Distinct/CopyDistinct.cs
@@ -1,4 +1,4 @@
-using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Phares.Shared;
using ShellProgressBar;
@@ -19,7 +19,7 @@ public class CopyDistinct
private readonly IsEnvironment _IsEnvironment;
private readonly IConfigurationRoot _ConfigurationRoot;
private readonly Property.Models.Configuration _PropertyConfiguration;
- private readonly ReadOnlyDictionary>> _FileGroups;
+ private readonly ReadOnlyDictionary> _FileGroups;
public CopyDistinct(List args, ILogger logger, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{
@@ -37,7 +37,9 @@ public class CopyDistinct
_Configuration = configuration;
logger?.LogInformation(propertyConfiguration.RootDirectory);
(bool move, ReadOnlyCollection filesCollection, bool anyLenFiles, bool moveBack) = Verify();
- _FileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, appSettings.CopyTo, [appSettings.ResultDirectoryKey]);
+ ReadOnlyDictionary>> keyValuePairs =
+ Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, appSettings.CopyTo, [appSettings.ResultDirectoryKey]);
+ _FileGroups = keyValuePairs[appSettings.ResultDirectoryKey];
List lines = CopyDistinctFilesInDirectories(logger, move, filesCollection, anyLenFiles, moveBack);
if (lines.Count != 0)
File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines);
@@ -93,6 +95,76 @@ public class CopyDistinct
return (move, new(filesCollection), anyLenFiles, moveBack);
}
+ private List CopyDistinctFilesInDirectories(ILogger? logger, bool move, ReadOnlyCollection filesCollection, bool anyLenFiles, bool moveBack)
+ {
+ List results = [];
+ ProgressBar progressBar;
+ string[] distinctDirectories;
+ ConsoleKey? consoleKey = null;
+ string message = nameof(CopyDistinct);
+ List<(FilePath, string)> toDoCollection;
+ int count = filesCollection.Select(l => l.Length).Sum();
+ ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
+ if (moveBack)
+ {
+ if (!anyLenFiles)
+ throw new NotSupportedException();
+ (distinctDirectories, toDoCollection) = GetMoveBackToDoCollection(_PropertyConfiguration, filesCollection);
+ }
+ else
+ {
+ progressBar = new(count, message, options);
+ string key = string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey) ? _PropertyConfiguration.ResultAllInOne : _AppSettings.ResultDirectoryKey;
+ if (key != _PropertyConfiguration.ResultContent)
+ throw new NotImplementedException("Changed but didn't update!");
+ ReadOnlyCollection> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollection, useIgnoreExtensions: true);
+ (distinctDirectories, toDoCollection) = IDirectory.GetToDoCollection(_PropertyConfiguration, _AppSettings.CopyDuplicates, _AppSettings.IfCanUseId, filePathsCollection, _FileGroups, () => progressBar.Tick());
+ progressBar.Dispose();
+ }
+ foreach (string distinctDirectory in distinctDirectories)
+ {
+ if (!Directory.Exists(distinctDirectory))
+ _ = Directory.CreateDirectory(distinctDirectory);
+ }
+ if (move)
+ logger?.LogInformation($"Ready to Move {toDoCollection.Count} file(s)?");
+ else if (!moveBack)
+ logger?.LogInformation($"Ready to Copy {toDoCollection.Count} file(s)?");
+ else
+ logger?.LogInformation($"Ready to Move back {toDoCollection.Count} file(s)?");
+ for (int y = 0; y < int.MaxValue; y++)
+ {
+ if (move)
+ logger?.LogInformation("Press \"Y\" key to move file(s), \"N\" key to log file(s) or close console to not move files");
+ else if (!moveBack)
+ logger?.LogInformation("Press \"Y\" key to copy file(s), \"N\" key to log file(s) or close console to not copy files");
+ else
+ logger?.LogInformation("Press \"Y\" key to move back file(s), \"N\" key to log file(s) or close console to not move back files");
+ consoleKey = System.Console.ReadKey().Key;
+ if (consoleKey is ConsoleKey.Y or ConsoleKey.N)
+ break;
+ }
+ logger?.LogInformation(". . .");
+ if (consoleKey is null || consoleKey.Value != ConsoleKey.Y)
+ {
+ if (move || moveBack)
+ logger?.LogInformation("Nothing moved!");
+ else
+ logger?.LogInformation("Nothing copied!");
+ }
+ else
+ {
+ progressBar = new(count, message, options);
+ results.AddRange(IDirectory.CopyOrMove(toDoCollection, move, moveBack, () => progressBar.Tick()));
+ progressBar.Dispose();
+ if (move || moveBack)
+ logger?.LogInformation("Done moving");
+ else
+ logger?.LogInformation("Done copying");
+ }
+ return results;
+ }
+
private static (string[], List<(FilePath, string)>) GetMoveBackToDoCollection(Property.Models.Configuration propertyConfiguration, ReadOnlyCollection filesCollection)
{
List<(FilePath, string)> results = [];
@@ -159,74 +231,4 @@ public class CopyDistinct
return (distinctDirectories.ToArray(), results);
}
- private List CopyDistinctFilesInDirectories(ILogger? logger, bool move, ReadOnlyCollection filesCollection, bool anyLenFiles, bool moveBack)
- {
- List results = [];
- ProgressBar progressBar;
- string[] distinctDirectories;
- ConsoleKey? consoleKey = null;
- string message = nameof(CopyDistinct);
- List<(FilePath, string)> toDoCollection;
- int count = filesCollection.Select(l => l.Length).Sum();
- ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
- if (moveBack)
- {
- if (!anyLenFiles)
- throw new NotSupportedException();
- (distinctDirectories, toDoCollection) = GetMoveBackToDoCollection(_PropertyConfiguration, filesCollection);
- }
- else
- {
- progressBar = new(count, message, options);
- string key = string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey) ? _PropertyConfiguration.ResultAllInOne : _AppSettings.ResultDirectoryKey;
- if (key != _PropertyConfiguration.ResultContent)
- throw new NotImplementedException("Changed but didn't update!");
- ReadOnlyCollection> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollection);
- (distinctDirectories, toDoCollection) = IDirectory.GetToDoCollection(_PropertyConfiguration, _AppSettings.CopyDuplicates, _AppSettings.IfCanUseId, filePathsCollection, _FileGroups, () => progressBar.Tick());
- progressBar.Dispose();
- }
- foreach (string distinctDirectory in distinctDirectories)
- {
- if (!Directory.Exists(distinctDirectory))
- _ = Directory.CreateDirectory(distinctDirectory);
- }
- if (move)
- logger?.LogInformation($"Ready to Move {toDoCollection.Count} file(s)?");
- else if (!moveBack)
- logger?.LogInformation($"Ready to Copy {toDoCollection.Count} file(s)?");
- else
- logger?.LogInformation($"Ready to Move back {toDoCollection.Count} file(s)?");
- for (int y = 0; y < int.MaxValue; y++)
- {
- if (move)
- logger?.LogInformation("Press \"Y\" key to move file(s), \"N\" key to log file(s) or close console to not move files");
- else if (!moveBack)
- logger?.LogInformation("Press \"Y\" key to copy file(s), \"N\" key to log file(s) or close console to not copy files");
- else
- logger?.LogInformation("Press \"Y\" key to move back file(s), \"N\" key to log file(s) or close console to not move back files");
- consoleKey = System.Console.ReadKey().Key;
- if (consoleKey is ConsoleKey.Y or ConsoleKey.N)
- break;
- }
- logger?.LogInformation(". . .");
- if (consoleKey is null || consoleKey.Value != ConsoleKey.Y)
- {
- if (move || moveBack)
- logger?.LogInformation("Nothing moved!");
- else
- logger?.LogInformation("Nothing copied!");
- }
- else
- {
- progressBar = new(count, message, options);
- results.AddRange(IDirectory.CopyOrMove(toDoCollection, move, moveBack, () => progressBar.Tick()));
- progressBar.Dispose();
- if (move || moveBack)
- logger?.LogInformation("Done moving");
- else
- logger?.LogInformation("Done copying");
- }
- return results;
- }
-
}
\ No newline at end of file
diff --git a/Date-Group/DateGroup.cs b/Date-Group/DateGroup.cs
index 3075263..9460b51 100644
--- a/Date-Group/DateGroup.cs
+++ b/Date-Group/DateGroup.cs
@@ -1,4 +1,4 @@
-using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Phares.Shared;
using System.Globalization;
@@ -96,203 +96,6 @@ public class DateGroup
throw new Exception("Change configuration!");
}
- private static bool WriteAllText(string path, string contents, bool compareBeforeWrite)
- {
- bool result;
- string text;
- if (!compareBeforeWrite)
- result = true;
- else
- {
- if (!File.Exists(path))
- text = string.Empty;
- else
- text = File.ReadAllText(path);
- result = text != contents;
- }
- if (result)
- {
- if (path.Contains("()"))
- File.WriteAllText(path, contents);
- else if (path.Contains("{}") && !path.EndsWith(".json"))
- File.WriteAllText(path, contents);
- else if (path.Contains("[]") && !path.EndsWith(".json"))
- File.WriteAllText(path, contents);
- else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
- File.WriteAllText(path, contents);
- else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
- File.WriteAllText(path, contents);
- else
- File.WriteAllText(path, contents);
- }
- return result;
- }
-
- private List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> GetMoveFileCollection(string destinationDirectory, string topDirectory, Item[] filteredItems)
- {
- List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> results = [];
- char flag;
- string day;
- int season;
- string year;
- string month;
- string? check;
- string fileName;
- string? pathRoot;
- DateTime dateTime;
- string seasonName;
- string weekOfYear;
- bool? isWrongYear;
- string seasonValue;
- string directoryName;
- string topDirectoryName;
- List dateTimes;
- string[]? matches = null;
- string[] directorySegments;
- List destinationCollection;
- List directoryNames = [];
- List topDirectorySegments = [];
- StringBuilder destinationDirectoryName = new();
- Calendar calendar = new CultureInfo("en-US").Calendar;
- for (int z = 1; z < 3; z++)
- {
- if (z == 1)
- {
- check = Path.Combine(destinationDirectory, ".");
- pathRoot = Path.GetPathRoot(destinationDirectory);
- }
- else if (z == 2)
- {
- check = Path.Combine(topDirectory, ".");
- pathRoot = Path.GetPathRoot(topDirectory);
- }
- else
- throw new Exception();
- if (string.IsNullOrEmpty(pathRoot))
- continue;
- for (int i = 0; i < int.MaxValue; i++)
- {
- check = Path.GetDirectoryName(check);
- if (string.IsNullOrEmpty(check) || check == pathRoot)
- break;
- directoryName = Path.GetFileName(check);
- directorySegments = directoryName.Split(' ');
- topDirectorySegments.AddRange(directorySegments);
- (_, matches) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(directorySegments, string.Empty);
- if (matches.Length != 0)
- break;
- }
- if (matches is not null && matches.Length != 0)
- break;
- }
- foreach (Item item in filteredItems)
- {
- directoryNames.Clear();
- destinationCollection = [];
- _ = destinationDirectoryName.Clear();
- if (item.Property is not null)
- dateTimes = item.Property.GetDateTimes();
- else
- dateTimes = [new(item.FilePath.LastWriteTicks)];
- if (item.Property is not null && item.Property.DateTimeOriginal is not null)
- dateTime = item.Property.DateTimeOriginal.Value;
- else if (item.Property is null)
- dateTime = new(item.FilePath.LastWriteTicks);
- else
- dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
- day = dateTime.ToString("MM-dd");
- month = dateTime.ToString("MMMM");
- if (item.Property?.Id is null)
- {
- flag = '#';
- isWrongYear = null;
- }
- else
- {
- (isWrongYear, _) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(item.FilePath, item.Property.DateTimeOriginal, dateTimes);
- if (isWrongYear is null)
- flag = '#';
- else if (isWrongYear.Value)
- flag = '~';
- else
- {
- if (item.Property.DateTimeOriginal is not null && dateTime.DayOfYear != item.Property.DateTimeOriginal.Value.DayOfYear && Math.Abs(new TimeSpan(dateTime.Ticks - item.Property.DateTimeOriginal.Value.Ticks).TotalHours) > 8)
- flag = '^';
- else
- flag = '=';
- }
- }
- (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
- if ((from l in topDirectorySegments where l == "Christmas" select true).Any())
- seasonValue = string.Empty;
- else
- seasonValue = $".{season}";
- if (isWrongYear is null || !isWrongYear.Value)
- year = $"{flag}{dateTime:yyyy}{seasonValue}";
- else if (matches is null || matches.Length < 3)
- year = "----";
- else
- {
- if (matches[0][0] != '~')
- year = $"{flag}{matches[0].Split('.')[0]}{seasonValue}";
- else
- year = $"{flag}{matches[0][1..].Split('.')[0]}{seasonValue}";
- }
- topDirectoryName = Path.GetFileName(topDirectory);
- weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
- if (_Configuration.ByHash)
- directoryNames.Add($"{year} {seasonName}");
- else if (_Configuration.BySeason && topDirectoryName.Length == 1 && topDirectoryName[0] == '_')
- directoryNames.Add($"{year} {seasonName}");
- else
- {
- if (!_Configuration.KeepFullPath)
- {
- if (topDirectoryName.Length > 1)
- _ = destinationDirectoryName.Append(topDirectoryName);
- if (_Configuration.BySeason)
- directoryNames.AddRange([$"{destinationDirectoryName} {year} {seasonName}"]);
- else if (_Configuration.ByDay)
- directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year}-{day}"]);
- else if (_Configuration.ByWeek)
- directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year} {month}"]);
- else
- throw new Exception();
- }
- else
- {
- foreach (string sourceDirectoryNameSegment in topDirectorySegments)
- {
- if (matches is not null && matches.Contains(sourceDirectoryNameSegment))
- _ = destinationDirectoryName.Append(year);
- else
- _ = destinationDirectoryName.Append(sourceDirectoryNameSegment);
- }
- if (_Configuration.BySeason)
- directoryNames.Add($"{year} {seasonName}");
- else if (_Configuration.ByDay)
- directoryNames.Add($"{weekOfYear}) {year} {day}");
- else if (_Configuration.ByWeek)
- directoryNames.Add($"{weekOfYear}) {month} {year}");
- else
- throw new Exception();
- }
- }
- if (!_Configuration.ByHash || item.Property?.Id is null)
- fileName = item.FilePath.Name;
- else
- fileName = $"{item.Property.Id.Value}{item.FilePath.ExtensionLowered}";
- destinationCollection.Add(destinationDirectory);
- destinationCollection.AddRange(directoryNames);
- destinationCollection.Add(fileName);
- if (item.Property is null)
- results.Add(new(item, item.FilePath.LastWriteTicks, dateTime.Ticks, destinationCollection.ToArray()));
- else
- results.Add(new(item, item.Property.LastWriteTime.Ticks, dateTime.Ticks, destinationCollection.ToArray()));
- }
- return results;
- }
-
private A_Property GetPropertyLogic(bool reverse, string outputExtension, string aResultsFullGroupDirectory)
{
A_Property result;
@@ -302,54 +105,64 @@ public class DateGroup
return result;
}
- private static Item[] GetFilterItems(Container.Models.Container container)
+ private static void CreateDateShortcut(Property.Models.Configuration configuration, Container.Models.Container[] containers)
{
- List
- results = [];
- foreach (Item item in container.Items)
- {
- if (item.FilePath is not null)
- results.Add(item);
- }
- return results.ToArray();
- }
-
- private (Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] GetFileMoveCollectionAll(Property.Models.Configuration configuration, string destinationRoot, Container.Models.Container[] containers)
- {
- (Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] results;
- Item[] filteredItems;
- string? topDirectory;
- string? checkDirectory;
- string destinationDirectory;
- List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollection = [];
- List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollectionDirectory;
+ string path;
+ string fileName;
+ string directory;
+ DateTime dateTime;
+ int selectedTotal;
+ const int minimum = 3;
+ List dateTimes;
+ List
- selectedItems;
+ const int maximumHours = 24;
+ string? relativePathDirectory;
+ WindowsShortcut windowsShortcut;
+ TimeSpan threeStandardDeviationHigh;
+ string aPropertyContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "()");
foreach (Container.Models.Container container in containers)
{
if (container.Items.Count == 0)
continue;
- if (!_Configuration.KeepFullPath)
- destinationDirectory = destinationRoot;
- else
- destinationDirectory = string.Concat(destinationRoot, container.SourceDirectory[configuration.RootDirectory.Length..]);
- checkDirectory = Path.GetFullPath(container.SourceDirectory);
- for (int z = 0; z < int.MaxValue; z++)
+ selectedTotal = 0;
+ threeStandardDeviationHigh = Property.Models.Stateless.IProperty.GetThreeStandardDeviationHigh(minimum, container);
+ if (threeStandardDeviationHigh.TotalHours > maximumHours)
+ threeStandardDeviationHigh = new(maximumHours, 0, 0);
+ for (int i = 0; i < container.Items.Count; i++)
{
- if (checkDirectory == configuration.RootDirectory)
- break;
- checkDirectory = Path.GetDirectoryName(checkDirectory);
- if (string.IsNullOrEmpty(checkDirectory))
- break;
+ (i, dateTimes, selectedItems) = Property.Models.Stateless.IProperty.Get(container, threeStandardDeviationHigh, i);
+ selectedTotal += selectedItems.Count;
+ foreach (Item item in selectedItems)
+ {
+ if (item.ExifDirectory is null)
+ continue;
+ relativePathDirectory = Path.GetDirectoryName(item.RelativePath);
+ if (string.IsNullOrEmpty(relativePathDirectory))
+ continue;
+ if (item.ExifDirectory is null)
+ dateTime = new(item.FilePath.LastWriteTicks);
+ else if (item.ExifDirectory is not null && item.ExifDirectory.DateTimeOriginal is not null)
+ dateTime = item.ExifDirectory.DateTimeOriginal.Value;
+ else
+ dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.ExifDirectory);
+ path = Path.GetFullPath($"{configuration.RootDirectory}{item.RelativePath[..^5]}");
+ directory = Path.Combine($"{aPropertyContentDirectory}{relativePathDirectory}", $"{dateTimes.Min():yyyy-MM-dd_HH-mm-ss}---{dateTimes.Max():yyyy-MM-dd_HH-mm-ss}");
+ if (!Directory.Exists(directory))
+ _ = Directory.CreateDirectory(directory);
+ fileName = Path.Combine(directory, $"{Path.GetFileName(item.RelativePath[..^5])}.lnk");
+ if (File.Exists(fileName))
+ continue;
+ windowsShortcut = new() { Path = path };
+ windowsShortcut.Save(fileName);
+ windowsShortcut.Dispose();
+ if (!File.Exists(fileName))
+ continue;
+ File.SetLastWriteTime(fileName, dateTime);
+ }
}
- if (string.IsNullOrEmpty(checkDirectory))
+ if (selectedTotal < container.Items.Count && selectedTotal < (from l in container.Items where l.Property is not null select true).Count())
continue;
- topDirectory = checkDirectory;
- filteredItems = GetFilterItems(container);
- if (filteredItems.Length == 0)
- continue;
- fileMoveCollectionDirectory = GetMoveFileCollection(destinationDirectory, topDirectory, filteredItems);
- fileMoveCollection.AddRange(fileMoveCollectionDirectory);
}
- results = (from l in fileMoveCollection orderby l.MinimumDateTimeTicks descending, l.LastWriteTimeTicks descending select l).ToArray();
- return results;
}
private void MoveFiles(Property.Models.Configuration configuration, string destinationRoot, Container.Models.Container[] containers)
@@ -453,64 +266,251 @@ public class DateGroup
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(configuration.RootDirectory);
}
- private static void CreateDateShortcut(Property.Models.Configuration configuration, Container.Models.Container[] containers)
+ private (Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] GetFileMoveCollectionAll(Property.Models.Configuration configuration, string destinationRoot, Container.Models.Container[] containers)
{
- string path;
- string fileName;
- string directory;
- DateTime dateTime;
- int selectedTotal;
- const int minimum = 3;
- List dateTimes;
- List
- selectedItems;
- const int maximumHours = 24;
- string? relativePathDirectory;
- WindowsShortcut windowsShortcut;
- TimeSpan threeStandardDeviationHigh;
- string aPropertyContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "()");
+ (Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] results;
+ Item[] filteredItems;
+ string? topDirectory;
+ string? checkDirectory;
+ string destinationDirectory;
+ List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollection = [];
+ List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollectionDirectory;
foreach (Container.Models.Container container in containers)
{
if (container.Items.Count == 0)
continue;
- selectedTotal = 0;
- threeStandardDeviationHigh = Property.Models.Stateless.IProperty.GetThreeStandardDeviationHigh(minimum, container);
- if (threeStandardDeviationHigh.TotalHours > maximumHours)
- threeStandardDeviationHigh = new(maximumHours, 0, 0);
- for (int i = 0; i < container.Items.Count; i++)
+ if (!_Configuration.KeepFullPath)
+ destinationDirectory = destinationRoot;
+ else
+ destinationDirectory = string.Concat(destinationRoot, container.SourceDirectory[configuration.RootDirectory.Length..]);
+ checkDirectory = Path.GetFullPath(container.SourceDirectory);
+ for (int z = 0; z < int.MaxValue; z++)
{
- (i, dateTimes, selectedItems) = Property.Models.Stateless.IProperty.Get(container, threeStandardDeviationHigh, i);
- selectedTotal += selectedItems.Count;
- foreach (Item item in selectedItems)
+ if (checkDirectory == configuration.RootDirectory)
+ break;
+ checkDirectory = Path.GetDirectoryName(checkDirectory);
+ if (string.IsNullOrEmpty(checkDirectory))
+ break;
+ }
+ if (string.IsNullOrEmpty(checkDirectory))
+ continue;
+ topDirectory = checkDirectory;
+ filteredItems = GetFilterItems(container);
+ if (filteredItems.Length == 0)
+ continue;
+ fileMoveCollectionDirectory = GetMoveFileCollection(destinationDirectory, topDirectory, filteredItems);
+ fileMoveCollection.AddRange(fileMoveCollectionDirectory);
+ }
+ results = (from l in fileMoveCollection orderby l.MinimumDateTimeTicks descending, l.LastWriteTimeTicks descending select l).ToArray();
+ return results;
+ }
+
+ private static Item[] GetFilterItems(Container.Models.Container container)
+ {
+ List
- results = [];
+ foreach (Item item in container.Items)
+ {
+ if (item.FilePath is not null)
+ results.Add(item);
+ }
+ return results.ToArray();
+ }
+
+ private List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> GetMoveFileCollection(string destinationDirectory, string topDirectory, Item[] filteredItems)
+ {
+ List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> results = [];
+ char flag;
+ string day;
+ int season;
+ string year;
+ string month;
+ string? check;
+ string fileName;
+ string? pathRoot;
+ DateTime dateTime;
+ string seasonName;
+ string weekOfYear;
+ bool? isWrongYear;
+ string seasonValue;
+ string directoryName;
+ string topDirectoryName;
+ List dateTimes;
+ string[]? matches = null;
+ string[] directorySegments;
+ List destinationCollection;
+ List directoryNames = [];
+ List topDirectorySegments = [];
+ StringBuilder destinationDirectoryName = new();
+ Calendar calendar = new CultureInfo("en-US").Calendar;
+ for (int z = 1; z < 3; z++)
+ {
+ if (z == 1)
+ {
+ check = Path.Combine(destinationDirectory, ".");
+ pathRoot = Path.GetPathRoot(destinationDirectory);
+ }
+ else if (z == 2)
+ {
+ check = Path.Combine(topDirectory, ".");
+ pathRoot = Path.GetPathRoot(topDirectory);
+ }
+ else
+ throw new Exception();
+ if (string.IsNullOrEmpty(pathRoot))
+ continue;
+ for (int i = 0; i < int.MaxValue; i++)
+ {
+ check = Path.GetDirectoryName(check);
+ if (string.IsNullOrEmpty(check) || check == pathRoot)
+ break;
+ directoryName = Path.GetFileName(check);
+ directorySegments = directoryName.Split(' ');
+ topDirectorySegments.AddRange(directorySegments);
+ (_, matches) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(directorySegments, string.Empty);
+ if (matches.Length != 0)
+ break;
+ }
+ if (matches is not null && matches.Length != 0)
+ break;
+ }
+ foreach (Item item in filteredItems)
+ {
+ directoryNames.Clear();
+ destinationCollection = [];
+ _ = destinationDirectoryName.Clear();
+ if (item.ExifDirectory is not null)
+ dateTimes = item.ExifDirectory.GetDateTimes();
+ else
+ dateTimes = [new(item.FilePath.LastWriteTicks)];
+ if (item.ExifDirectory is not null && item.ExifDirectory.DateTimeOriginal is not null)
+ dateTime = item.ExifDirectory.DateTimeOriginal.Value;
+ else if (item.ExifDirectory is null)
+ dateTime = new(item.FilePath.LastWriteTicks);
+ else
+ dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.ExifDirectory);
+ day = dateTime.ToString("MM-dd");
+ month = dateTime.ToString("MMMM");
+ if (item.ExifDirectory?.FilePath.Id is null)
+ {
+ flag = '#';
+ isWrongYear = null;
+ }
+ else
+ {
+ (isWrongYear, _) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(item.FilePath, item.ExifDirectory.DateTimeOriginal, dateTimes);
+ if (isWrongYear is null)
+ flag = '#';
+ else if (isWrongYear.Value)
+ flag = '~';
+ else
{
- if (item.Property is null)
- continue;
- relativePathDirectory = Path.GetDirectoryName(item.RelativePath);
- if (string.IsNullOrEmpty(relativePathDirectory))
- continue;
- if (item.Property is null)
- dateTime = new(item.FilePath.LastWriteTicks);
- else if (item.Property is not null && item.Property.DateTimeOriginal is not null)
- dateTime = item.Property.DateTimeOriginal.Value;
+ if (item.ExifDirectory.DateTimeOriginal is not null && dateTime.DayOfYear != item.ExifDirectory.DateTimeOriginal.Value.DayOfYear && Math.Abs(new TimeSpan(dateTime.Ticks - item.ExifDirectory.DateTimeOriginal.Value.Ticks).TotalHours) > 8)
+ flag = '^';
else
- dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
- path = Path.GetFullPath($"{configuration.RootDirectory}{item.RelativePath[..^5]}");
- directory = Path.Combine($"{aPropertyContentDirectory}{relativePathDirectory}", $"{dateTimes.Min():yyyy-MM-dd_HH-mm-ss}---{dateTimes.Max():yyyy-MM-dd_HH-mm-ss}");
- if (!Directory.Exists(directory))
- _ = Directory.CreateDirectory(directory);
- fileName = Path.Combine(directory, $"{Path.GetFileName(item.RelativePath[..^5])}.lnk");
- if (File.Exists(fileName))
- continue;
- windowsShortcut = new() { Path = path };
- windowsShortcut.Save(fileName);
- windowsShortcut.Dispose();
- if (!File.Exists(fileName))
- continue;
- File.SetLastWriteTime(fileName, dateTime);
+ flag = '=';
}
}
- if (selectedTotal < container.Items.Count && selectedTotal < (from l in container.Items where l.Property is not null select true).Count())
- continue;
+ (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
+ if ((from l in topDirectorySegments where l == "Christmas" select true).Any())
+ seasonValue = string.Empty;
+ else
+ seasonValue = $".{season}";
+ if (isWrongYear is null || !isWrongYear.Value)
+ year = $"{flag}{dateTime:yyyy}{seasonValue}";
+ else if (matches is null || matches.Length < 3)
+ year = "----";
+ else
+ {
+ if (matches[0][0] != '~')
+ year = $"{flag}{matches[0].Split('.')[0]}{seasonValue}";
+ else
+ year = $"{flag}{matches[0][1..].Split('.')[0]}{seasonValue}";
+ }
+ topDirectoryName = Path.GetFileName(topDirectory);
+ weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
+ if (_Configuration.ByHash)
+ directoryNames.Add($"{year} {seasonName}");
+ else if (_Configuration.BySeason && topDirectoryName.Length == 1 && topDirectoryName[0] == '_')
+ directoryNames.Add($"{year} {seasonName}");
+ else
+ {
+ if (!_Configuration.KeepFullPath)
+ {
+ if (topDirectoryName.Length > 1)
+ _ = destinationDirectoryName.Append(topDirectoryName);
+ if (_Configuration.BySeason)
+ directoryNames.AddRange([$"{destinationDirectoryName} {year} {seasonName}"]);
+ else if (_Configuration.ByDay)
+ directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year}-{day}"]);
+ else if (_Configuration.ByWeek)
+ directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year} {month}"]);
+ else
+ throw new Exception();
+ }
+ else
+ {
+ foreach (string sourceDirectoryNameSegment in topDirectorySegments)
+ {
+ if (matches is not null && matches.Contains(sourceDirectoryNameSegment))
+ _ = destinationDirectoryName.Append(year);
+ else
+ _ = destinationDirectoryName.Append(sourceDirectoryNameSegment);
+ }
+ if (_Configuration.BySeason)
+ directoryNames.Add($"{year} {seasonName}");
+ else if (_Configuration.ByDay)
+ directoryNames.Add($"{weekOfYear}) {year} {day}");
+ else if (_Configuration.ByWeek)
+ directoryNames.Add($"{weekOfYear}) {month} {year}");
+ else
+ throw new Exception();
+ }
+ }
+ if (!_Configuration.ByHash || item.ExifDirectory?.FilePath.Id is null)
+ fileName = item.FilePath.Name;
+ else
+ fileName = $"{item.ExifDirectory.FilePath.Id.Value}{item.FilePath.ExtensionLowered}";
+ destinationCollection.Add(destinationDirectory);
+ destinationCollection.AddRange(directoryNames);
+ destinationCollection.Add(fileName);
+ if (item.ExifDirectory is null)
+ results.Add(new(item, item.FilePath.LastWriteTicks, dateTime.Ticks, destinationCollection.ToArray()));
+ else
+ results.Add(new(item, item.ExifDirectory.LastWriteTime.Ticks, dateTime.Ticks, destinationCollection.ToArray()));
}
+ return results;
+ }
+
+ private static bool WriteAllText(string path, string contents, bool compareBeforeWrite)
+ {
+ bool result;
+ string text;
+ if (!compareBeforeWrite)
+ result = true;
+ else
+ {
+ if (!File.Exists(path))
+ text = string.Empty;
+ else
+ text = File.ReadAllText(path);
+ result = text != contents;
+ }
+ if (result)
+ {
+ if (path.Contains("()"))
+ File.WriteAllText(path, contents);
+ else if (path.Contains("{}") && !path.EndsWith(".json"))
+ File.WriteAllText(path, contents);
+ else if (path.Contains("[]") && !path.EndsWith(".json"))
+ File.WriteAllText(path, contents);
+ else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
+ File.WriteAllText(path, contents);
+ else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
+ File.WriteAllText(path, contents);
+ else
+ File.WriteAllText(path, contents);
+ }
+ return result;
}
}
\ No newline at end of file
diff --git a/Drag-Drop-Search/DragDropSearch.cs b/Drag-Drop-Search/DragDropSearch.cs
index 1811159..abf2426 100644
--- a/Drag-Drop-Search/DragDropSearch.cs
+++ b/Drag-Drop-Search/DragDropSearch.cs
@@ -64,63 +64,6 @@ public partial class DragDropSearch : Form
Controls.Add(_TextBox);
}
- private void Form1_Load(object? sender, EventArgs e)
- {
- try
- {
- AllowDrop = true;
- DragDrop += new DragEventHandler(Form1_DragDrop);
- DragEnter += new DragEventHandler(Form1_DragEnter);
- _TextBox.LostFocus += new EventHandler(TextBox_LostFocus);
- }
- catch (Exception)
- {
- throw;
- }
- }
-
- private void TextBox_LostFocus(object? sender, EventArgs e)
- {
- try
- {
- if (_TextBox.Text == "ps")
- throw new NotImplementedException();
- }
- catch (Exception)
- {
- throw;
- }
- }
-
- private 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 LoadData()
- {
- Container.Models.Container[] containers;
- string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "{}");
- (_, containers) = View_by_Distance.Container.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory);
- List
- collection = Program.GetItemCollection(_Configuration, containers);
- foreach (Item item in collection)
- {
- if (item.Property?.Id is null)
- continue;
- if (_IdToItem.ContainsKey(item.Property.Id.Value))
- continue;
- _IdToItem.Add(item.Property.Id.Value, item);
- }
- }
-
public static string? GetFaceEncoding(string file)
{
string? result;
@@ -147,6 +90,37 @@ public partial class DragDropSearch : Form
return result;
}
+ private void LoadData()
+ {
+ Container.Models.Container[] containers;
+ string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "{}");
+ (_, containers) = View_by_Distance.Container.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory);
+ List
- collection = Program.GetItemCollection(_Configuration, containers);
+ foreach (Item item in collection)
+ {
+ if (item.ExifDirectory?.FilePath.Id is null)
+ continue;
+ if (_IdToItem.ContainsKey(item.ExifDirectory.FilePath.Id.Value))
+ continue;
+ _IdToItem.Add(item.ExifDirectory.FilePath.Id.Value, item);
+ }
+ }
+
+ private void Form1_Load(object? sender, EventArgs e)
+ {
+ try
+ {
+ AllowDrop = true;
+ DragDrop += new DragEventHandler(Form1_DragDrop);
+ DragEnter += new DragEventHandler(Form1_DragEnter);
+ _TextBox.LostFocus += new EventHandler(TextBox_LostFocus);
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+
private void GetDirectoriesOrDoDragDrop(string[] paths)
{
string name;
@@ -168,6 +142,19 @@ public partial class DragDropSearch : Form
}
}
+ private void TextBox_LostFocus(object? sender, EventArgs e)
+ {
+ try
+ {
+ if (_TextBox.Text == "ps")
+ throw new NotImplementedException();
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+
private void Form1_DragDrop(object? sender, DragEventArgs e)
{
try
@@ -183,4 +170,17 @@ public partial class DragDropSearch : Form
}
}
+ private 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;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/Duplicate-Search/DuplicateSearch.cs b/Duplicate-Search/DuplicateSearch.cs
index 82e1694..a897783 100644
--- a/Duplicate-Search/DuplicateSearch.cs
+++ b/Duplicate-Search/DuplicateSearch.cs
@@ -1,4 +1,4 @@
-using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Phares.Shared;
using ShellProgressBar;
@@ -61,6 +61,144 @@ public class DuplicateSearch
File.WriteAllText(Path.Combine(alongSideDirectory, $"{directoryName}-{ticks}.json"), json);
}
+ private static Container.Models.Container[] GetContainers(long ticks, Configuration configuration)
+ {
+ int f;
+ Container.Models.Container[] containers;
+ int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
+ string message = $") Building Container(s) - {totalSeconds} total second(s)";
+ ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
+ using (ProgressBar progressBar = new(1, message, options))
+ {
+ progressBar.Tick();
+ string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
+ (f, containers) = Container.Models.Stateless.Methods.IContainer.GetContainers(configuration, aPropertySingletonDirectory);
+ }
+ return containers;
+ }
+
+ private static List GetPreloadIds(string destinationRoot)
+ {
+ List results = [];
+ string[] lines;
+ string preloadDirectory = Path.Combine(destinationRoot, "Preload");
+ if (!Directory.Exists(preloadDirectory))
+ _ = Directory.CreateDirectory(preloadDirectory);
+ string[] files = Directory.GetFiles(preloadDirectory, "*.lsv", SearchOption.TopDirectoryOnly);
+ foreach (string file in files)
+ {
+ lines = File.ReadAllLines(file);
+ foreach (string line in lines)
+ {
+ if (string.IsNullOrEmpty(line) || !int.TryParse(line, out int id) || id == 0)
+ continue;
+ results.Add(id);
+ }
+ }
+ return results;
+ }
+
+ private static Dictionary> GetIdToCollection(string argZero, Configuration configuration, bool argZeroIsConfigurationRootDirectory, Container.Models.Container[] containers, string destinationRoot, List preloadIds)
+ {
+ Dictionary> results = [];
+ string directory;
+ const int zero = 0;
+ FileHolder resizedFileHolder;
+ DateTime[] containerDateTimes;
+ MappingFromItem? mappingFromItem;
+ List? collection;
+ ReadOnlyCollection
- validImageItems;
+ const string duplicates = "-Duplicate(s)";
+ if (containers.Length != 0)
+ {
+ foreach (int id in preloadIds)
+ results.Add(id, [null]);
+ }
+ foreach (Container.Models.Container container in containers)
+ {
+ if (container.Items.Count == 0)
+ continue;
+ if (!argZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
+ continue;
+ validImageItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(configuration, container);
+ if (validImageItems.Count == 0)
+ continue;
+ containerDateTimes = Container.Models.Stateless.Methods.IContainer.GetContainerDateTimes(validImageItems);
+ foreach (Item item in validImageItems)
+ {
+ if (item.ExifDirectory?.FilePath.Id is null)
+ {
+ if (int.TryParse(item.FilePath.NameWithoutExtension, out int id))
+ continue;
+ continue;
+ }
+ if (!results.TryGetValue(item.ExifDirectory.FilePath.Id.Value, out collection))
+ results.Add(item.ExifDirectory.FilePath.Id.Value, []);
+ if (collection is null && !results.TryGetValue(item.ExifDirectory.FilePath.Id.Value, out collection))
+ continue;
+ if (collection.Count == 0)
+ directory = $"0{duplicates}";
+ else
+ directory = $"{collection.Count + 1}{duplicates}";
+ if (collection.Count == 1)
+ {
+ mappingFromItem = collection[zero];
+ if (mappingFromItem is not null)
+ {
+ resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}"));
+ collection[0] = new(mappingFromItem.ContainerDateTimes, item.Property.DateTimeDigitized, item.Property.DateTimeOriginal, mappingFromItem.Id, mappingFromItem.IsArchive, mappingFromItem.FilePath, mappingFromItem.IsWrongYear, item.Property.Keywords ?? [], mappingFromItem.MinimumDateTime, item.Property.Model, mappingFromItem.RelativePath, resizedFileHolder);
+ }
+ }
+ resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath));
+ mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
+ collection.Add(mappingFromItem);
+ }
+ }
+ return results;
+ }
+
+ private static void QuestionMove(long ticks, ILogger? logger, string destinationRoot, Dictionary> idToCollection, int duplicates)
+ {
+ int[] ids = (from l in idToCollection orderby l.Key where l.Value.Any(m => m is not null) select l.Key).ToArray();
+ _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(destinationRoot, $"{ticks}-id(s).lsv"), string.Join(Environment.NewLine, ids), updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
+ string json = JsonSerializer.Serialize(idToCollection, new JsonSerializerOptions { WriteIndented = true });
+ _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(destinationRoot, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
+ logger?.LogInformation($"Found {duplicates} duplicate file(s)");
+ for (int y = 0; y < int.MaxValue; y++)
+ {
+ logger?.LogInformation("Press \"Y\" key to continue or close console to leave them moved");
+ if (System.Console.ReadKey().Key != ConsoleKey.Y)
+ continue;
+ logger?.LogInformation(". . .");
+ List<(FilePath FilePath, string Destination)> collection = GetCollectionAndCreateDirectories(idToCollection);
+ Move(logger, ticks, destinationRoot, collection);
+ }
+ }
+
+ private static List<(FilePath FilePath, string Destination)> GetCollectionAndCreateDirectories(Dictionary> idToCollection)
+ {
+ List<(FilePath FilePath, string Destination)> results = [];
+ List collection = [];
+ foreach (KeyValuePair> keyValuePair in idToCollection)
+ {
+ foreach (MappingFromItem? mappingFromItem in keyValuePair.Value)
+ {
+ if (mappingFromItem?.ResizedFileHolder.DirectoryFullPath is null)
+ continue;
+ if (mappingFromItem.ResizedFileHolder.Exists)
+ continue;
+ collection.Add(mappingFromItem.ResizedFileHolder.DirectoryFullPath);
+ results.Add(new(mappingFromItem.FilePath, mappingFromItem.ResizedFileHolder.FullName));
+ }
+ }
+ foreach (string directory in collection.Distinct())
+ {
+ if (!Directory.Exists(directory))
+ _ = Directory.CreateDirectory(directory);
+ }
+ return results;
+ }
+
private static void Move(ILogger? logger, long ticks, string destinationRoot, List<(FilePath FilePath, string Destination)> collection)
{
StringBuilder stringBuilder = new();
@@ -107,142 +245,4 @@ public class DuplicateSearch
logger?.LogInformation(". . .");
}
- private static void QuestionMove(long ticks, ILogger? logger, string destinationRoot, Dictionary> idToCollection, int duplicates)
- {
- int[] ids = (from l in idToCollection orderby l.Key where l.Value.Any(m => m is not null) select l.Key).ToArray();
- _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(destinationRoot, $"{ticks}-id(s).lsv"), string.Join(Environment.NewLine, ids), updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
- string json = JsonSerializer.Serialize(idToCollection, new JsonSerializerOptions { WriteIndented = true });
- _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(destinationRoot, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
- logger?.LogInformation($"Found {duplicates} duplicate file(s)");
- for (int y = 0; y < int.MaxValue; y++)
- {
- logger?.LogInformation("Press \"Y\" key to continue or close console to leave them moved");
- if (System.Console.ReadKey().Key != ConsoleKey.Y)
- continue;
- logger?.LogInformation(". . .");
- List<(FilePath FilePath, string Destination)> collection = GetCollectionAndCreateDirectories(idToCollection);
- Move(logger, ticks, destinationRoot, collection);
- }
- }
-
- private static Container.Models.Container[] GetContainers(long ticks, Configuration configuration)
- {
- int f;
- Container.Models.Container[] containers;
- int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
- string message = $") Building Container(s) - {totalSeconds} total second(s)";
- ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
- using (ProgressBar progressBar = new(1, message, options))
- {
- progressBar.Tick();
- string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
- (f, containers) = Container.Models.Stateless.Methods.IContainer.GetContainers(configuration, aPropertySingletonDirectory);
- }
- return containers;
- }
-
- private static Dictionary> GetIdToCollection(string argZero, Configuration configuration, bool argZeroIsConfigurationRootDirectory, Container.Models.Container[] containers, string destinationRoot, List preloadIds)
- {
- Dictionary> results = [];
- string directory;
- const int zero = 0;
- FileHolder resizedFileHolder;
- DateTime[] containerDateTimes;
- MappingFromItem? mappingFromItem;
- List? collection;
- ReadOnlyCollection
- validImageItems;
- const string duplicates = "-Duplicate(s)";
- if (containers.Length != 0)
- {
- foreach (int id in preloadIds)
- results.Add(id, [null]);
- }
- foreach (Container.Models.Container container in containers)
- {
- if (container.Items.Count == 0)
- continue;
- if (!argZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
- continue;
- validImageItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(configuration, container);
- if (validImageItems.Count == 0)
- continue;
- containerDateTimes = Container.Models.Stateless.Methods.IContainer.GetContainerDateTimes(validImageItems);
- foreach (Item item in validImageItems)
- {
- if (item.Property?.Id is null)
- {
- if (int.TryParse(item.FilePath.NameWithoutExtension, out int id))
- continue;
- continue;
- }
- if (!results.TryGetValue(item.Property.Id.Value, out collection))
- results.Add(item.Property.Id.Value, []);
- if (collection is null && !results.TryGetValue(item.Property.Id.Value, out collection))
- continue;
- if (collection.Count == 0)
- directory = $"0{duplicates}";
- else
- directory = $"{collection.Count + 1}{duplicates}";
- if (collection.Count == 1)
- {
- mappingFromItem = collection[zero];
- if (mappingFromItem is not null)
- {
- resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}"));
- collection[0] = new(mappingFromItem.ContainerDateTimes, item.Property.DateTimeDigitized, item.Property.DateTimeOriginal, mappingFromItem.Id, mappingFromItem.IsArchive, mappingFromItem.FilePath, mappingFromItem.IsWrongYear, item.Property.Keywords ?? [], mappingFromItem.MinimumDateTime, item.Property.Model, mappingFromItem.RelativePath, resizedFileHolder);
- }
- }
- resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath));
- mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
- collection.Add(mappingFromItem);
- }
- }
- return results;
- }
-
- private static List<(FilePath FilePath, string Destination)> GetCollectionAndCreateDirectories(Dictionary> idToCollection)
- {
- List<(FilePath FilePath, string Destination)> results = [];
- List collection = [];
- foreach (KeyValuePair> keyValuePair in idToCollection)
- {
- foreach (MappingFromItem? mappingFromItem in keyValuePair.Value)
- {
- if (mappingFromItem?.ResizedFileHolder.DirectoryFullPath is null)
- continue;
- if (mappingFromItem.ResizedFileHolder.Exists)
- continue;
- collection.Add(mappingFromItem.ResizedFileHolder.DirectoryFullPath);
- results.Add(new(mappingFromItem.FilePath, mappingFromItem.ResizedFileHolder.FullName));
- }
- }
- foreach (string directory in collection.Distinct())
- {
- if (!Directory.Exists(directory))
- _ = Directory.CreateDirectory(directory);
- }
- return results;
- }
-
- private static List GetPreloadIds(string destinationRoot)
- {
- List results = [];
- string[] lines;
- string preloadDirectory = Path.Combine(destinationRoot, "Preload");
- if (!Directory.Exists(preloadDirectory))
- _ = Directory.CreateDirectory(preloadDirectory);
- string[] files = Directory.GetFiles(preloadDirectory, "*.lsv", SearchOption.TopDirectoryOnly);
- foreach (string file in files)
- {
- lines = File.ReadAllLines(file);
- foreach (string line in lines)
- {
- if (string.IsNullOrEmpty(line) || !int.TryParse(line, out int id) || id == 0)
- continue;
- results.Add(id);
- }
- }
- return results;
- }
-
}
\ No newline at end of file
diff --git a/Face/Models/_D_Face.cs b/Face/Models/_D_Face.cs
index 895e4c1..94fb512 100644
--- a/Face/Models/_D_Face.cs
+++ b/Face/Models/_D_Face.cs
@@ -264,7 +264,7 @@ public class D_Face : IFaceD
}
}
- public List GetFaces(string outputResolution, string cResultsFullGroupDirectory, FilePath filePath, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, List? mappingFromPhotoPrismCollection)
+ public List GetFaces(string outputResolution, string cResultsFullGroupDirectory, FilePath filePath, List> subFileTuples, List parseExceptions, ExifDirectory exifDirectory, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, List? mappingFromPhotoPrismCollection)
{
List? results;
string? json;
@@ -314,7 +314,7 @@ public class D_Face : IFaceD
locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(results, mappingFromPhotoPrismCollection, _RectangleIntersectMinimum);
if (results is null || locations.Count > 0)
{
- results = GetFaces(outputResolution, cResultsFullGroupDirectory, property, mappingFromItem, outputResolutionToResize, locations);
+ results = GetFaces(outputResolution, cResultsFullGroupDirectory, exifDirectory, mappingFromItem, outputResolutionToResize, locations);
if (results.Count == 0)
File.Move(mappingFromItem.ResizedFileHolder.FullName, $"{mappingFromItem.ResizedFileHolder.FullName}.err");
else
@@ -338,7 +338,7 @@ public class D_Face : IFaceD
return results;
}
- private List GetFaces(string outputResolution, string cResultsFullGroupDirectory, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, List locations)
+ private List GetFaces(string outputResolution, string cResultsFullGroupDirectory, ExifDirectory exifDirectory, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, List locations)
{
if (_PropertyConfiguration.NumberOfJitters is null)
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfJitters));
@@ -374,7 +374,7 @@ public class D_Face : IFaceD
FaceRecognition faceRecognition = new(_PropertyConfiguration.NumberOfJitters.Value, _PropertyConfiguration.NumberOfTimesToUpsample.Value, _Model, _ModelParameter, _PredictorModel);
collection = faceRecognition.GetCollection(unknownImage, locations, includeFaceEncoding: true, includeFaceParts: true);
if (collection.Count == 0)
- results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null));
+ results.Add(new(exifDirectory, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null));
else
{
double[] rawEncoding;
@@ -382,7 +382,7 @@ public class D_Face : IFaceD
Shared.Models.FaceEncoding convertedFaceEncoding;
foreach ((Location location, FaceRecognitionDotNet.FaceEncoding? faceEncoding, Dictionary? faceParts) in collection)
{
- face = new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location);
+ face = new(exifDirectory, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location);
if (faceEncoding is not null)
{
rawEncoding = faceEncoding.GetRawEncoding();
diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs
index b3d030b..26d9e84 100644
--- a/Instance/DlibDotNet.cs
+++ b/Instance/DlibDotNet.cs
@@ -25,6 +25,13 @@ namespace View_by_Distance.Instance;
public partial class DlibDotNet : IDlibDotNet, IDisposable
{
+ public record Record(ReadOnlyDictionary ExifDirectoriesById,
+ string FilesCollectionRootDirectory,
+ bool FilesCollectionCountIsOne,
+ ReadOnlyCollection> FilePathsCollection,
+ ReadOnlyDictionary>? IdToFilePaths,
+ ReadOnlyDictionary? SplatNineIdentifiers);
+
private readonly D_Face _Faces;
private ProgressBar? _ProgressBar;
private readonly C_Resize _Resize;
@@ -40,6 +47,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
private readonly DistanceLimits _DistanceLimits;
private readonly bool _PropertyRootExistedBefore;
private readonly Models.Configuration _Configuration;
+ private readonly ProgressBarOptions _ProgressBarOptions;
private readonly bool _ArgZeroIsConfigurationRootDirectory;
private readonly Map.Models.Configuration _MapConfiguration;
private readonly List<(string Directory, long PersonKey)> _JLinkResolvedDirectories;
@@ -56,15 +64,16 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
{
string message;
_Logger = logger;
+ _Exceptions = [];
_Console = console;
_AppSettings = appSettings;
_IsEnvironment = isEnvironment;
long ticks = DateTime.Now.Ticks;
- _Exceptions = [];
_JLinkResolvedDirectories = [];
if (ticks.ToString().Last() == '0')
ticks += 1;
ReadOnlyCollection personContainers;
+ _ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration);
_Logger?.LogInformation(propertyConfiguration.RootDirectory);
@@ -119,8 +128,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
{
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
message = $") Building People Collection - {totalSeconds} total second(s)";
- ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
- using ProgressBar progressBar = new(1, message, options);
+ using ProgressBar progressBar = new(1, message, _ProgressBarOptions);
progressBar.Tick();
string peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A2_People));
string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory)) ?? throw new Exception();
@@ -165,8 +173,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
_Logger?.LogInformation("First run completed. Run again if wanted");
}
- private int FullParallelForWork(A_Property propertyLogic,
- B_Metadata metadata,
+ private int FullParallelForWork(B_Metadata metadata,
MapLogic mapLogic,
string outputResolution,
bool outputResolutionHasNumber,
@@ -174,59 +181,47 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
string d2ResultsFullGroupDirectory,
List> sourceDirectoryChanges,
Dictionary> fileNameToCollection,
+ Record record,
Container.Models.Container container,
Item item,
DateTime[] containerDateTimes,
bool? isFocusRelativePath)
{
int result = 0;
+ bool? shouldIgnore;
List faces;
long ticks = DateTime.Now.Ticks;
DateTime dateTime = DateTime.Now;
- Shared.Models.Property? property;
List parseExceptions = [];
string[] changesFrom = [nameof(A_Property)];
List> subFileTuples = [];
FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber);
- if (item.Property is null || item.Property.Id is null || !item.SourceDirectoryFileHolder.Exists || item.SourceDirectoryFileHolder.CreationTime is null || item.SourceDirectoryFileHolder.LastWriteTime is null || item.Any())
+ if (item.ExifDirectory is null || item.ExifDirectory.FilePath.Id is null || !item.SourceDirectoryFileHolder.Exists || item.SourceDirectoryFileHolder.CreationTime is null || item.SourceDirectoryFileHolder.LastWriteTime is null || item.Any())
+ throw new Exception();
+ if (_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime && item.SourceDirectoryFileHolder.LastWriteTime.Value != item.SourceDirectoryFileHolder.CreationTime.Value)
{
- LogItemPropertyIsNull(item);
- int? propertyHashCode = item.Property?.GetHashCode();
- property = propertyLogic.GetProperty(metadata, item, subFileTuples, parseExceptions);
- item.Update(property);
- if (propertyHashCode is null)
- {
- lock (sourceDirectoryChanges)
- sourceDirectoryChanges.Add(new Tuple(nameof(A_Property), DateTime.Now));
- }
- else if (propertyHashCode.Value != property.GetHashCode())
- {
- lock (sourceDirectoryChanges)
- sourceDirectoryChanges.Add(new Tuple(nameof(A_Property), DateTime.Now));
- }
+ File.SetLastWriteTime(item.SourceDirectoryFileHolder.FullName, item.SourceDirectoryFileHolder.CreationTime.Value);
+ subFileTuples.Add(new Tuple(nameof(A_Property), item.SourceDirectoryFileHolder.CreationTime.Value));
+ }
+ else if (item.SourceDirectoryFileHolder.LastWriteTime is not null)
+ subFileTuples.Add(new Tuple(nameof(A_Property), item.SourceDirectoryFileHolder.LastWriteTime.Value));
+ else
+ subFileTuples.Add(new Tuple(nameof(A_Property), new FileInfo(item.SourceDirectoryFileHolder.FullName).LastWriteTime));
+ if (resizedFileHolder.Exists && item.ExifDirectory.Width is not null && item.ExifDirectory.Width.Value > 4 && _Configuration.SaveBlurHashForOutputResolutions.Contains(outputResolution))
+ {
+ string? file = _BlurHasher.GetFile(item.FilePath);
+ if (file is not null && !File.Exists(file))
+ _ = _BlurHasher.EncodeAndSave(item.FilePath, resizedFileHolder);
+ }
+ if (item.FilePath.Id is null || !record.ExifDirectoriesById.TryGetValue(item.FilePath.Id.Value, out ExifDirectory? exifDirectory))
+ {
+ shouldIgnore = null;
+ exifDirectory = null;
}
else
{
- property = item.Property;
- if (_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime && item.SourceDirectoryFileHolder.LastWriteTime.Value != item.SourceDirectoryFileHolder.CreationTime.Value)
- {
- File.SetLastWriteTime(item.SourceDirectoryFileHolder.FullName, item.SourceDirectoryFileHolder.CreationTime.Value);
- subFileTuples.Add(new Tuple(nameof(A_Property), item.SourceDirectoryFileHolder.CreationTime.Value));
- }
- else if (item.SourceDirectoryFileHolder.LastWriteTime is not null)
- subFileTuples.Add(new Tuple(nameof(A_Property), item.SourceDirectoryFileHolder.LastWriteTime.Value));
- else
- subFileTuples.Add(new Tuple(nameof(A_Property), new FileInfo(item.SourceDirectoryFileHolder.FullName).LastWriteTime));
- if (resizedFileHolder.Exists && item.Property.Width is not null && item.Property.Width.Value > 4 && _Configuration.SaveBlurHashForOutputResolutions.Contains(outputResolution))
- {
- string? file = _BlurHasher.GetFile(item.FilePath);
- if (file is not null && !File.Exists(file))
- _ = _BlurHasher.EncodeAndSave(item.FilePath, resizedFileHolder);
- }
- }
- bool? shouldIgnore = property is null || property.Keywords is null ? null : _Configuration.PropertyConfiguration.IgnoreRulesKeyWords.Any(l => property.Keywords.Contains(l));
- if (shouldIgnore is not null)
- {
+ ReadOnlyCollection keywords = IMetaBase.GetKeywords(exifDirectory.ExifBaseDirectories);
+ shouldIgnore = _Configuration.PropertyConfiguration.IgnoreRulesKeyWords.Any(keywords.Contains);
if (shouldIgnore.Value)
{
FileInfo fileInfo = new(resizedFileHolder.FullName);
@@ -241,11 +236,9 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
throw new NotSupportedException($"Rename File! <{item.FilePath.FileNameFirstSegment}>");
}
}
- if (property is null || item.Property is null)
- throw new NullReferenceException(nameof(property));
item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder);
MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
- ExifDirectory exifDirectory = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
+ exifDirectory ??= metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
if (_AppSettings.Places.Count > 0)
{
float latitude;
@@ -268,13 +261,13 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
distance += 1;
}
}
- Dictionary outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem);
+ Dictionary outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.ExifDirectory, mappingFromItem);
if (_Configuration.SaveResizedSubfiles)
{
if (shouldIgnore is not null && item.FilePath.HasIgnoreKeyword is not null && item.FilePath.HasIgnoreKeyword.Value != shouldIgnore.Value)
faces = [];
else
- _Resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize);
+ _Resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.ExifDirectory, mappingFromItem, outputResolutionToResize);
}
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution))
faces = [];
@@ -286,7 +279,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
if (!fileNameToCollection.TryGetValue(mappingFromItem.Id, out mappingFromPhotoPrismCollection))
mappingFromPhotoPrismCollection = null;
bool move = _Configuration.DistanceMoveUnableToMatch || _Configuration.DistanceRenameToMatch && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution);
- faces = _Faces.GetFaces(outputResolution, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, mappingFromPhotoPrismCollection);
+ faces = _Faces.GetFaces(outputResolution, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.ExifDirectory, mappingFromItem, outputResolutionToResize, mappingFromPhotoPrismCollection);
result = GetNotMappedCountAndUpdateMappingFromPersonThenSetMapping(mapLogic, item, isFocusRelativePath, mappingFromItem, mappingFromPhotoPrismCollection, faces);
List<(Shared.Models.Face, FileHolder?, string, bool Saved)> faceCollection = _Faces.SaveFaces(item.FilePath, subFileTuples, parseExceptions, mappingFromItem, exifDirectory, faces);
if (move && faceCollection.All(l => !l.Saved))
@@ -319,7 +312,6 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
}
private (int, bool) FullParallelWork(int maxDegreeOfParallelism,
- A_Property propertyLogic,
B_Metadata metadata,
MapLogic mapLogic,
string outputResolution,
@@ -328,6 +320,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
string d2ResultsFullGroupDirectory,
List> sourceDirectoryChanges,
Dictionary> fileNameToCollection,
+ Record record,
Container.Models.Container container,
ReadOnlyCollection
- filteredItems,
string message)
@@ -336,17 +329,15 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
int exceptionsCount = 0;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
DateTime[] containerDateTimes = Container.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems);
- ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory));
bool? isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
bool anyPropertiesChangedForX = _Configuration.PropertyConfiguration.PropertiesChangedForProperty || _Configuration.PropertiesChangedForDistance || _Configuration.PropertiesChangedForFaces || _Configuration.PropertiesChangedForIndex || _Configuration.PropertiesChangedForMetadata || _Configuration.PropertiesChangedForResize;
- using ProgressBar progressBar = new(filteredItems.Count, message, options);
+ using ProgressBar progressBar = new(filteredItems.Count, message, _ProgressBarOptions);
_ = Parallel.For(0, filteredItems.Count, parallelOptions, (i, state) =>
{
try
{
- result += FullParallelForWork(propertyLogic,
- metadata,
+ result += FullParallelForWork(metadata,
mapLogic,
outputResolution,
outputResolutionHasNumber,
@@ -354,6 +345,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
d2ResultsFullGroupDirectory,
sourceDirectoryChanges,
fileNameToCollection,
+ record,
container,
filteredItems[i],
containerDateTimes,
@@ -371,6 +363,98 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
return (result, exceptionsCount > 0);
}
+ private void FullDoWork(string argZero,
+ string propertyRoot,
+ long ticks,
+ string fPhotoPrismSingletonDirectory,
+ int count,
+ B_Metadata metadata,
+ Record record,
+ ReadOnlyCollection readOnlyContainers,
+ MapLogic mapLogic)
+ {
+ int total;
+ int notMapped;
+ string message;
+ bool exceptions;
+ int totalSeconds;
+ int totalNotMapped = 0;
+ IDlibDotNet dlibDotNet = this;
+ bool outputResolutionHasNumber;
+ bool anyNullOrNoIsUniqueFileName;
+ string cResultsFullGroupDirectory;
+ string dResultsFullGroupDirectory;
+ string c2ResultsFullGroupDirectory;
+ string d2ResultsFullGroupDirectory;
+ Container.Models.Container container;
+ ReadOnlyCollection
- filteredItems;
+ List> sourceDirectoryChanges = [];
+ int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism;
+ Dictionary> fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = [] : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory);
+ string dResultsDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D_Face));
+ foreach (string outputResolution in _Configuration.OutputResolutions)
+ {
+ total = 0;
+ outputResolutionHasNumber = outputResolution.Any(char.IsNumber);
+ (cResultsFullGroupDirectory, c2ResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
+ _Faces.Update(dResultsFullGroupDirectory);
+ _Resize.Update(cResultsFullGroupDirectory);
+ _FaceParts.Update(d2ResultsFullGroupDirectory);
+ _BlurHasher.Update(c2ResultsFullGroupDirectory);
+ for (int i = 0; i < readOnlyContainers.Count; i++)
+ {
+ container = readOnlyContainers[i];
+ if (container.Items.Count == 0)
+ continue;
+ if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
+ continue;
+ filteredItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, container);
+ if (filteredItems.Count == 0)
+ continue;
+ sourceDirectoryChanges.Clear();
+ anyNullOrNoIsUniqueFileName = filteredItems.Any(l => !l.IsUniqueFileName);
+ totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
+ message = $"{totalSeconds} total second(s) - {outputResolution} - {i + 1:000} / {readOnlyContainers.Count:000} - {total} / {count} total - <{container.SourceDirectory}> [{filteredItems.Count:000}] - total not mapped {totalNotMapped:000000}";
+ if (outputResolutionHasNumber)
+ _Resize.SetAngleBracketCollection(cResultsFullGroupDirectory, container.SourceDirectory);
+ (notMapped, exceptions) = FullParallelWork(maxDegreeOfParallelism,
+ metadata,
+ mapLogic,
+ outputResolution,
+ outputResolutionHasNumber,
+ cResultsFullGroupDirectory,
+ d2ResultsFullGroupDirectory,
+ sourceDirectoryChanges,
+ fileNameToCollection,
+ record,
+ container,
+ filteredItems,
+ message);
+ totalNotMapped += notMapped;
+ if (exceptions)
+ {
+ _Exceptions.Add(container.SourceDirectory);
+ continue;
+ }
+ if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Length > 0)
+ {
+ for (int y = 0; y < int.MaxValue; y++)
+ {
+ _Logger?.LogInformation("Press \"Y\" key when ready to continue or close console");
+ if (_Console.ReadKey() == ConsoleKey.Y)
+ break;
+ }
+ _Logger?.LogInformation(". . .");
+ }
+ total += container.Items.Count;
+ }
+ totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
+ message = $"{totalSeconds} total second(s) - {outputResolution} - ### [###] / {readOnlyContainers.Count:000} - {total} / {count} total - <> - total not mapped {totalNotMapped:000000}";
+ using ProgressBar progressBar = new(1, message, _ProgressBarOptions);
+ progressBar.Tick();
+ }
+ }
+
void IDlibDotNet.Tick() =>
_ProgressBar?.Tick();
@@ -399,6 +483,12 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory);
}
+ void IDlibDotNet.ConstructProgressBar(int maxTicks, string message)
+ {
+ _ProgressBar?.Dispose();
+ _ProgressBar = new(maxTicks, message, _ProgressBarOptions);
+ }
+
(string, string, string, string) IDlibDotNet.GetResultsFullGroupDirectories(string outputResolution)
{
string cResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
@@ -466,7 +556,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
if (filePath.Id is null)
throw new Exception();
string[] directoryNames = keyValuePair.Value.Select(l => l.DirectoryFullPath.Replace('\\', '/')).ToArray();
- string paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal, index: null);
+ string paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, filePath.ExtensionLowered, filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal, index: null);
result = new(directoryNames, filePath.ExtensionLowered, filePath.HasDateTimeOriginal, filePath.Id.Value, filePath.Length, paddedId, filePath.LastWriteTicks);
return result;
}
@@ -513,6 +603,22 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
throw new NullReferenceException(nameof(configuration.ModelDirectory));
}
+ private static ExifDirectory? GetExifDirectory(FilePair filePair)
+ {
+ ExifDirectory? result;
+ if (filePair.Match is null)
+ result = null;
+ else
+ {
+ string json = File.ReadAllText(filePair.Match.FullName);
+ if (string.IsNullOrEmpty(json))
+ result = null;
+ else
+ result = JsonSerializer.Deserialize(json, ExifDirectorySourceGenerationContext.Default.ExifDirectory);
+ }
+ return result;
+ }
+
private static void DeleteContinueFiles(ReadOnlyCollection personContainers)
{
foreach (PersonContainer personContainer in personContainers)
@@ -554,7 +660,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
}
}
- private static bool IsFilesCollectionCountIsOne(ReadOnlyCollection> filePathsCollection)
+ private static bool GetFilesCollectionCountIsOne(ReadOnlyCollection> filePathsCollection)
{
bool result = true;
int count = 0;
@@ -582,11 +688,11 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
foreach (Item item in distinctFilteredItems)
{
found = false;
- if (item.Property?.Id is null)
+ if (item.ExifDirectory?.FilePath.Id is null)
continue;
foreach (Mapping mapping in distinctFilteredMappingCollection)
{
- if (mapping.MappingFromItem.Id != item.Property.Id.Value)
+ if (mapping.MappingFromItem.Id != item.ExifDirectory.FilePath.Id.Value)
continue;
found = true;
break;
@@ -601,13 +707,15 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
string fileName;
string directory;
bool? isWrongYear;
- List dateTimes;
+ DateTime? dateTime;
+ string? exifDirectoryModel;
List distinct = [];
WindowsShortcut windowsShortcut;
+ ReadOnlyCollection dateTimes;
List<(string, string, string)> collection = [];
foreach (Item item in distinctValidImageItems)
{
- if (item.Property?.Id is null)
+ if (item.ExifDirectory?.FilePath.Id is null)
continue;
if (item.IsNotUniqueAndNeedsReview is null || !item.IsNotUniqueAndNeedsReview.Value)
continue;
@@ -620,15 +728,19 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
}
foreach (Item item in distinctValidImageItems)
{
- if (item.Property?.Id is null || item.Property.DateTimeOriginal is null)
+ if (item.ExifDirectory?.FilePath.Id is null)
continue;
- dateTimes = item.Property.GetDateTimes();
- (isWrongYear, _) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(item.FilePath, item.Property.DateTimeOriginal, dateTimes);
+ dateTime = IDate.GetDateTimeOriginal(item.ExifDirectory);
+ if (dateTime is null)
+ continue;
+ dateTimes = IDate.GetDateTimes(item.ExifDirectory);
+ (isWrongYear, _) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(item.FilePath, dateTime, dateTimes.ToList());
if (isWrongYear is null || !isWrongYear.Value)
continue;
// Remove-Item -LiteralPath "\\?\D:\Tmp\a\EX-Z70 "
- model = string.IsNullOrEmpty(item.Property.Model) ? "Unknown" : CameraRegex().Replace(item.Property.Model.Trim(), "_");
- directory = Path.Combine($"{eDistanceContentDirectory[..^1]}{nameof(Item)})", item.Property.DateTimeOriginal.Value.Year.ToString(), model);
+ exifDirectoryModel = IMetaBase.GetModel(item.ExifDirectory?.ExifBaseDirectories);
+ model = string.IsNullOrEmpty(exifDirectoryModel) ? "Unknown" : CameraRegex().Replace(exifDirectoryModel.Trim(), "_");
+ directory = Path.Combine($"{eDistanceContentDirectory[..^1]}{nameof(Item)})", dateTime.Value.Year.ToString(), model);
fileName = item.IsNotUniqueAndNeedsReview is not null && item.IsNotUniqueAndNeedsReview.Value ? Path.Combine(directory, $"{item.FilePath.Name} {item.FilePath.Length}.lnk") : Path.Combine(directory, $"{item.FilePath.Name}.lnk");
collection.Add((item.FilePath.FullName, directory, fileName));
if (distinct.Contains(directory))
@@ -797,15 +909,19 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
return results;
}
- private bool? GetIsFocusModel(Shared.Models.Property? property)
+ private bool? GetIsFocusModel(ExifDirectory? exifDirectory)
{
bool? result;
if (string.IsNullOrEmpty(_Configuration.FocusModel))
result = null;
- else if (property is null || string.IsNullOrEmpty(property.Model))
- result = null;
else
- result = property.Model.Contains(_Configuration.FocusModel);
+ {
+ string? model = IMetaBase.GetModel(exifDirectory?.ExifBaseDirectories);
+ if (exifDirectory is null || string.IsNullOrEmpty(model))
+ result = null;
+ else
+ result = model.Contains(_Configuration.FocusModel);
+ }
return result;
}
@@ -867,7 +983,39 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
return result;
}
- private bool GetRunToDoCollectionFirst(Models.Configuration configuration, long ticks)
+ private ReadOnlyCollection GetFilePath(long ticks, string dFacesContentDirectory)
+ {
+ List results = [];
+ FilePath filePath;
+ FileHolder fileHolder;
+ string[] files = Directory.GetFiles(dFacesContentDirectory, $"*{_Faces.FileNameExtension}", SearchOption.AllDirectories);
+ long? skipOlderThan = _Configuration.SkipOlderThanDays is null ? null : new DateTime(ticks).AddDays(-_Configuration.SkipOlderThanDays.Value).Ticks;
+ foreach (string file in files)
+ {
+ fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(file);
+ filePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: null);
+ if (filePath.Id is null)
+ continue;
+ if (skipOlderThan is not null && (fileHolder.LastWriteTime is null || fileHolder.LastWriteTime.Value.Ticks < skipOlderThan.Value))
+ continue;
+ results.Add(filePath);
+ }
+ return results.AsReadOnly();
+ }
+
+ private void ParallelFor(IDlibDotNet dlibDotNet, FilePair filePair, Dictionary results)
+ {
+ dlibDotNet?.Tick();
+ if (filePair.FilePath.Id is null || results.ContainsKey(filePair.FilePath.Id.Value))
+ return;
+ ExifDirectory? exifDirectory = GetExifDirectory(filePair);
+ if (exifDirectory is null)
+ return;
+ lock (results)
+ results.Add(filePair.FilePath.Id.Value, exifDirectory);
+ }
+
+ private bool GetRunToDoCollectionFirst(Models.Configuration configuration, long ticks, string[] checkDirectories)
{
bool result = configuration.SaveSortingWithoutPerson;
if (!result)
@@ -887,20 +1035,16 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
string eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), _Configuration.PropertyConfiguration.ResultContent);
(int season, string seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
FileSystemInfo fileSystemInfo = new DirectoryInfo(eDistanceContentDirectory);
- string[] checkDirectories =
- [
- Path.Combine(rootDirectory, "Ancestry"),
- Path.Combine(rootDirectory, "Facebook"),
- Path.Combine(rootDirectory, "LinkedIn")
- ];
foreach (string checkDirectory in checkDirectories)
{
+ if (!Directory.Exists(checkDirectory))
+ result = true;
if (checkDirectory == rootDirectory)
seasonDirectory = Path.Combine(checkDirectory, $"{dateTime.Year}.{season} {seasonName}");
else
seasonDirectory = Path.Combine(checkDirectory, $"{dateTime.Year}.{season} {seasonName} {Path.GetFileName(checkDirectory)}");
if (!Directory.Exists(seasonDirectory))
- _ = Directory.CreateDirectory(seasonDirectory);
+ result = true;
if (result)
continue;
directories = Directory.GetDirectories(checkDirectory, "*", SearchOption.TopDirectoryOnly);
@@ -923,32 +1067,15 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
return result;
}
- private ReadOnlyCollection GetFilePath(long ticks, string dFacesContentDirectory)
- {
- List results = [];
- FilePath filePath;
- FileHolder fileHolder;
- string[] files = Directory.GetFiles(dFacesContentDirectory, $"*{_Faces.FileNameExtension}", SearchOption.AllDirectories);
- long? skipOlderThan = _Configuration.SkipOlderThanDays is null ? null : new DateTime(ticks).AddDays(-_Configuration.SkipOlderThanDays.Value).Ticks;
- foreach (string file in files)
- {
- fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(file);
- filePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: null);
- if (filePath.Id is null)
- continue;
- if (skipOlderThan is not null && (fileHolder.LastWriteTime is null || fileHolder.LastWriteTime.Value.Ticks < skipOlderThan.Value))
- continue;
- results.Add(filePath);
- }
- return results.AsReadOnly();
- }
-
private void Search(long ticks, ReadOnlyCollection personContainers, string argZero, string propertyRoot)
{
string message;
MapLogic? mapLogic;
+ Record? record = null;
+ string seasonDirectory;
A_Property propertyLogic;
IDlibDotNet dlibDotNet = this;
+ DateTime dateTime = new(ticks);
string eDistanceContentDirectory;
string? a2PeopleContentDirectory;
string aResultsFullGroupDirectory;
@@ -957,23 +1084,24 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
string fPhotoPrismContentDirectory;
const string fileSearchFilter = "*";
string fPhotoPrismSingletonDirectory;
- bool filesCollectionCountIsOne = false;
const string directorySearchFilter = "*";
- string? filesCollectionRootDirectory = null;
bool configurationOutputResolutionsHas = false;
ReadOnlyDictionary> personKeyToIds;
- ReadOnlyDictionary? splatNineIdentifiers = null;
- ReadOnlyDictionary>? keyValuePairs = null;
- ReadOnlyCollection>? filePathsCollection = null;
- bool runToDoCollectionFirst = GetRunToDoCollectionFirst(_Configuration, ticks);
+ (int season, string seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
+ string[] checkDirectories =
+ [
+ Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, "Ancestry"),
+ Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, "Facebook"),
+ Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, "LinkedIn")
+ ];
+ bool runToDoCollectionFirst = GetRunToDoCollectionFirst(_Configuration, ticks, checkDirectories);
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
- ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory, ticks);
a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])");
- B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory);
eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), _Configuration.PropertyConfiguration.ResultContent);
string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), _Configuration.PropertyConfiguration.ResultSingleton);
_ = Directory.CreateDirectory(Path.Combine(eDistanceContentDirectory, ticks.ToString()));
+ B_Metadata metadata = new(dlibDotNet, _Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, ticks, bResultsFullGroupDirectory);
if (runToDoCollectionFirst)
mapLogic = null;
else
@@ -985,18 +1113,16 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
configurationOutputResolutionsHas = true;
if (!runToDoCollectionFirst)
break;
- (filesCollectionRootDirectory, filePathsCollection, filesCollectionCountIsOne) = GetFilesCollectionThenCopyOrMove(ticks, fileSearchFilter, directorySearchFilter, options, outputResolution);
- keyValuePairs = FilePath.GetKeyValuePairs(filePathsCollection);
- splatNineIdentifiers = GetSplatNineIdentifiersAndHideSplatNine(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, keyValuePairs);
+ record = GetFilesCollectionThenCopyOrMove(dlibDotNet, ticks, fileSearchFilter, directorySearchFilter, bResultsFullGroupDirectory, outputResolution);
break;
}
fPhotoPrismContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), _Configuration.PropertyConfiguration.ResultContent);
fPhotoPrismSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), _Configuration.PropertyConfiguration.ResultSingleton);
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory);
- if (filesCollectionCountIsOne)
+ if (record is not null && record.FilesCollectionCountIsOne)
{
- if (filePathsCollection is null)
- throw new NullReferenceException(nameof(filePathsCollection));
+ if (record.FilePathsCollection is null)
+ throw new NullReferenceException(nameof(record.FilePathsCollection));
string resultsGroupDirectory;
a2PeopleContentDirectory = null;
eDistanceContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", _Configuration.PropertyConfiguration.ResultContent);
@@ -1007,7 +1133,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
resultsGroupDirectory = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true);
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(resultsGroupDirectory);
}
- argZero = SaveUrlAndGetNewRootDirectory(filePathsCollection.First());
+ argZero = SaveUrlAndGetNewRootDirectory(record.FilePathsCollection.First());
_Configuration.PropertyConfiguration.ChangeRootDirectory(argZero);
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false);
@@ -1019,24 +1145,55 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
{
if (outputResolution.Any(char.IsNumber))
continue;
+ Dictionary exifDirectoriesById = [];
(cResultsFullGroupDirectory, _, _, _) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
- filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
- filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, directorySearchFilter, fileSearchFilter, filesCollectionRootDirectory, useCeilingAverage: true);
+ string? filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
+ ReadOnlyCollection>? filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, directorySearchFilter, fileSearchFilter, filesCollectionRootDirectory, useIgnoreExtensions: true, useCeilingAverage: true);
+ record = new(FilesCollectionRootDirectory: filesCollectionRootDirectory,
+ FilesCollectionCountIsOne: false,
+ FilePathsCollection: filePathsCollection,
+ ExifDirectoriesById: new(exifDirectoriesById),
+ IdToFilePaths: null,
+ SplatNineIdentifiers: null);
break;
}
}
- if (filesCollectionRootDirectory is null || filePathsCollection is null)
- throw new NullReferenceException(nameof(filePathsCollection));
- int count = filePathsCollection.Select(l => l.Count).Sum();
+ if (string.IsNullOrEmpty(record?.FilesCollectionRootDirectory) || record.FilePathsCollection.Count == 0)
+ throw new NullReferenceException(nameof(record.FilePathsCollection));
+ foreach (string checkDirectory in checkDirectories)
+ {
+ seasonDirectory = Path.Combine(checkDirectory, $"{dateTime.Year}.{season} {seasonName} {Path.GetFileName(checkDirectory)}");
+ if (!Directory.Exists(seasonDirectory))
+ _ = Directory.CreateDirectory(seasonDirectory);
+ }
+ int count = record.FilePathsCollection.Select(l => l.Count).Sum();
message = $") Building Container(s) - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
- _ProgressBar = new(count, message, options);
- ReadOnlyCollection readOnlyContainers = Container.Models.Stateless.Methods.IContainer.GetContainers(this, _Configuration.PropertyConfiguration, _Faces.FileNameExtension, _Faces.HiddenFileNameExtension, eDistanceContentDirectory, filesCollectionRootDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection);
+ _ProgressBar = new(count, message, _ProgressBarOptions);
+ ReadOnlyCollection readOnlyContainers =
+ Container.Models.Stateless.Methods.IContainer.GetContainers(dlibDotNet,
+ _Configuration.PropertyConfiguration,
+ _Faces.FileNameExtension,
+ _Faces.HiddenFileNameExtension,
+ eDistanceContentDirectory,
+ record.FilesCollectionRootDirectory,
+ record.IdToFilePaths,
+ record.SplatNineIdentifiers,
+ record.FilePathsCollection,
+ record.ExifDirectoriesById);
_ProgressBar.Dispose();
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleContentDirectory, a2PeopleSingletonDirectory, eDistanceContentDirectory);
DeleteContinueFiles(personContainers);
if (!runToDoCollectionFirst)
- MapFaceFileLogic(ticks, personContainers, mapLogic, a2PeopleContentDirectory, eDistanceContentDirectory, options);
- FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, fPhotoPrismSingletonDirectory, count, metadata, readOnlyContainers, propertyLogic, mapLogic);
+ MapFaceFileLogic(ticks, personContainers, mapLogic, a2PeopleContentDirectory, eDistanceContentDirectory);
+ FullDoWork(argZero,
+ propertyRoot,
+ ticks,
+ fPhotoPrismSingletonDirectory,
+ count,
+ metadata,
+ record,
+ readOnlyContainers,
+ mapLogic);
ReadOnlyCollection
- distinctValidImageItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true);
if (_Configuration.LookForAbandoned)
{
@@ -1044,9 +1201,9 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
string d2ResultsFullGroupDirectory;
foreach (string outputResolution in _Configuration.OutputResolutions)
{
- _ProgressBar = new(5, nameof(mapLogic.LookForAbandoned), options);
+ _ProgressBar = new(5, nameof(mapLogic.LookForAbandoned), _ProgressBarOptions);
(cResultsFullGroupDirectory, _, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
- mapLogic.LookForAbandoned(this, _Configuration.PropertyConfiguration, bResultsFullGroupDirectory, readOnlyContainers, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory);
+ mapLogic.LookForAbandoned(dlibDotNet, _Configuration.PropertyConfiguration, bResultsFullGroupDirectory, readOnlyContainers, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory);
_ProgressBar.Dispose();
}
}
@@ -1077,8 +1234,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
&& _Exceptions.Count == 0)
MapLogic(ticks, readOnlyContainers, fPhotoPrismContentDirectory, mapLogic, outputResolution, new(personKeyToIds), distinctValidImageFaces, distinctValidImageMappingCollection);
- if (runToDoCollectionFirst && _Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Count > 0 && splatNineIdentifiers is not null && distinctValidImageMappingCollection.Count > 0)
- _Random.Random(_Configuration.PropertyConfiguration, _Configuration.ImmichAssetsFile, _Configuration.ImmichOwnerId, _Configuration.ImmichRoot, _Configuration.RadomUseBirthdayMinimum, _Configuration.ValidKeyWordsToIgnoreInRandom, personKeyToIds, splatNineIdentifiers, distinctValidImageMappingCollection);
+ if (runToDoCollectionFirst && _Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Count > 0 && record?.SplatNineIdentifiers is not null && distinctValidImageMappingCollection.Count > 0)
+ _Random.Random(_Configuration.PropertyConfiguration, _Configuration.ImmichAssetsFile, _Configuration.ImmichOwnerId, _Configuration.ImmichRoot, _Configuration.RadomUseBirthdayMinimum, _Configuration.ValidKeyWordsToIgnoreInRandom, personKeyToIds, record.SplatNineIdentifiers, distinctValidImageMappingCollection);
if (_IsEnvironment.Development)
continue;
if (!_IsEnvironment.Development)
@@ -1096,19 +1253,37 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
}
}
- private (string, ReadOnlyCollection>, bool) GetFilesCollectionThenCopyOrMove(long ticks, string fileSearchFilter, string directorySearchFilter, ProgressBarOptions options, string outputResolution)
+ private Record GetFilesCollectionThenCopyOrMove(IDlibDotNet dlibDotNet, long ticks, string fileSearchFilter, string directorySearchFilter, string bResultsFullGroupDirectory, string outputResolution)
{
+ Record result;
+ int count;
+ string message;
ProgressBar progressBar;
- IDlibDotNet dlibDotNet = this;
+ const string extension = ".json";
+ ReadOnlyCollection filePairs;
+ int maxDegreeOfParallelism = Environment.ProcessorCount;
+ Dictionary exifDirectoriesById = [];
string filesCollectionRootDirectory = _Configuration.PropertyConfiguration.RootDirectory;
+ ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
(string cResultsFullGroupDirectory, _, _, _) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
- IReadOnlyDictionary>> fileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, [_Configuration.PropertyConfiguration.ResultContent]);
- ReadOnlyCollection> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, directorySearchFilter, fileSearchFilter, filesCollectionRootDirectory, useCeilingAverage: false);
- int count = filePathsCollection.Select(l => l.Count).Sum();
- bool filesCollectionCountIsOne = IsFilesCollectionCountIsOne(filePathsCollection);
- string message = $") Selecting for ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
- progressBar = new(count, message, options);
- (string[] distinctDirectories, List<(FilePath, string)> toDoCollection) = IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, filePathsCollection, fileGroups, () => progressBar.Tick());
+ string jsonGroupDirectory = Path.Combine(bResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton);
+ if (!Directory.Exists(jsonGroupDirectory))
+ _ = Directory.CreateDirectory(jsonGroupDirectory);
+ IReadOnlyDictionary>> keyValuePairs =
+ Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, [_Configuration.PropertyConfiguration.ResultContent]);
+ ReadOnlyDictionary> fileGroups = keyValuePairs[_Configuration.PropertyConfiguration.ResultContent];
+ ReadOnlyCollection> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, directorySearchFilter, fileSearchFilter, filesCollectionRootDirectory, useIgnoreExtensions: true, useCeilingAverage: false);
+ count = filePathsCollection.Select(l => l.Count).Sum();
+ filePairs = IFilePair.GetFilePairs(_Configuration.PropertyConfiguration, directorySearchFilter, extension, jsonGroupDirectory, filePathsCollection);
+ message = $") Preloading ExifDirectory Dictionary - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
+ progressBar = new(count, message, _ProgressBarOptions);
+ _ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(dlibDotNet, filePairs[i], exifDirectoriesById));
+ progressBar.Dispose();
+ count = filePathsCollection.Select(l => l.Count).Sum();
+ bool filesCollectionCountIsOne = GetFilesCollectionCountIsOne(filePathsCollection);
+ message = $") Selecting for ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
+ progressBar = new(count, message, _ProgressBarOptions);
+ (string[] distinctDirectories, List<(FilePath, string)> toDoCollection) = IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, filePathsCollection, fileGroups, exifDirectoriesById, () => progressBar.Tick());
progressBar.Dispose();
foreach (string distinctDirectory in distinctDirectories)
{
@@ -1116,13 +1291,21 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
_ = Directory.CreateDirectory(distinctDirectory);
}
message = $") Copying to ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
- progressBar = new(count, message, options);
+ progressBar = new(count, message, _ProgressBarOptions);
_ = IDirectory.CopyOrMove(toDoCollection, move: false, moveBack: false, () => progressBar.Tick());
progressBar.Dispose();
- return (filesCollectionRootDirectory, filePathsCollection, filesCollectionCountIsOne);
+ ReadOnlyDictionary> idToFilePaths = FilePath.GetKeyValuePairs(filePathsCollection);
+ ReadOnlyDictionary splatNineIdentifiers = GetSplatNineIdentifiersAndHideSplatNine(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, idToFilePaths);
+ result = new(ExifDirectoriesById: new(exifDirectoriesById),
+ FilesCollectionRootDirectory: filesCollectionRootDirectory,
+ FilesCollectionCountIsOne: filesCollectionCountIsOne,
+ FilePathsCollection: filePathsCollection,
+ IdToFilePaths: idToFilePaths,
+ SplatNineIdentifiers: splatNineIdentifiers);
+ return result;
}
- private void MapFaceFileLogic(long ticks, ReadOnlyCollection