added-numbers-to-distinguish-has-ignore-keyword-and-has-date-time-original
moved-container-to-new-project-to-prepare-to-remove-property-file added-logic-to-rename-to-3-and-7-like-should-ignore-for-missing-date-time-original
This commit is contained in:
parent
d9d55d9e4c
commit
d5fa108f81
@ -160,7 +160,7 @@ public class Compare
|
|||||||
}
|
}
|
||||||
if (_IsEnvironment.Development && propertyConfiguration.PopulatePropertyId)
|
if (_IsEnvironment.Development && propertyConfiguration.PopulatePropertyId)
|
||||||
throw new Exception("Copy keyValuePairs-####.json file");
|
throw new Exception("Copy keyValuePairs-####.json file");
|
||||||
(int j, int f, int t, Shared.Models.Container[] containers) = Shared.Models.Stateless.Methods.IContainer.GetContainers(propertyConfiguration, propertyLogic);
|
(int j, int f, int t, Shared.Models.Container[] containers) = Container.Models.Stateless.Methods.IContainer.GetContainers(propertyConfiguration, propertyLogic);
|
||||||
if (propertyLogic.ExceptionsDirectories.Any())
|
if (propertyLogic.ExceptionsDirectories.Any())
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
if (propertyConfiguration.PopulatePropertyId && Shared.Models.Stateless.Methods.IProperty.Any(containers))
|
if (propertyConfiguration.PopulatePropertyId && Shared.Models.Stateless.Methods.IProperty.Any(containers))
|
||||||
|
1
Container/.vscode/format-report.json
vendored
Normal file
1
Container/.vscode/format-report.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[]
|
8
Container/.vscode/settings.json
vendored
Normal file
8
Container/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"dlib",
|
||||||
|
"Exif",
|
||||||
|
"nosj",
|
||||||
|
"Serilog"
|
||||||
|
]
|
||||||
|
}
|
51
Container/Container.csproj
Normal file
51
Container/Container.csproj
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<OutputType>library</OutputType>
|
||||||
|
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<PackageId>Phares.View.by.Distance.Container</PackageId>
|
||||||
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||||
|
<Version>9.0.100.1</Version>
|
||||||
|
<Authors>Mike Phares</Authors>
|
||||||
|
<Company>Phares</Company>
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">
|
||||||
|
true
|
||||||
|
</IsWindows>
|
||||||
|
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
|
||||||
|
true
|
||||||
|
</IsOSX>
|
||||||
|
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">
|
||||||
|
true
|
||||||
|
</IsLinux>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(IsWindows)'=='true'">
|
||||||
|
<DefineConstants>Windows</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(IsOSX)'=='true'">
|
||||||
|
<DefineConstants>OSX</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(IsLinux)'=='true'">
|
||||||
|
<DefineConstants>Linux</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
|
||||||
|
<SupportedPlatform Include="browser" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MetadataExtractor" Version="2.8.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
|
||||||
|
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
|
||||||
|
<PackageReference Include="System.Drawing.Common" Version="8.0.10" />
|
||||||
|
<PackageReference Include="System.Text.Json" Version="9.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -1,7 +1,8 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using View_by_Distance.Shared.Models;
|
||||||
|
|
||||||
namespace View_by_Distance.Shared.Models;
|
namespace View_by_Distance.Container.Models;
|
||||||
|
|
||||||
public record Container(string SourceDirectory, ReadOnlyCollection<Item> Items)
|
public record Container(string SourceDirectory, ReadOnlyCollection<Item> Items)
|
||||||
{
|
{
|
664
Container/Models/Stateless/Methods/Container.cs
Normal file
664
Container/Models/Stateless/Methods/Container.cs
Normal file
@ -0,0 +1,664 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
namespace View_by_Distance.Container.Models.Stateless.Methods;
|
||||||
|
|
||||||
|
internal abstract class Container
|
||||||
|
{
|
||||||
|
|
||||||
|
private record FilePair(bool IsUnique, List<string> Collection, FilePath FilePath, Item Item) { }
|
||||||
|
|
||||||
|
internal static DateTime[] GetContainerDateTimes(ReadOnlyCollection<Item> items)
|
||||||
|
{
|
||||||
|
DateTime[] results;
|
||||||
|
long containerMinimumTicks = (from l in items select l.FilePath.LastWriteTicks).Min();
|
||||||
|
long containerMaximumTicks = (from l in items select l.FilePath.LastWriteTicks).Max();
|
||||||
|
results = [new(containerMinimumTicks), new(containerMaximumTicks)];
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container)
|
||||||
|
{
|
||||||
|
List<Item> results = [];
|
||||||
|
foreach (Item item in container.Items)
|
||||||
|
{
|
||||||
|
if (!item.IsValidImageFormatExtension || propertyConfiguration.IgnoreExtensions.Contains(item.FilePath.ExtensionLowered))
|
||||||
|
continue;
|
||||||
|
results.Add(item);
|
||||||
|
}
|
||||||
|
return container.Items.Count == results.Count ? container.Items : results.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
|
||||||
|
{
|
||||||
|
Dictionary<string, List<string>> results = [];
|
||||||
|
List<string>? collection;
|
||||||
|
string fileNameWithoutExtensionMinusOne;
|
||||||
|
foreach (ReadOnlyCollection<FilePath> 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 IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<string[]> filesCollection)
|
||||||
|
{
|
||||||
|
Dictionary<string, List<string>> results = [];
|
||||||
|
string fileNameWithoutExtension;
|
||||||
|
string fileNameWithoutExtensionSecond;
|
||||||
|
string fileNameWithoutExtensionSecondMinusOne;
|
||||||
|
List<string>? 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 bool AnyMoved(IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, List<string> renameCollection, string[] files)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
string checkFile;
|
||||||
|
string directory;
|
||||||
|
string fileNameWith;
|
||||||
|
string checkDirectory;
|
||||||
|
string directoryName;
|
||||||
|
List<string>? collection;
|
||||||
|
string fileNameWithoutExtension;
|
||||||
|
List<string> 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 int LookForAbandoned(ReadOnlyCollection<string[]> jsonFilesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
bool check;
|
||||||
|
bool moved = false;
|
||||||
|
List<string> 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 List<Shared.Models.FilePair> GetFilePairs(IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string jsonGroupDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles)
|
||||||
|
{
|
||||||
|
List<Shared.Models.FilePair>? results = null;
|
||||||
|
int renamed;
|
||||||
|
const bool useCeilingAverage = true;
|
||||||
|
ReadOnlyCollection<string[]>? jsonFilesCollection = null;
|
||||||
|
IReadOnlyDictionary<string, List<string>>? 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 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 MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, string fullFileName)
|
||||||
|
{
|
||||||
|
string[] segments = directory.Split(cei.Combined);
|
||||||
|
string? checkDirectory = segments.Length == 1 ?
|
||||||
|
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
||||||
|
segments.Length == 2 ?
|
||||||
|
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
||||||
|
null;
|
||||||
|
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
||||||
|
{
|
||||||
|
string checkFile = Path.Combine(checkDirectory, fileName);
|
||||||
|
if (File.Exists(checkFile))
|
||||||
|
File.Move(checkFile, fullFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RenameFile(string extension, Shared.Models.FilePair filePair, FilePath filePath, char change, ReadOnlyCollection<FilePath> filePaths)
|
||||||
|
{
|
||||||
|
string checkFile;
|
||||||
|
if (filePath.DirectoryFullPath.Contains("Results") && filePath.DirectoryFullPath.Contains("Resize"))
|
||||||
|
File.Delete(filePath.FullName);
|
||||||
|
if (!string.IsNullOrEmpty(filePair.Match))
|
||||||
|
{
|
||||||
|
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}");
|
||||||
|
if (!File.Exists(checkFile))
|
||||||
|
File.Move(filePair.Match, checkFile);
|
||||||
|
}
|
||||||
|
foreach (FilePath f in filePaths)
|
||||||
|
{
|
||||||
|
checkFile = Path.Combine(f.DirectoryFullPath, $"{f.NameWithoutExtension[..^1]}{change}{f.ExtensionLowered}");
|
||||||
|
if (File.Exists(checkFile))
|
||||||
|
continue;
|
||||||
|
File.Move(f.FullName, checkFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ParallelFor(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, int rootDirectoryLength, Shared.Models.FilePair filePair, List<FilePair> 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)
|
||||||
|
{
|
||||||
|
char? change;
|
||||||
|
ReadOnlyCollection<FilePath>? filePaths = null;
|
||||||
|
char hasIgnoreKeyword = IId.GetHasIgnoreKeyword(filePath).ToString()[0];
|
||||||
|
char hasDateTimeOriginal = IId.GetHasDateTimeOriginal(filePath).ToString()[0];
|
||||||
|
char missingDateTimeOriginal = IId.GetMissingDateTimeOriginal(filePath).ToString()[0];
|
||||||
|
if (shouldIgnore is not null && shouldIgnore.Value)
|
||||||
|
{
|
||||||
|
if (filePath.NameWithoutExtension[^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}>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((shouldIgnore is null || !shouldIgnore.Value) && property.DateTimeOriginal is null)
|
||||||
|
{
|
||||||
|
if (filePath.NameWithoutExtension[^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}>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (filePath.NameWithoutExtension[^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}>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
change = null;
|
||||||
|
if (filePaths is not null && change is not null)
|
||||||
|
RenameFile(extension, 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;
|
||||||
|
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 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)
|
||||||
|
{
|
||||||
|
File.SetCreationTime(sourceDirectoryFileHolder.FullName, new(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);
|
||||||
|
lock (results)
|
||||||
|
results.Add(new(filePair.IsUnique, filePair.Collection, filePath, item));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<FilePair> GetFilePairs(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
|
||||||
|
{
|
||||||
|
List<FilePair> results = [];
|
||||||
|
const string extension = ".json";
|
||||||
|
List<Shared.Models.FilePair> filePairs;
|
||||||
|
string jsonGroupDirectory = aPropertySingletonDirectory;
|
||||||
|
int maxDegreeOfParallelism = Environment.ProcessorCount;
|
||||||
|
int filesCollectionDirectoryLength = filesCollectionDirectory.Length;
|
||||||
|
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||||
|
IReadOnlyDictionary<string, List<string>> fileNamesToFiles = GetFilesKeyValuePairs(filePathsCollection);
|
||||||
|
filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, jsonGroupDirectory, filePathsCollection, fileNamesToFiles);
|
||||||
|
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) =>
|
||||||
|
ParallelFor(dlibDotNet, propertyConfiguration, jsonGroupDirectory, extension, keyValuePairs, splatNineIdentifiers, filesCollectionDirectoryLength, filePairs[i], results));
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (int, Models.Container[]) GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
|
||||||
|
{
|
||||||
|
List<Models.Container> results = [];
|
||||||
|
string directory;
|
||||||
|
List<Item>? items;
|
||||||
|
Models.Container container;
|
||||||
|
List<string> directories = [];
|
||||||
|
Dictionary<string, List<Item>> directoryToItems = [];
|
||||||
|
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
|
||||||
|
{
|
||||||
|
if (filePaths.Count == 0)
|
||||||
|
continue;
|
||||||
|
directory = filePaths[0].DirectoryFullPath;
|
||||||
|
if (directory is null)
|
||||||
|
continue;
|
||||||
|
if (!directories.Contains(directory))
|
||||||
|
directories.Add(directory);
|
||||||
|
if (!directoryToItems.TryGetValue(directory, out items))
|
||||||
|
{
|
||||||
|
directoryToItems.Add(directory, []);
|
||||||
|
if (!directoryToItems.TryGetValue(directory, out items))
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(string aResultsFullGroupDirectory, _) = dlibDotNet.GetResultsFullGroupDirectories();
|
||||||
|
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
|
||||||
|
if (!Directory.Exists(aPropertySingletonDirectory))
|
||||||
|
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
|
||||||
|
List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
|
||||||
|
foreach (FilePair filePair in filePairs)
|
||||||
|
{
|
||||||
|
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
|
||||||
|
{
|
||||||
|
directoryToItems.Add(filePair.FilePath.DirectoryFullPath, []);
|
||||||
|
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
items.Add(filePair.Item);
|
||||||
|
}
|
||||||
|
foreach (KeyValuePair<string, List<Item>> keyValuePair in directoryToItems)
|
||||||
|
{
|
||||||
|
if (keyValuePair.Value.Count == 0)
|
||||||
|
continue;
|
||||||
|
container = new(keyValuePair.Key, new(keyValuePair.Value));
|
||||||
|
results.Add(container);
|
||||||
|
}
|
||||||
|
return (filePairs.Count, results.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AnyMovedFace(IReadOnlyDictionary<string, List<string>> fileNamesToFiles, List<string> directories)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
string checkFile;
|
||||||
|
string subDirectory;
|
||||||
|
string directoryName;
|
||||||
|
string checkDirectory;
|
||||||
|
List<string>? collection;
|
||||||
|
string directoryNameWith;
|
||||||
|
string directoryNameMinusOne;
|
||||||
|
List<string> 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 AnyMovedFace(string extension, string hiddenExtension, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string jsonGroupDirectory)
|
||||||
|
{
|
||||||
|
string directory;
|
||||||
|
string checkFile;
|
||||||
|
string directoryName;
|
||||||
|
List<string> files = [];
|
||||||
|
string[] fileNameSegments;
|
||||||
|
List<string> 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 AnyMovedDistance(string extension, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string jsonGroupDirectory)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
string fileName;
|
||||||
|
string checkFile;
|
||||||
|
string directory;
|
||||||
|
List<string>? collection;
|
||||||
|
string[] fileNameSegments;
|
||||||
|
List<string> 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 void DoGetFilePairsForRemaining(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
|
||||||
|
{
|
||||||
|
const string extension = ".json";
|
||||||
|
(_, string bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
|
||||||
|
IReadOnlyDictionary<string, List<string>> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> 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 IDlibDotNet GetDlibDotNet() =>
|
||||||
|
throw new NotImplementedException();
|
||||||
|
|
||||||
|
internal static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string _)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
Models.Container[] results;
|
||||||
|
const bool useCeilingAverage = true;
|
||||||
|
const string fileSearchFilter = "*";
|
||||||
|
IDlibDotNet dlibDotNet = GetDlibDotNet();
|
||||||
|
const string directorySearchFilter = "*";
|
||||||
|
ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs = null;
|
||||||
|
ReadOnlyCollection<string[]> filesCollection = IDirectory.GetFilesCollection(propertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
|
||||||
|
ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
|
||||||
|
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, propertyConfiguration.RootDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
|
||||||
|
return (count, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<int> GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers)
|
||||||
|
{
|
||||||
|
List<int> results = [];
|
||||||
|
ReadOnlyCollection<Item> filteredItems;
|
||||||
|
foreach (Models.Container container in readOnlyContainers)
|
||||||
|
{
|
||||||
|
if (container.Items.Count == 0)
|
||||||
|
continue;
|
||||||
|
filteredItems = GetValidImageItems(propertyConfiguration, container);
|
||||||
|
if (filteredItems.Count == 0)
|
||||||
|
continue;
|
||||||
|
foreach (Item item in filteredItems)
|
||||||
|
{
|
||||||
|
if (item.Property?.Id is null || item.ResizedFileHolder is null)
|
||||||
|
continue;
|
||||||
|
if (results.Contains(item.Property.Id.Value))
|
||||||
|
continue;
|
||||||
|
results.Add(item.Property.Id.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<string> GetFilteredDistinctFileNameFirstSegments(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers)
|
||||||
|
{
|
||||||
|
List<string> results = [];
|
||||||
|
ReadOnlyCollection<Item> filteredItems;
|
||||||
|
foreach (Models.Container container in readOnlyContainers)
|
||||||
|
{
|
||||||
|
if (container.Items.Count == 0)
|
||||||
|
continue;
|
||||||
|
filteredItems = GetValidImageItems(propertyConfiguration, container);
|
||||||
|
if (filteredItems.Count == 0)
|
||||||
|
continue;
|
||||||
|
foreach (Item item in filteredItems)
|
||||||
|
{
|
||||||
|
if (item.Property?.Id is null || item.ResizedFileHolder is null)
|
||||||
|
continue;
|
||||||
|
if (results.Contains(item.FilePath.FileNameFirstSegment))
|
||||||
|
continue;
|
||||||
|
results.Add(item.FilePath.FileNameFirstSegment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems)
|
||||||
|
{
|
||||||
|
List<Item> results = [];
|
||||||
|
List<int> distinct = [];
|
||||||
|
ReadOnlyCollection<Item> filteredItems;
|
||||||
|
foreach (Models.Container container in containers)
|
||||||
|
{
|
||||||
|
if (container.Items.Count == 0)
|
||||||
|
continue;
|
||||||
|
if (!filterItems)
|
||||||
|
filteredItems = container.Items;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filteredItems = GetValidImageItems(propertyConfiguration, container);
|
||||||
|
if (filteredItems.Count == 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach (Item item in filteredItems)
|
||||||
|
{
|
||||||
|
if (item.Property?.Id is null || item.ResizedFileHolder is null)
|
||||||
|
continue;
|
||||||
|
if (distinctItems)
|
||||||
|
{
|
||||||
|
if (distinct.Contains(item.Property.Id.Value))
|
||||||
|
continue;
|
||||||
|
distinct.Add(item.Property.Id.Value);
|
||||||
|
}
|
||||||
|
results.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
51
Container/Models/Stateless/Methods/IContainer.cs
Normal file
51
Container/Models/Stateless/Methods/IContainer.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using View_by_Distance.Shared.Models;
|
||||||
|
using View_by_Distance.Shared.Models.Properties;
|
||||||
|
using View_by_Distance.Shared.Models.Stateless.Methods;
|
||||||
|
|
||||||
|
namespace View_by_Distance.Container.Models.Stateless.Methods;
|
||||||
|
|
||||||
|
public interface IContainer
|
||||||
|
{
|
||||||
|
|
||||||
|
DateTime[] TestStatic_GetContainerDateTimes(ReadOnlyCollection<Item> items) =>
|
||||||
|
GetContainerDateTimes(items);
|
||||||
|
static DateTime[] GetContainerDateTimes(ReadOnlyCollection<Item> items) =>
|
||||||
|
Container.GetContainerDateTimes(items);
|
||||||
|
|
||||||
|
ReadOnlyCollection<Item> TestStatic_GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
||||||
|
GetValidImageItems(propertyConfiguration, container);
|
||||||
|
static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
||||||
|
Container.GetValidImageItems(propertyConfiguration, container);
|
||||||
|
|
||||||
|
(int, Models.Container[]) TestStatic_GetContainers(IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
||||||
|
GetContainers(propertyConfiguration, aPropertySingletonDirectory);
|
||||||
|
static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
||||||
|
GetContainers(propertyConfiguration, null, aPropertySingletonDirectory);
|
||||||
|
|
||||||
|
(int, Models.Container[]) TestStatic_GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
|
||||||
|
GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
|
||||||
|
static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
|
||||||
|
Container.GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
|
||||||
|
|
||||||
|
ReadOnlyCollection<Models.Container> TestStatic_GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
|
||||||
|
GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection);
|
||||||
|
static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
|
||||||
|
Container.GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection);
|
||||||
|
|
||||||
|
List<int> TestStatic_GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
||||||
|
GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
||||||
|
static List<int> GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
||||||
|
Container.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
||||||
|
|
||||||
|
List<string> TestStatic_GetFilteredDistinctFileNameFirstSegments(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
||||||
|
GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
||||||
|
static List<string> GetFilteredDistinctFileNameFirstSegments(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
||||||
|
Container.GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
||||||
|
|
||||||
|
ReadOnlyCollection<Item> TestStatic_GetValidImageItems(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
|
||||||
|
GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
|
||||||
|
static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
|
||||||
|
Container.GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
|
||||||
|
|
||||||
|
}
|
@ -57,11 +57,11 @@ public class DateGroup
|
|||||||
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, "{}");
|
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, "{}");
|
||||||
if (!Directory.Exists(aPropertySingletonDirectory))
|
if (!Directory.Exists(aPropertySingletonDirectory))
|
||||||
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
|
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
|
||||||
(int t, Container[] containers) = Shared.Models.Stateless.Methods.IContainer.GetContainers(propertyConfiguration, aPropertySingletonDirectory);
|
(int t, Container.Models.Container[] containers) = Container.Models.Stateless.Methods.IContainer.GetContainers(propertyConfiguration, aPropertySingletonDirectory);
|
||||||
A_Property propertyLogic = GetPropertyLogic(reverse, aResultsFullGroupDirectory, aResultsFullGroupDirectory);
|
A_Property propertyLogic = GetPropertyLogic(reverse, aResultsFullGroupDirectory, aResultsFullGroupDirectory);
|
||||||
if (propertyLogic.ExceptionsDirectories.Count != 0)
|
if (propertyLogic.ExceptionsDirectories.Count != 0)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
if (propertyConfiguration.PopulatePropertyId && (configuration.ByCreateDateShortcut || configuration.ByHash) && Shared.Models.Stateless.Methods.IProperty.Any(containers))
|
if (propertyConfiguration.PopulatePropertyId && (configuration.ByCreateDateShortcut || configuration.ByHash) && Property.Models.Stateless.IProperty.Any(containers))
|
||||||
{
|
{
|
||||||
propertyLogic.SavePropertyParallelWork(ticks, metadata, t, containers);
|
propertyLogic.SavePropertyParallelWork(ticks, metadata, t, containers);
|
||||||
if (propertyLogic.ExceptionsDirectories.Count != 0)
|
if (propertyLogic.ExceptionsDirectories.Count != 0)
|
||||||
@ -302,7 +302,7 @@ public class DateGroup
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Item[] GetFilterItems(Container container)
|
private static Item[] GetFilterItems(Container.Models.Container container)
|
||||||
{
|
{
|
||||||
List<Item> results = [];
|
List<Item> results = [];
|
||||||
foreach (Item item in container.Items)
|
foreach (Item item in container.Items)
|
||||||
@ -313,7 +313,7 @@ public class DateGroup
|
|||||||
return results.ToArray();
|
return results.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private (Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] GetFileMoveCollectionAll(Property.Models.Configuration configuration, string destinationRoot, Container[] containers)
|
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 Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] results;
|
||||||
Item[] filteredItems;
|
Item[] filteredItems;
|
||||||
@ -322,7 +322,7 @@ public class DateGroup
|
|||||||
string destinationDirectory;
|
string destinationDirectory;
|
||||||
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollection = [];
|
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollection = [];
|
||||||
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollectionDirectory;
|
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollectionDirectory;
|
||||||
foreach (Container container in containers)
|
foreach (Container.Models.Container container in containers)
|
||||||
{
|
{
|
||||||
if (container.Items.Count == 0)
|
if (container.Items.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
@ -352,7 +352,7 @@ public class DateGroup
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MoveFiles(Property.Models.Configuration configuration, string destinationRoot, Container[] containers)
|
private void MoveFiles(Property.Models.Configuration configuration, string destinationRoot, Container.Models.Container[] containers)
|
||||||
{
|
{
|
||||||
string checkDirectory;
|
string checkDirectory;
|
||||||
bool hasDuplicate;
|
bool hasDuplicate;
|
||||||
@ -453,7 +453,7 @@ public class DateGroup
|
|||||||
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(configuration.RootDirectory);
|
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(configuration.RootDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CreateDateShortcut(Property.Models.Configuration configuration, Container[] containers)
|
private static void CreateDateShortcut(Property.Models.Configuration configuration, Container.Models.Container[] containers)
|
||||||
{
|
{
|
||||||
string path;
|
string path;
|
||||||
string fileName;
|
string fileName;
|
||||||
@ -468,17 +468,17 @@ public class DateGroup
|
|||||||
WindowsShortcut windowsShortcut;
|
WindowsShortcut windowsShortcut;
|
||||||
TimeSpan threeStandardDeviationHigh;
|
TimeSpan threeStandardDeviationHigh;
|
||||||
string aPropertyContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "()");
|
string aPropertyContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "()");
|
||||||
foreach (Container container in containers)
|
foreach (Container.Models.Container container in containers)
|
||||||
{
|
{
|
||||||
if (container.Items.Count == 0)
|
if (container.Items.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
selectedTotal = 0;
|
selectedTotal = 0;
|
||||||
threeStandardDeviationHigh = Shared.Models.Stateless.Methods.IProperty.GetThreeStandardDeviationHigh(minimum, container);
|
threeStandardDeviationHigh = Property.Models.Stateless.IProperty.GetThreeStandardDeviationHigh(minimum, container);
|
||||||
if (threeStandardDeviationHigh.TotalHours > maximumHours)
|
if (threeStandardDeviationHigh.TotalHours > maximumHours)
|
||||||
threeStandardDeviationHigh = new(maximumHours, 0, 0);
|
threeStandardDeviationHigh = new(maximumHours, 0, 0);
|
||||||
for (int i = 0; i < container.Items.Count; i++)
|
for (int i = 0; i < container.Items.Count; i++)
|
||||||
{
|
{
|
||||||
(i, dateTimes, selectedItems) = Shared.Models.Stateless.Methods.IProperty.Get(container, threeStandardDeviationHigh, i);
|
(i, dateTimes, selectedItems) = Property.Models.Stateless.IProperty.Get(container, threeStandardDeviationHigh, i);
|
||||||
selectedTotal += selectedItems.Count;
|
selectedTotal += selectedItems.Count;
|
||||||
foreach (Item item in selectedItems)
|
foreach (Item item in selectedItems)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />
|
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />
|
||||||
<ProjectReference Include="..\Metadata\Metadata.csproj" />
|
<ProjectReference Include="..\Metadata\Metadata.csproj" />
|
||||||
|
<ProjectReference Include="..\Container\Container.csproj" />
|
||||||
<ProjectReference Include="..\Property\Property.csproj" />
|
<ProjectReference Include="..\Property\Property.csproj" />
|
||||||
<ProjectReference Include="..\Resize\Resize.csproj" />
|
<ProjectReference Include="..\Resize\Resize.csproj" />
|
||||||
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||||
|
@ -107,9 +107,9 @@ public partial class DragDropSearch : Form
|
|||||||
|
|
||||||
private void LoadData()
|
private void LoadData()
|
||||||
{
|
{
|
||||||
Container[] containers;
|
Container.Models.Container[] containers;
|
||||||
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "{}");
|
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "{}");
|
||||||
(_, containers) = IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory);
|
(_, containers) = View_by_Distance.Container.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory);
|
||||||
List<Item> collection = Program.GetItemCollection(_Configuration, containers);
|
List<Item> collection = Program.GetItemCollection(_Configuration, containers);
|
||||||
foreach (Item item in collection)
|
foreach (Item item in collection)
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ public class Program
|
|||||||
// ApplicationConfiguration.Initialize();
|
// ApplicationConfiguration.Initialize();
|
||||||
Application.Run(new DragDropSearch());
|
Application.Run(new DragDropSearch());
|
||||||
|
|
||||||
private static Item[] GetFilterItems(Models.Configuration configuration, Container container)
|
private static Item[] GetFilterItems(Models.Configuration configuration, Container.Models.Container container)
|
||||||
{
|
{
|
||||||
List<Item> results = [];
|
List<Item> results = [];
|
||||||
foreach (Item item in container.Items)
|
foreach (Item item in container.Items)
|
||||||
@ -24,11 +24,11 @@ public class Program
|
|||||||
return results.ToArray();
|
return results.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Item> GetItemCollection(Models.Configuration configuration, Container[] containers)
|
public static List<Item> GetItemCollection(Models.Configuration configuration, Container.Models.Container[] containers)
|
||||||
{
|
{
|
||||||
List<Item> results = [];
|
List<Item> results = [];
|
||||||
Item[] filteredItems;
|
Item[] filteredItems;
|
||||||
foreach (Container container in containers)
|
foreach (Container.Models.Container container in containers)
|
||||||
{
|
{
|
||||||
if (container.Items.Count == 0)
|
if (container.Items.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -30,7 +30,7 @@ public class DuplicateSearch
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Configuration.Verify(configuration, requireExist: false);
|
Configuration.Verify(configuration, requireExist: false);
|
||||||
Container[] containers = GetContainers(ticks, configuration);
|
Container.Models.Container[] containers = GetContainers(ticks, configuration);
|
||||||
string argZero = args.Count > 0 ? Path.GetFullPath(args[0]) : Path.GetFullPath(configuration.RootDirectory);
|
string argZero = args.Count > 0 ? Path.GetFullPath(args[0]) : Path.GetFullPath(configuration.RootDirectory);
|
||||||
bool argZeroIsConfigurationRootDirectory = configuration.RootDirectory == argZero;
|
bool argZeroIsConfigurationRootDirectory = configuration.RootDirectory == argZero;
|
||||||
string destinationRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, "Z) Moved");
|
string destinationRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, "Z) Moved");
|
||||||
@ -125,10 +125,10 @@ public class DuplicateSearch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Container[] GetContainers(long ticks, Configuration configuration)
|
private static Container.Models.Container[] GetContainers(long ticks, Configuration configuration)
|
||||||
{
|
{
|
||||||
int f;
|
int f;
|
||||||
Container[] containers;
|
Container.Models.Container[] containers;
|
||||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||||
string message = $") Building Container(s) - {totalSeconds} total second(s)";
|
string message = $") Building Container(s) - {totalSeconds} total second(s)";
|
||||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||||
@ -136,12 +136,12 @@ public class DuplicateSearch
|
|||||||
{
|
{
|
||||||
progressBar.Tick();
|
progressBar.Tick();
|
||||||
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
|
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
|
||||||
(f, containers) = Shared.Models.Stateless.Methods.IContainer.GetContainers(configuration, aPropertySingletonDirectory);
|
(f, containers) = Container.Models.Stateless.Methods.IContainer.GetContainers(configuration, aPropertySingletonDirectory);
|
||||||
}
|
}
|
||||||
return containers;
|
return containers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dictionary<int, List<MappingFromItem?>> GetIdToCollection(string argZero, Configuration configuration, bool argZeroIsConfigurationRootDirectory, Container[] containers, string destinationRoot, List<int> preloadIds)
|
private static Dictionary<int, List<MappingFromItem?>> GetIdToCollection(string argZero, Configuration configuration, bool argZeroIsConfigurationRootDirectory, Container.Models.Container[] containers, string destinationRoot, List<int> preloadIds)
|
||||||
{
|
{
|
||||||
Dictionary<int, List<MappingFromItem?>> results = [];
|
Dictionary<int, List<MappingFromItem?>> results = [];
|
||||||
string directory;
|
string directory;
|
||||||
@ -157,16 +157,16 @@ public class DuplicateSearch
|
|||||||
foreach (int id in preloadIds)
|
foreach (int id in preloadIds)
|
||||||
results.Add(id, [null]);
|
results.Add(id, [null]);
|
||||||
}
|
}
|
||||||
foreach (Container container in containers)
|
foreach (Container.Models.Container container in containers)
|
||||||
{
|
{
|
||||||
if (container.Items.Count == 0)
|
if (container.Items.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
if (!argZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
|
if (!argZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
|
||||||
continue;
|
continue;
|
||||||
validImageItems = Shared.Models.Stateless.Methods.IContainer.GetValidImageItems(configuration, container);
|
validImageItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(configuration, container);
|
||||||
if (validImageItems.Count == 0)
|
if (validImageItems.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(validImageItems);
|
containerDateTimes = Container.Models.Stateless.Methods.IContainer.GetContainerDateTimes(validImageItems);
|
||||||
foreach (Item item in validImageItems)
|
foreach (Item item in validImageItems)
|
||||||
{
|
{
|
||||||
if (item.Property?.Id is null)
|
if (item.Property?.Id is null)
|
||||||
|
@ -403,7 +403,7 @@ public class D2_FaceParts
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveFaceLandmarkImages(Configuration configuration, string d2ResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces, bool saveRotated)
|
public void SaveFaceLandmarkImages(Property.Models.Configuration configuration, string d2ResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces, bool saveRotated)
|
||||||
{
|
{
|
||||||
FileInfo fileInfo;
|
FileInfo fileInfo;
|
||||||
bool check = false;
|
bool check = false;
|
||||||
|
@ -300,6 +300,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
string message;
|
string message;
|
||||||
MapLogic? mapLogic;
|
MapLogic? mapLogic;
|
||||||
A_Property propertyLogic;
|
A_Property propertyLogic;
|
||||||
|
IDlibDotNet dlibDotNet = this;
|
||||||
string eDistanceContentDirectory;
|
string eDistanceContentDirectory;
|
||||||
string? a2PeopleContentDirectory;
|
string? a2PeopleContentDirectory;
|
||||||
string aResultsFullGroupDirectory;
|
string aResultsFullGroupDirectory;
|
||||||
@ -314,15 +315,17 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
bool configurationOutputResolutionsHas = false;
|
bool configurationOutputResolutionsHas = false;
|
||||||
ReadOnlyDictionary<long, List<int>> personKeyToIds;
|
ReadOnlyDictionary<long, List<int>> personKeyToIds;
|
||||||
ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers = null;
|
ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers = null;
|
||||||
|
ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs = null;
|
||||||
ReadOnlyCollection<ReadOnlyCollection<FilePath>>? filePathsCollection = null;
|
ReadOnlyCollection<ReadOnlyCollection<FilePath>>? filePathsCollection = null;
|
||||||
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(_Configuration, ticks);
|
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(_Configuration, ticks);
|
||||||
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
|
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
|
||||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||||
Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory, ticks);
|
Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory, ticks);
|
||||||
a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])");
|
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);
|
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);
|
string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), _Configuration.PropertyConfiguration.ResultSingleton);
|
||||||
_ = Directory.CreateDirectory(Path.Combine(eDistanceContentDirectory, $"{ticks}"));
|
_ = Directory.CreateDirectory(Path.Combine(eDistanceContentDirectory, ticks.ToString()));
|
||||||
if (runToDoCollectionFirst)
|
if (runToDoCollectionFirst)
|
||||||
mapLogic = null;
|
mapLogic = null;
|
||||||
else
|
else
|
||||||
@ -335,7 +338,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
if (!runToDoCollectionFirst)
|
if (!runToDoCollectionFirst)
|
||||||
break;
|
break;
|
||||||
(filesCollectionRootDirectory, filePathsCollection, filesCollectionCountIsOne) = GetFilesCollectionThenCopyOrMove(ticks, fileSearchFilter, directorySearchFilter, options, outputResolution);
|
(filesCollectionRootDirectory, filePathsCollection, filesCollectionCountIsOne) = GetFilesCollectionThenCopyOrMove(ticks, fileSearchFilter, directorySearchFilter, options, outputResolution);
|
||||||
splatNineIdentifiers = GetSplatNineIdentifiersAndHideSplatNine(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, filePathsCollection);
|
keyValuePairs = FilePath.GetKeyValuePairs(filePathsCollection);
|
||||||
|
splatNineIdentifiers = GetSplatNineIdentifiersAndHideSplatNine(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, keyValuePairs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fPhotoPrismContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), _Configuration.PropertyConfiguration.ResultContent);
|
fPhotoPrismContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), _Configuration.PropertyConfiguration.ResultContent);
|
||||||
@ -357,7 +361,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
}
|
}
|
||||||
argZero = SaveUrlAndGetNewRootDirectory(filePathsCollection.First());
|
argZero = SaveUrlAndGetNewRootDirectory(filePathsCollection.First());
|
||||||
_Configuration.PropertyConfiguration.ChangeRootDirectory(argZero);
|
_Configuration.PropertyConfiguration.ChangeRootDirectory(argZero);
|
||||||
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
|
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
|
||||||
propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false);
|
propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false);
|
||||||
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory);
|
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory);
|
||||||
}
|
}
|
||||||
@ -367,7 +371,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
{
|
{
|
||||||
if (outputResolution.Any(char.IsNumber))
|
if (outputResolution.Any(char.IsNumber))
|
||||||
continue;
|
continue;
|
||||||
(cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution);
|
(cResultsFullGroupDirectory, _, _, _) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
|
||||||
filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
|
filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
|
||||||
filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, directorySearchFilter, fileSearchFilter, filesCollectionRootDirectory, useCeilingAverage: true);
|
filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, directorySearchFilter, fileSearchFilter, filesCollectionRootDirectory, useCeilingAverage: true);
|
||||||
break;
|
break;
|
||||||
@ -375,20 +379,17 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
}
|
}
|
||||||
if (filesCollectionRootDirectory is null || filePathsCollection is null)
|
if (filesCollectionRootDirectory is null || filePathsCollection is null)
|
||||||
throw new NullReferenceException(nameof(filePathsCollection));
|
throw new NullReferenceException(nameof(filePathsCollection));
|
||||||
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton);
|
|
||||||
if (!Directory.Exists(aPropertySingletonDirectory))
|
|
||||||
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
|
|
||||||
int count = filePathsCollection.Select(l => l.Count).Sum();
|
int count = filePathsCollection.Select(l => l.Count).Sum();
|
||||||
message = $") Building Container(s) - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
message = $") Building Container(s) - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
||||||
_ProgressBar = new(count, message, options);
|
_ProgressBar = new(count, message, options);
|
||||||
ReadOnlyCollection<Container> readOnlyContainers = Shared.Models.Stateless.Methods.IContainer.GetContainers(this, _Configuration.PropertyConfiguration, aPropertySingletonDirectory, filesCollectionRootDirectory, splatNineIdentifiers, filePathsCollection);
|
ReadOnlyCollection<Container.Models.Container> readOnlyContainers = Container.Models.Stateless.Methods.IContainer.GetContainers(this, _Configuration.PropertyConfiguration, _Faces.FileNameExtension, _Faces.HiddenFileNameExtension, eDistanceContentDirectory, filesCollectionRootDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection);
|
||||||
_ProgressBar.Dispose();
|
_ProgressBar.Dispose();
|
||||||
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleContentDirectory, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleContentDirectory, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
||||||
DeleteContinueFiles(personContainers);
|
DeleteContinueFiles(personContainers);
|
||||||
if (!runToDoCollectionFirst)
|
if (!runToDoCollectionFirst)
|
||||||
MapFaceFileLogic(ticks, personContainers, mapLogic, a2PeopleContentDirectory, eDistanceContentDirectory, options);
|
MapFaceFileLogic(ticks, personContainers, mapLogic, a2PeopleContentDirectory, eDistanceContentDirectory, options);
|
||||||
FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, fPhotoPrismSingletonDirectory, count, readOnlyContainers, propertyLogic, mapLogic);
|
FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, fPhotoPrismSingletonDirectory, count, metadata, readOnlyContainers, propertyLogic, mapLogic);
|
||||||
ReadOnlyCollection<Item> distinctValidImageItems = Shared.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true);
|
ReadOnlyCollection<Item> distinctValidImageItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true);
|
||||||
if (_Configuration.LookForAbandoned)
|
if (_Configuration.LookForAbandoned)
|
||||||
{
|
{
|
||||||
string dResultsFullGroupDirectory;
|
string dResultsFullGroupDirectory;
|
||||||
@ -396,7 +397,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
foreach (string outputResolution in _Configuration.OutputResolutions)
|
foreach (string outputResolution in _Configuration.OutputResolutions)
|
||||||
{
|
{
|
||||||
_ProgressBar = new(5, nameof(mapLogic.LookForAbandoned), options);
|
_ProgressBar = new(5, nameof(mapLogic.LookForAbandoned), options);
|
||||||
(cResultsFullGroupDirectory, _, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution);
|
(cResultsFullGroupDirectory, _, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
|
||||||
mapLogic.LookForAbandoned(this, _Configuration.PropertyConfiguration, bResultsFullGroupDirectory, readOnlyContainers, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory);
|
mapLogic.LookForAbandoned(this, _Configuration.PropertyConfiguration, bResultsFullGroupDirectory, readOnlyContainers, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory);
|
||||||
_ProgressBar.Dispose();
|
_ProgressBar.Dispose();
|
||||||
}
|
}
|
||||||
@ -437,7 +438,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
string dResultsFullGroupDirectory;
|
string dResultsFullGroupDirectory;
|
||||||
string c2ResultsFullGroupDirectory;
|
string c2ResultsFullGroupDirectory;
|
||||||
string d2ResultsFullGroupDirectory;
|
string d2ResultsFullGroupDirectory;
|
||||||
(cResultsFullGroupDirectory, c2ResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution);
|
(cResultsFullGroupDirectory, c2ResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
|
||||||
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(aResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
|
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(aResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
|
||||||
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(bResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
|
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(bResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
|
||||||
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
|
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
|
||||||
@ -549,33 +550,32 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string fPhotoPrismSingletonDirectory, int count, ReadOnlyCollection<Container> readOnlyContainers, A_Property propertyLogic, MapLogic mapLogic)
|
private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string fPhotoPrismSingletonDirectory, int count, B_Metadata metadata, ReadOnlyCollection<Container.Models.Container> readOnlyContainers, A_Property propertyLogic, MapLogic mapLogic)
|
||||||
{
|
{
|
||||||
int total;
|
int total;
|
||||||
int notMapped;
|
int notMapped;
|
||||||
string message;
|
string message;
|
||||||
bool exceptions;
|
bool exceptions;
|
||||||
int totalSeconds;
|
int totalSeconds;
|
||||||
Container container;
|
|
||||||
int totalNotMapped = 0;
|
int totalNotMapped = 0;
|
||||||
|
IDlibDotNet dlibDotNet = this;
|
||||||
bool outputResolutionHasNumber;
|
bool outputResolutionHasNumber;
|
||||||
bool anyNullOrNoIsUniqueFileName;
|
bool anyNullOrNoIsUniqueFileName;
|
||||||
string cResultsFullGroupDirectory;
|
string cResultsFullGroupDirectory;
|
||||||
string dResultsFullGroupDirectory;
|
string dResultsFullGroupDirectory;
|
||||||
string c2ResultsFullGroupDirectory;
|
string c2ResultsFullGroupDirectory;
|
||||||
string d2ResultsFullGroupDirectory;
|
string d2ResultsFullGroupDirectory;
|
||||||
|
Container.Models.Container container;
|
||||||
ReadOnlyCollection<Item> filteredItems;
|
ReadOnlyCollection<Item> filteredItems;
|
||||||
int containersLength = readOnlyContainers.Count;
|
|
||||||
List<Tuple<string, DateTime>> sourceDirectoryChanges = [];
|
List<Tuple<string, DateTime>> sourceDirectoryChanges = [];
|
||||||
int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism;
|
int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism;
|
||||||
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = [] : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory);
|
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = [] : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory);
|
||||||
string dResultsDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D_Face));
|
string dResultsDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D_Face));
|
||||||
B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory);
|
|
||||||
foreach (string outputResolution in _Configuration.OutputResolutions)
|
foreach (string outputResolution in _Configuration.OutputResolutions)
|
||||||
{
|
{
|
||||||
total = 0;
|
total = 0;
|
||||||
outputResolutionHasNumber = outputResolution.Any(char.IsNumber);
|
outputResolutionHasNumber = outputResolution.Any(char.IsNumber);
|
||||||
(cResultsFullGroupDirectory, c2ResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution);
|
(cResultsFullGroupDirectory, c2ResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
|
||||||
_Faces.Update(dResultsFullGroupDirectory);
|
_Faces.Update(dResultsFullGroupDirectory);
|
||||||
_Resize.Update(cResultsFullGroupDirectory);
|
_Resize.Update(cResultsFullGroupDirectory);
|
||||||
_FaceParts.Update(d2ResultsFullGroupDirectory);
|
_FaceParts.Update(d2ResultsFullGroupDirectory);
|
||||||
@ -587,13 +587,13 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
continue;
|
continue;
|
||||||
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
|
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
|
||||||
continue;
|
continue;
|
||||||
filteredItems = Shared.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, container);
|
filteredItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, container);
|
||||||
if (filteredItems.Count == 0)
|
if (filteredItems.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
sourceDirectoryChanges.Clear();
|
sourceDirectoryChanges.Clear();
|
||||||
anyNullOrNoIsUniqueFileName = filteredItems.Any(l => !l.IsUniqueFileName);
|
anyNullOrNoIsUniqueFileName = filteredItems.Any(l => !l.IsUniqueFileName);
|
||||||
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||||
message = $"{i + 1:000} [{filteredItems.Count:000}] / {containersLength:000} - {total} / {count} total - {totalSeconds} total second(s) - {outputResolution} - <{container.SourceDirectory}> - total not mapped {totalNotMapped:000000}";
|
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}";
|
||||||
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, container.SourceDirectory, anyNullOrNoIsUniqueFileName);
|
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, container.SourceDirectory, anyNullOrNoIsUniqueFileName);
|
||||||
if (outputResolutionHasNumber)
|
if (outputResolutionHasNumber)
|
||||||
_Resize.SetAngleBracketCollection(cResultsFullGroupDirectory, container.SourceDirectory);
|
_Resize.SetAngleBracketCollection(cResultsFullGroupDirectory, container.SourceDirectory);
|
||||||
@ -629,7 +629,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
total += container.Items.Count;
|
total += container.Items.Count;
|
||||||
}
|
}
|
||||||
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||||
message = $"### [###] / {containersLength:000} - {total} / {count} total - {totalSeconds} total second(s) - {outputResolution} - <> - total not mapped {totalNotMapped:000000}";
|
message = $"{totalSeconds} total second(s) - {outputResolution} - ### [###] / {readOnlyContainers.Count:000} - {total} / {count} total - <> - total not mapped {totalNotMapped:000000}";
|
||||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||||
using ProgressBar progressBar = new(1, message, options);
|
using ProgressBar progressBar = new(1, message, options);
|
||||||
progressBar.Tick();
|
progressBar.Tick();
|
||||||
@ -678,14 +678,24 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
return results.AsReadOnly();
|
return results.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Identifier GetIdentifier(Property.Models.Configuration propertyConfiguration, FilePath filePath, KeyValuePair<int, ReadOnlyCollection<FilePath>> keyValuePair)
|
||||||
|
{
|
||||||
|
Identifier result;
|
||||||
|
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);
|
||||||
|
result = new(directoryNames, filePath.ExtensionLowered, filePath.HasDateTimeOriginal, filePath.Id.Value, filePath.Length, paddedId, filePath.LastWriteTicks);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private static ReadOnlyDictionary<int, Identifier> GetSplatNineIdentifiers(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>> keyValuePairs)
|
private static ReadOnlyDictionary<int, Identifier> GetSplatNineIdentifiers(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>> keyValuePairs)
|
||||||
{
|
{
|
||||||
Dictionary<int, Identifier> results = [];
|
Dictionary<int, Identifier> results = [];
|
||||||
string json;
|
string json;
|
||||||
string paddedId;
|
|
||||||
FilePath? filePath;
|
FilePath? filePath;
|
||||||
Identifier identifier;
|
Identifier identifier;
|
||||||
string[] directoryNames;
|
List<Identifier> identifiers = [];
|
||||||
string rootDirectory = propertyConfiguration.RootDirectory.Replace('\\', '/');
|
string rootDirectory = propertyConfiguration.RootDirectory.Replace('\\', '/');
|
||||||
string bMetadataCollectionDirectory = Path.Combine(bResultsFullGroupDirectory, propertyConfiguration.ResultCollection);
|
string bMetadataCollectionDirectory = Path.Combine(bResultsFullGroupDirectory, propertyConfiguration.ResultCollection);
|
||||||
if (!Directory.Exists(bMetadataCollectionDirectory))
|
if (!Directory.Exists(bMetadataCollectionDirectory))
|
||||||
@ -700,24 +710,31 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
break;
|
break;
|
||||||
filePath = null;
|
filePath = null;
|
||||||
}
|
}
|
||||||
if (filePath?.Id is null)
|
if (filePath is null)
|
||||||
|
{
|
||||||
|
filePath = keyValuePair.Value[0];
|
||||||
|
if (filePath.Id is null)
|
||||||
|
continue;
|
||||||
|
identifier = GetIdentifier(propertyConfiguration, filePath, keyValuePair);
|
||||||
|
identifiers.Add(identifier);
|
||||||
continue;
|
continue;
|
||||||
directoryNames = keyValuePair.Value.Select(l => l.DirectoryFullPath.Replace('\\', '/')).ToArray();
|
}
|
||||||
paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal, index: null);
|
else if (filePath.Id is null)
|
||||||
identifier = new(directoryNames, filePath.ExtensionLowered, filePath.HasDateTimeOriginal, filePath.Id.Value, filePath.Length, paddedId, filePath.LastWriteTicks);
|
continue;
|
||||||
|
identifier = GetIdentifier(propertyConfiguration, filePath, keyValuePair);
|
||||||
|
identifiers.Add(identifier);
|
||||||
results.Add(keyValuePair.Key, identifier);
|
results.Add(keyValuePair.Key, identifier);
|
||||||
}
|
}
|
||||||
json = JsonSerializer.Serialize(results.Values.ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
|
json = JsonSerializer.Serialize(results.Values.ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
|
||||||
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(bMetadataCollectionDirectory, "!9.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(bMetadataCollectionDirectory, "!9.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
||||||
json = JsonSerializer.Serialize((from l in results orderby l.Value.PaddedId select l.Value).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
|
json = JsonSerializer.Serialize((from l in identifiers orderby l.PaddedId select l).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
|
||||||
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(bMetadataCollectionDirectory, ".json"), json.Replace(rootDirectory, string.Empty), updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(bMetadataCollectionDirectory, ".json"), json.Replace(rootDirectory, string.Empty), updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
||||||
return results.AsReadOnly();
|
return results.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadOnlyDictionary<int, Identifier> GetSplatNineIdentifiersAndHideSplatNine(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
|
private static ReadOnlyDictionary<int, Identifier> GetSplatNineIdentifiersAndHideSplatNine(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>> keyValuePairs)
|
||||||
{
|
{
|
||||||
ReadOnlyDictionary<int, Identifier> results;
|
ReadOnlyDictionary<int, Identifier> results;
|
||||||
ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>> keyValuePairs = FilePath.GetKeyValuePairs(filePathsCollection);
|
|
||||||
if (keyValuePairs.Count == 0)
|
if (keyValuePairs.Count == 0)
|
||||||
results = new(new Dictionary<int, Identifier>());
|
results = new(new Dictionary<int, Identifier>());
|
||||||
else
|
else
|
||||||
@ -730,7 +747,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReadOnlyCollection<Mapping> GetMappings(Property.Models.Configuration propertyConfiguration, string eDistanceContentDirectory, ReadOnlyCollection<Container> readOnlyContainers, MapLogic mapLogic, bool distinctItems)
|
private ReadOnlyCollection<Mapping> GetMappings(Property.Models.Configuration propertyConfiguration, string eDistanceContentDirectory, ReadOnlyCollection<Container.Models.Container> readOnlyContainers, MapLogic mapLogic, bool distinctItems)
|
||||||
{
|
{
|
||||||
List<Mapping> results = [];
|
List<Mapping> results = [];
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@ -743,14 +760,14 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
DateTime[] containerDateTimes;
|
DateTime[] containerDateTimes;
|
||||||
MappingFromItem mappingFromItem;
|
MappingFromItem mappingFromItem;
|
||||||
ReadOnlyCollection<Item> filteredItems;
|
ReadOnlyCollection<Item> filteredItems;
|
||||||
foreach (Container container in readOnlyContainers)
|
foreach (Container.Models.Container container in readOnlyContainers)
|
||||||
{
|
{
|
||||||
if (container.Items.Count == 0)
|
if (container.Items.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
filteredItems = Shared.Models.Stateless.Methods.IContainer.GetValidImageItems(propertyConfiguration, container);
|
filteredItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(propertyConfiguration, container);
|
||||||
if (filteredItems.Count == 0)
|
if (filteredItems.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems);
|
containerDateTimes = Container.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems);
|
||||||
focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory));
|
focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory));
|
||||||
isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
|
isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
|
||||||
foreach (Item item in filteredItems)
|
foreach (Item item in filteredItems)
|
||||||
@ -927,8 +944,9 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
private List<SaveContainer> GetSaveContainers(long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory, ProgressBarOptions options, MapLogic mapLogic, string outputResolution)
|
private List<SaveContainer> GetSaveContainers(long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory, ProgressBarOptions options, MapLogic mapLogic, string outputResolution)
|
||||||
{
|
{
|
||||||
List<SaveContainer> results;
|
List<SaveContainer> results;
|
||||||
|
IDlibDotNet dlibDotNet = this;
|
||||||
long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray();
|
long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray();
|
||||||
(string cResultsFullGroupDirectory, string _, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution);
|
(string cResultsFullGroupDirectory, string _, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
|
||||||
string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
|
string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
|
||||||
ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mapped = Map.Models.Stateless.Methods.IMapLogic.GetMapped(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mapped = Map.Models.Stateless.Methods.IMapLogic.GetMapped(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
||||||
if (mapped.Count == 0 && !_Configuration.SaveSortingWithoutPerson)
|
if (mapped.Count == 0 && !_Configuration.SaveSortingWithoutPerson)
|
||||||
@ -968,9 +986,10 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapLogic(long ticks, ReadOnlyCollection<Container> containers, string fPhotoPrismContentDirectory, MapLogic mapLogic, string outputResolution, ReadOnlyDictionary<long, List<int>> personKeyToIds, ReadOnlyCollection<Shared.Models.Face> distinctValidImageFaces, ReadOnlyCollection<Mapping> distinctValidImageMappingCollection)
|
private void MapLogic(long ticks, ReadOnlyCollection<Container.Models.Container> containers, string fPhotoPrismContentDirectory, MapLogic mapLogic, string outputResolution, ReadOnlyDictionary<long, List<int>> personKeyToIds, ReadOnlyCollection<Shared.Models.Face> distinctValidImageFaces, ReadOnlyCollection<Mapping> distinctValidImageMappingCollection)
|
||||||
{
|
{
|
||||||
(_, _, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution);
|
IDlibDotNet dlibDotNet = this;
|
||||||
|
(_, _, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
|
||||||
string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
|
string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
|
||||||
string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
|
string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
|
||||||
string d2FacePartsContentCollectionDirectory = Path.Combine(d2ResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContentCollection);
|
string d2FacePartsContentCollectionDirectory = Path.Combine(d2ResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContentCollection);
|
||||||
@ -1141,7 +1160,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
string d2ResultsFullGroupDirectory,
|
string d2ResultsFullGroupDirectory,
|
||||||
List<Tuple<string, DateTime>> sourceDirectoryChanges,
|
List<Tuple<string, DateTime>> sourceDirectoryChanges,
|
||||||
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection,
|
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection,
|
||||||
Container container,
|
Container.Models.Container container,
|
||||||
Item item,
|
Item item,
|
||||||
DateTime[] containerDateTimes,
|
DateTime[] containerDateTimes,
|
||||||
bool? isFocusRelativePath)
|
bool? isFocusRelativePath)
|
||||||
@ -1202,12 +1221,10 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
}
|
}
|
||||||
if (resizedFileHolder.Exists && item.FilePath.HasIgnoreKeyword is not null && item.FilePath.HasIgnoreKeyword.Value != shouldIgnore.Value)
|
if (resizedFileHolder.Exists && item.FilePath.HasIgnoreKeyword is not null && item.FilePath.HasIgnoreKeyword.Value != shouldIgnore.Value)
|
||||||
{
|
{
|
||||||
if (!item.FilePath.DirectoryFullPath.Contains("Results") || !item.FilePath.DirectoryFullPath.Contains("Resize"))
|
if (item.FilePath.DirectoryFullPath.Contains("Results") && item.FilePath.DirectoryFullPath.Contains("Resize"))
|
||||||
throw new NotSupportedException($"Rename File! <{item.FilePath.FileNameFirstSegment}>");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
File.Delete(resizedFileHolder.FullName);
|
File.Delete(resizedFileHolder.FullName);
|
||||||
}
|
else
|
||||||
|
throw new NotSupportedException($"Rename File! <{item.FilePath.FileNameFirstSegment}>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (property is null || item.Property is null)
|
if (property is null || item.Property is null)
|
||||||
@ -1297,14 +1314,14 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
string d2ResultsFullGroupDirectory,
|
string d2ResultsFullGroupDirectory,
|
||||||
List<Tuple<string, DateTime>> sourceDirectoryChanges,
|
List<Tuple<string, DateTime>> sourceDirectoryChanges,
|
||||||
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection,
|
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection,
|
||||||
Container container,
|
Container.Models.Container container,
|
||||||
ReadOnlyCollection<Item> filteredItems,
|
ReadOnlyCollection<Item> filteredItems,
|
||||||
string message)
|
string message)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int exceptionsCount = 0;
|
int exceptionsCount = 0;
|
||||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||||
DateTime[] containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems);
|
DateTime[] containerDateTimes = Container.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems);
|
||||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||||
string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory));
|
string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory));
|
||||||
bool? isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
|
bool? isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
|
||||||
@ -1340,7 +1357,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
return (result, exceptionsCount > 0);
|
return (result, exceptionsCount > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private (string, string) GetResultsFullGroupDirectories()
|
(string, string) IDlibDotNet.GetResultsFullGroupDirectories()
|
||||||
{
|
{
|
||||||
string aResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
|
string aResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
|
||||||
_Configuration.PropertyConfiguration,
|
_Configuration.PropertyConfiguration,
|
||||||
@ -1359,7 +1376,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory);
|
return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private (string, string, string, string) GetResultsFullGroupDirectories(string outputResolution)
|
(string, string, string, string) IDlibDotNet.GetResultsFullGroupDirectories(string outputResolution)
|
||||||
{
|
{
|
||||||
string cResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
|
string cResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
|
||||||
_Configuration.PropertyConfiguration,
|
_Configuration.PropertyConfiguration,
|
||||||
@ -1503,8 +1520,9 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
private (string, ReadOnlyCollection<ReadOnlyCollection<FilePath>>, bool) GetFilesCollectionThenCopyOrMove(long ticks, string fileSearchFilter, string directorySearchFilter, ProgressBarOptions options, string outputResolution)
|
private (string, ReadOnlyCollection<ReadOnlyCollection<FilePath>>, bool) GetFilesCollectionThenCopyOrMove(long ticks, string fileSearchFilter, string directorySearchFilter, ProgressBarOptions options, string outputResolution)
|
||||||
{
|
{
|
||||||
ProgressBar progressBar;
|
ProgressBar progressBar;
|
||||||
|
IDlibDotNet dlibDotNet = this;
|
||||||
string filesCollectionRootDirectory = _Configuration.PropertyConfiguration.RootDirectory;
|
string filesCollectionRootDirectory = _Configuration.PropertyConfiguration.RootDirectory;
|
||||||
(string cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution);
|
(string cResultsFullGroupDirectory, _, _, _) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
|
||||||
IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, [_Configuration.PropertyConfiguration.ResultContent, _Configuration.PropertyConfiguration.ResultContentCollection]);
|
IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, [_Configuration.PropertyConfiguration.ResultContent, _Configuration.PropertyConfiguration.ResultContentCollection]);
|
||||||
ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, directorySearchFilter, fileSearchFilter, filesCollectionRootDirectory, useCeilingAverage: false);
|
ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, directorySearchFilter, fileSearchFilter, filesCollectionRootDirectory, useCeilingAverage: false);
|
||||||
int count = filePathsCollection.Select(l => l.Count).Sum();
|
int count = filePathsCollection.Select(l => l.Count).Sum();
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
<ProjectReference Include="..\FaceParts\FaceParts.csproj" />
|
<ProjectReference Include="..\FaceParts\FaceParts.csproj" />
|
||||||
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />
|
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />
|
||||||
<ProjectReference Include="..\Map\Map.csproj" />
|
<ProjectReference Include="..\Map\Map.csproj" />
|
||||||
|
<ProjectReference Include="..\Container\Container.csproj" />
|
||||||
<ProjectReference Include="..\Metadata\Metadata.csproj" />
|
<ProjectReference Include="..\Metadata\Metadata.csproj" />
|
||||||
<ProjectReference Include="..\PhotoPrism\PhotoPrism.csproj" />
|
<ProjectReference Include="..\PhotoPrism\PhotoPrism.csproj" />
|
||||||
<ProjectReference Include="..\Property-Compare\Property-Compare.csproj" />
|
<ProjectReference Include="..\Property-Compare\Property-Compare.csproj" />
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||||
|
<ProjectReference Include="..\Container\Container.csproj" />
|
||||||
|
<ProjectReference Include="..\Property\Property.csproj" />
|
||||||
<ProjectReference Include="..\Metadata\Metadata.csproj" />
|
<ProjectReference Include="..\Metadata\Metadata.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -460,7 +460,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private (long?, string?) GetDirectory(Configuration configuration, string by, string segmentB)
|
private (long?, string?) GetDirectory(Configuration configuration, string by, LocationContainer _, string segmentB)
|
||||||
{
|
{
|
||||||
long? ticks = null;
|
long? ticks = null;
|
||||||
const int zero = 0;
|
const int zero = 0;
|
||||||
@ -537,22 +537,22 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Record Get(Configuration configuration, string by, long? personKey, string? displayDirectoryName, string segmentB)
|
private Record Get(Configuration configuration, string by, LocationContainer locationContainer, string? displayDirectoryName, string segmentB)
|
||||||
{
|
{
|
||||||
long? ticks;
|
long? ticks;
|
||||||
string? directory;
|
string? directory;
|
||||||
string? debugDirectory;
|
string? debugDirectory;
|
||||||
string? personDirectory;
|
string? personDirectory;
|
||||||
if (personKey is null || string.IsNullOrEmpty(displayDirectoryName))
|
if (locationContainer.PersonKey is null || string.IsNullOrEmpty(displayDirectoryName))
|
||||||
{
|
{
|
||||||
debugDirectory = null;
|
debugDirectory = null;
|
||||||
(ticks, directory) = GetDirectory(configuration, by, segmentB);
|
(ticks, directory) = GetDirectory(configuration, by, locationContainer, segmentB);
|
||||||
personDirectory = directory is null ? null : Path.Combine(directory, $"X+{ticks}");
|
personDirectory = directory is null ? null : Path.Combine(directory, $"X+{ticks}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ticks = null;
|
ticks = null;
|
||||||
string personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personKey.Value);
|
string personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, locationContainer.PersonKey.Value);
|
||||||
debugDirectory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, displayDirectoryName);
|
debugDirectory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, displayDirectoryName);
|
||||||
directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, segmentB);
|
directory = Path.Combine(_EDistanceContentTicksDirectory, by, personKeyFormatted, segmentB);
|
||||||
personDirectory = Path.Combine(directory, displayDirectoryName, "lnk");
|
personDirectory = Path.Combine(directory, displayDirectoryName, "lnk");
|
||||||
@ -880,7 +880,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
|||||||
displayDirectoryName = GetDisplayDirectoryName(locationContainer.DisplayDirectoryName, locationContainer, personKeyToPersonContainer);
|
displayDirectoryName = GetDisplayDirectoryName(locationContainer.DisplayDirectoryName, locationContainer, personKeyToPersonContainer);
|
||||||
isCounterPersonYear = locationContainer.PersonKey is not null && IPersonBirthday.IsCounterPersonYear(locationContainer.PersonKey.Value);
|
isCounterPersonYear = locationContainer.PersonKey is not null && IPersonBirthday.IsCounterPersonYear(locationContainer.PersonKey.Value);
|
||||||
(by, _, isBySorting) = Stateless.MapLogic.Get(useFiltersCounter, _Configuration.SaveIndividually, sortingContainersAny, forceSingleImageHumanized, locationContainer.LengthPermyriad, locationContainer.PersonKey, displayDirectoryName);
|
(by, _, isBySorting) = Stateless.MapLogic.Get(useFiltersCounter, _Configuration.SaveIndividually, sortingContainersAny, forceSingleImageHumanized, locationContainer.LengthPermyriad, locationContainer.PersonKey, displayDirectoryName);
|
||||||
record = Get(_Configuration, by, locationContainer.PersonKey, displayDirectoryName, segmentB);
|
record = Get(_Configuration, by, locationContainer, displayDirectoryName, segmentB);
|
||||||
if (string.IsNullOrEmpty(record.Directory) || string.IsNullOrEmpty(record.PersonDirectory))
|
if (string.IsNullOrEmpty(record.Directory) || string.IsNullOrEmpty(record.PersonDirectory))
|
||||||
continue;
|
continue;
|
||||||
directory = record.Directory;
|
directory = record.Directory;
|
||||||
@ -1406,14 +1406,14 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
|||||||
return new(directoriesAndDateTimes, collection);
|
return new(directoriesAndDateTimes, collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveShortcutsForOutputResolutionsDuringMapLogic(ReadOnlyCollection<Container> containers, ReadOnlyDictionary<long, List<int>> personKeyToIds, string dFacesContentDirectory, ReadOnlyCollection<Mapping> distinctValidImageMappingCollection)
|
public void SaveShortcutsForOutputResolutionsDuringMapLogic(ReadOnlyCollection<Container.Models.Container> containers, ReadOnlyDictionary<long, List<int>> personKeyToIds, string dFacesContentDirectory, ReadOnlyCollection<Mapping> distinctValidImageMappingCollection)
|
||||||
{
|
{
|
||||||
if (_Configuration is null)
|
if (_Configuration is null)
|
||||||
throw new NullReferenceException(nameof(_Configuration));
|
throw new NullReferenceException(nameof(_Configuration));
|
||||||
WindowsShortcut windowsShortcut;
|
WindowsShortcut windowsShortcut;
|
||||||
List<(string, DateTime[])> directoriesAndDateTimes;
|
List<(string, DateTime[])> directoriesAndDateTimes;
|
||||||
List<SaveShortcutsForOutputResolutions> collection;
|
List<SaveShortcutsForOutputResolutions> collection;
|
||||||
ReadOnlyCollection<Item> validImageItems = IContainer.GetValidImageItems(_PropertyConfiguration, containers, distinctItems: true, filterItems: true);
|
ReadOnlyCollection<Item> validImageItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(_PropertyConfiguration, containers, distinctItems: true, filterItems: true);
|
||||||
(directoriesAndDateTimes, collection) = GetCollectionForSaveShortcutsForOutputResolutionsDuringMapLogic(personKeyToIds, dFacesContentDirectory, validImageItems, distinctValidImageMappingCollection);
|
(directoriesAndDateTimes, collection) = GetCollectionForSaveShortcutsForOutputResolutionsDuringMapLogic(personKeyToIds, dFacesContentDirectory, validImageItems, distinctValidImageMappingCollection);
|
||||||
string[] directories = (from l in collection select l.Directory).Distinct().ToArray();
|
string[] directories = (from l in collection select l.Directory).Distinct().ToArray();
|
||||||
foreach (string directory in directories)
|
foreach (string directory in directories)
|
||||||
@ -1499,14 +1499,14 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
|||||||
public bool? IsFocusPerson(int? skipPersonWithMoreThen, long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, MappingFromLocation mappingFromLocation) =>
|
public bool? IsFocusPerson(int? skipPersonWithMoreThen, long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, MappingFromLocation mappingFromLocation) =>
|
||||||
IsFocusPerson(skipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation.WholePercentages);
|
IsFocusPerson(skipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation.WholePercentages);
|
||||||
|
|
||||||
public void LookForAbandoned(IDlibDotNet dlibDotNet, Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<Container> readOnlyContainers, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory)
|
public void LookForAbandoned(IDlibDotNet dlibDotNet, Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<Container.Models.Container> readOnlyContainers, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory)
|
||||||
{
|
{
|
||||||
string[] directories;
|
string[] directories;
|
||||||
string? directoryName;
|
string? directoryName;
|
||||||
List<int> distinctFilteredIds = IContainer.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
List<int> distinctFilteredIds = Container.Models.Stateless.Methods.IContainer.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
||||||
LookForAbandoned(propertyConfiguration, distinctFilteredIds);
|
LookForAbandoned(propertyConfiguration, distinctFilteredIds);
|
||||||
dlibDotNet.Tick();
|
dlibDotNet.Tick();
|
||||||
List<string> distinctFilteredFileNameFirstSegments = IContainer.GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
List<string> distinctFilteredFileNameFirstSegments = Container.Models.Stateless.Methods.IContainer.GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
||||||
Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, bResultsFullGroupDirectory, distinctFilteredFileNameFirstSegments);
|
Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, bResultsFullGroupDirectory, distinctFilteredFileNameFirstSegments);
|
||||||
dlibDotNet.Tick();
|
dlibDotNet.Tick();
|
||||||
directories = Directory.GetDirectories(cResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
|
directories = Directory.GetDirectories(cResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
@ -22,7 +22,6 @@ internal abstract class DistanceLogic
|
|||||||
internal record TicksDirectory(DateTime AlternateDirectoryDateTime,
|
internal record TicksDirectory(DateTime AlternateDirectoryDateTime,
|
||||||
string Directory,
|
string Directory,
|
||||||
DateTime DirectoryDateTime,
|
DateTime DirectoryDateTime,
|
||||||
string DirectoryName,
|
|
||||||
bool? IsLocationContainerDebugDirectory,
|
bool? IsLocationContainerDebugDirectory,
|
||||||
float? TotalDays);
|
float? TotalDays);
|
||||||
|
|
||||||
@ -86,53 +85,55 @@ internal abstract class DistanceLogic
|
|||||||
float? totalDays;
|
float? totalDays;
|
||||||
long? next = null;
|
long? next = null;
|
||||||
string? checkDirectory;
|
string? checkDirectory;
|
||||||
string ticksDirectoryName;
|
|
||||||
DateTime directoryDateTime;
|
DateTime directoryDateTime;
|
||||||
DirectoryInfo directoryInfo;
|
DirectoryInfo directoryInfo;
|
||||||
|
TicksDirectory ticksDirectory;
|
||||||
long? lastDirectoryTicks = null;
|
long? lastDirectoryTicks = null;
|
||||||
DateTime dateTime = DateTime.Now;
|
DateTime dateTime = DateTime.Now;
|
||||||
DateTime alternateDirectoryDateTime;
|
DateTime alternateDirectoryDateTime;
|
||||||
|
string ticksDirectoryNameFirstSegment;
|
||||||
bool? isLocationContainerDebugDirectory;
|
bool? isLocationContainerDebugDirectory;
|
||||||
long month = dateTime.AddMonths(1).Ticks - dateTime.Ticks;
|
long month = dateTime.AddMonths(1).Ticks - dateTime.Ticks;
|
||||||
for (int i = 1; i < 5; i++)
|
for (int i = 1; i < 5; i++)
|
||||||
_ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
|
_ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
|
||||||
if (!Directory.Exists(eDistanceContentDirectory))
|
if (!Directory.Exists(eDistanceContentDirectory))
|
||||||
_ = Directory.CreateDirectory(eDistanceContentDirectory);
|
_ = Directory.CreateDirectory(eDistanceContentDirectory);
|
||||||
string[] ticksDirectories = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly);
|
string[] ticksFullPaths = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
foreach (string ticksDirectory in ticksDirectories)
|
foreach (string ticksFullPath in ticksFullPaths)
|
||||||
{
|
{
|
||||||
ticksDirectoryName = Path.GetFileName(ticksDirectory);
|
ticksDirectoryNameFirstSegment = Path.GetFileName(ticksFullPath).Split('.')[0];
|
||||||
if (ticksDirectoryName.Length < 3)
|
if (ticksDirectoryNameFirstSegment.Length < 3)
|
||||||
continue;
|
continue;
|
||||||
if (!long.TryParse(ticksDirectoryName, out long directoryTicks))
|
if (!long.TryParse(ticksDirectoryNameFirstSegment, out long directoryTicks))
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
if (next is null)
|
if (next is null)
|
||||||
next = new DateTime(directoryTicks).Ticks;
|
next = new DateTime(directoryTicks).Ticks;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
next += month;
|
next += month;
|
||||||
checkDirectory = Path.GetDirectoryName(ticksDirectory);
|
checkDirectory = Path.GetDirectoryName(ticksFullPath);
|
||||||
if (string.IsNullOrEmpty(checkDirectory))
|
if (string.IsNullOrEmpty(checkDirectory))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(checkDirectory))
|
if (string.IsNullOrEmpty(checkDirectory))
|
||||||
continue;
|
continue;
|
||||||
checkDirectory = Path.Combine(checkDirectory, next.Value.ToString());
|
checkDirectory = Path.Combine(checkDirectory, next.Value.ToString());
|
||||||
if (ticksDirectory == checkDirectory || !checkDirectory.EndsWith(configuration.LocationContainerDirectoryPattern))
|
if (ticksFullPath == checkDirectory || !checkDirectory.EndsWith(configuration.LocationContainerDirectoryPattern))
|
||||||
continue;
|
continue;
|
||||||
Directory.Move(ticksDirectory, checkDirectory);
|
Directory.Move(ticksFullPath, checkDirectory);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
directoryInfo = new(ticksDirectory);
|
directoryInfo = new(ticksFullPath);
|
||||||
directoryDateTime = new DateTime(directoryTicks);
|
directoryDateTime = new DateTime(directoryTicks);
|
||||||
if (directoryInfo.CreationTime.Ticks != directoryTicks)
|
if (directoryInfo.CreationTime.Ticks != directoryTicks)
|
||||||
Directory.SetCreationTime(ticksDirectory, new DateTime(directoryTicks));
|
Directory.SetCreationTime(ticksFullPath, new DateTime(directoryTicks));
|
||||||
if (directoryInfo.LastWriteTime.Ticks != directoryTicks)
|
if (directoryInfo.LastWriteTime.Ticks != directoryTicks)
|
||||||
Directory.SetLastWriteTime(ticksDirectory, new DateTime(directoryTicks));
|
Directory.SetLastWriteTime(ticksFullPath, new DateTime(directoryTicks));
|
||||||
alternateDirectoryDateTime = new DateTime(directoryDateTime.Year, directoryDateTime.Month, directoryDateTime.Day).AddMonths(1);
|
alternateDirectoryDateTime = new DateTime(directoryDateTime.Year, directoryDateTime.Month, directoryDateTime.Day).AddMonths(1);
|
||||||
isLocationContainerDebugDirectory = configuration.LocationContainerDebugDirectory is null ? null : ticksDirectoryName.EndsWith(configuration.LocationContainerDebugDirectory);
|
isLocationContainerDebugDirectory = configuration.LocationContainerDebugDirectory is null ? null : ticksDirectoryNameFirstSegment.EndsWith(configuration.LocationContainerDebugDirectory);
|
||||||
totalDays = lastDirectoryTicks is null || new TimeSpan(dateTime.Ticks - directoryTicks).TotalDays < 1 ? null : (float)new TimeSpan(directoryTicks - lastDirectoryTicks.Value).TotalDays;
|
totalDays = lastDirectoryTicks is null || new TimeSpan(dateTime.Ticks - directoryTicks).TotalDays < 1 ? null : (float)new TimeSpan(directoryTicks - lastDirectoryTicks.Value).TotalDays;
|
||||||
results.Add(new(alternateDirectoryDateTime, ticksDirectory, new(directoryTicks), ticksDirectoryName, isLocationContainerDebugDirectory, totalDays));
|
ticksDirectory = new(alternateDirectoryDateTime, ticksFullPath, new(directoryTicks), isLocationContainerDebugDirectory, totalDays);
|
||||||
|
results.Add(ticksDirectory);
|
||||||
if (directoryDateTime.Hour == 0 && directoryDateTime.Minute == 0 && directoryDateTime.Second == 0)
|
if (directoryDateTime.Hour == 0 && directoryDateTime.Minute == 0 && directoryDateTime.Second == 0)
|
||||||
continue;
|
continue;
|
||||||
lastDirectoryTicks = directoryTicks;
|
lastDirectoryTicks = directoryTicks;
|
||||||
@ -216,9 +217,37 @@ internal abstract class DistanceLogic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Record> GetRecords(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, int? linksCount, List<string> distinct, string? personDisplayDirectoryName)
|
private static string GetCheckFile(TicksDirectory ticksDirectory, string @enum, string fileName, string file)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
string checkDirectory;
|
||||||
|
string directory = file;
|
||||||
|
List<string> collection = [];
|
||||||
|
for (int i = 0; i < file.Length; i++)
|
||||||
|
{
|
||||||
|
directory = Path.GetDirectoryName(directory) ?? throw new Exception();
|
||||||
|
if (directory == ticksDirectory.Directory)
|
||||||
|
break;
|
||||||
|
collection.Add(Path.GetFileName(directory));
|
||||||
|
}
|
||||||
|
collection.Reverse();
|
||||||
|
checkDirectory = $"{ticksDirectory.Directory}.{@enum}";
|
||||||
|
foreach (string directoryName in collection)
|
||||||
|
checkDirectory = Path.Combine(checkDirectory, directoryName);
|
||||||
|
if (!Directory.Exists(checkDirectory))
|
||||||
|
_ = Directory.CreateDirectory(checkDirectory);
|
||||||
|
result = Path.Combine(checkDirectory, fileName);
|
||||||
|
if (File.Exists(result))
|
||||||
|
throw new Exception($"File <{fileName}> already exists!");
|
||||||
|
File.Move(file, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Record> GetRecords(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, TicksDirectory ticksDirectory, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, int? linksCount, List<string> distinct, string? personDisplayDirectoryName)
|
||||||
{
|
{
|
||||||
List<Record> results = [];
|
List<Record> results = [];
|
||||||
|
string @enum;
|
||||||
|
Record record;
|
||||||
string fileName;
|
string fileName;
|
||||||
string checkFile;
|
string checkFile;
|
||||||
FilePath filePath;
|
FilePath filePath;
|
||||||
@ -244,8 +273,26 @@ internal abstract class DistanceLogic
|
|||||||
File.Move(file, checkFile);
|
File.Move(file, checkFile);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (file.StartsWith(ticksDirectory.Directory))
|
||||||
|
{
|
||||||
|
@enum = IPath.GetEnum(filePath).ToString();
|
||||||
|
if (!ticksDirectory.Directory.EndsWith(@enum))
|
||||||
|
{
|
||||||
|
checkFile = GetCheckFile(ticksDirectory, @enum, fileName, file);
|
||||||
|
fileHolder = IFileHolder.Get(checkFile);
|
||||||
|
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
|
||||||
|
if (filePath.Id is null)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
distinct.Add(fileName);
|
distinct.Add(fileName);
|
||||||
results.Add(new(directoryNumber, isDefault, linksCount, filePath, personDisplayDirectoryName, personKeyFormatted));
|
record = new(DirectoryNumber: directoryNumber,
|
||||||
|
IsDefault: isDefault,
|
||||||
|
LinksCount: linksCount,
|
||||||
|
MappedFaceFilePath: filePath,
|
||||||
|
PersonDisplayDirectoryName: personDisplayDirectoryName,
|
||||||
|
PersonKeyFormatted: personKeyFormatted);
|
||||||
|
results.Add(record);
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@ -311,6 +358,7 @@ internal abstract class DistanceLogic
|
|||||||
DateTime dateTime;
|
DateTime dateTime;
|
||||||
TimeSpan timeSpan;
|
TimeSpan timeSpan;
|
||||||
int directoryNumber;
|
int directoryNumber;
|
||||||
|
List<Record> records;
|
||||||
string? checkDirectory;
|
string? checkDirectory;
|
||||||
ProgressBar progressBar;
|
ProgressBar progressBar;
|
||||||
string[] yearDirectories;
|
string[] yearDirectories;
|
||||||
@ -340,8 +388,7 @@ internal abstract class DistanceLogic
|
|||||||
progressBar = new(ticksDirectories.Count, message, options);
|
progressBar = new(ticksDirectories.Count, message, options);
|
||||||
foreach (TicksDirectory ticksDirectory in ticksDirectories)
|
foreach (TicksDirectory ticksDirectory in ticksDirectories)
|
||||||
{
|
{
|
||||||
if (i == 1)
|
progressBar.Tick();
|
||||||
progressBar.Tick();
|
|
||||||
personKeyFormattedDirectories = Directory.GetDirectories(ticksDirectory.Directory, "*", SearchOption.TopDirectoryOnly);
|
personKeyFormattedDirectories = Directory.GetDirectories(ticksDirectory.Directory, "*", SearchOption.TopDirectoryOnly);
|
||||||
foreach (string personKeyFormattedDirectory in personKeyFormattedDirectories)
|
foreach (string personKeyFormattedDirectory in personKeyFormattedDirectories)
|
||||||
{
|
{
|
||||||
@ -368,23 +415,6 @@ internal abstract class DistanceLogic
|
|||||||
linksCount = null;
|
linksCount = null;
|
||||||
else
|
else
|
||||||
linksCount = GetLinksCount(yearDirectory);
|
linksCount = GetLinksCount(yearDirectory);
|
||||||
if (ticksDirectory.DirectoryName != configuration.LocationContainerDebugDirectory)
|
|
||||||
{
|
|
||||||
files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly);
|
|
||||||
foreach (string file in files)
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
if (ticksDirectory.DirectoryName == configuration.LocationContainerDebugDirectory)
|
|
||||||
{
|
|
||||||
isDefault = null;
|
|
||||||
personDisplayDirectoryName = null;
|
|
||||||
files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly);
|
|
||||||
results.AddRange(GetRecords(propertyConfiguration, configuration, isDefault, files, directoryNumber, personKeyFormatted, linksCount, distinct, personDisplayDirectoryName));
|
|
||||||
files = Directory.GetFiles(yearDirectory, "*.lnk", SearchOption.AllDirectories);
|
|
||||||
foreach (string file in files)
|
|
||||||
File.Delete(file);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly);
|
personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
if (personNameDirectories.Length > 1)
|
if (personNameDirectories.Length > 1)
|
||||||
throw new NotSupportedException("Try deleting *.lnk files!");
|
throw new NotSupportedException("Try deleting *.lnk files!");
|
||||||
@ -467,7 +497,9 @@ internal abstract class DistanceLogic
|
|||||||
Directory.Move(personNameDirectory, personFirstInitialDirectory);
|
Directory.Move(personNameDirectory, personFirstInitialDirectory);
|
||||||
files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
|
files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
}
|
}
|
||||||
results.AddRange(GetRecords(propertyConfiguration, configuration, isDefault, files, directoryNumber, personKeyFormatted, linksCount, distinct, personDisplayDirectoryName));
|
records = GetRecords(propertyConfiguration, configuration, ticksDirectory, isDefault, files, directoryNumber, personKeyFormatted, linksCount, distinct, personDisplayDirectoryName);
|
||||||
|
if (records.Count > 0)
|
||||||
|
results.AddRange(records);
|
||||||
personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
|
personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
foreach (string personNameLinkDirectory in personNameLinkDirectories)
|
foreach (string personNameLinkDirectory in personNameLinkDirectories)
|
||||||
{
|
{
|
||||||
|
@ -13,17 +13,17 @@ namespace View_by_Distance.Map.Models.Stateless;
|
|||||||
internal abstract class MapLogic
|
internal abstract class MapLogic
|
||||||
{
|
{
|
||||||
|
|
||||||
|
internal record Duplicate(long PersonKey,
|
||||||
|
int Id,
|
||||||
|
FilePath FilePath,
|
||||||
|
float? Percent);
|
||||||
|
|
||||||
internal record MappedFile(long PersonKey,
|
internal record MappedFile(long PersonKey,
|
||||||
string PersonKeyFormatted,
|
string PersonKeyFormatted,
|
||||||
string? PersonDisplayDirectoryName,
|
string? PersonDisplayDirectoryName,
|
||||||
int? DirectoryNumber,
|
int? DirectoryNumber,
|
||||||
FilePath FilePath);
|
FilePath FilePath);
|
||||||
|
|
||||||
internal record Duplicate(long PersonKey,
|
|
||||||
int Id,
|
|
||||||
FilePath FilePath,
|
|
||||||
float? Percent);
|
|
||||||
|
|
||||||
internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted,
|
internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted,
|
||||||
string? PersonDisplayDirectoryName,
|
string? PersonDisplayDirectoryName,
|
||||||
bool? IsDefault,
|
bool? IsDefault,
|
||||||
@ -188,6 +188,7 @@ internal abstract class MapLogic
|
|||||||
private static List<MappedFile> GetDisplayDirectoryAllFiles(string fileNameExtension, string personBirthdayFormat, ReadOnlyCollection<PersonContainer> personContainers)
|
private static List<MappedFile> GetDisplayDirectoryAllFiles(string fileNameExtension, string personBirthdayFormat, ReadOnlyCollection<PersonContainer> personContainers)
|
||||||
{
|
{
|
||||||
List<MappedFile> results = [];
|
List<MappedFile> results = [];
|
||||||
|
MappedFile mappedFile;
|
||||||
string personKeyFormatted;
|
string personKeyFormatted;
|
||||||
List<string> distinct = [];
|
List<string> distinct = [];
|
||||||
foreach (PersonContainer personContainer in personContainers)
|
foreach (PersonContainer personContainer in personContainers)
|
||||||
@ -202,7 +203,12 @@ internal abstract class MapLogic
|
|||||||
continue;
|
continue;
|
||||||
distinct.Add(personContainer.DisplayDirectoryAllFilePaths[i].Name);
|
distinct.Add(personContainer.DisplayDirectoryAllFilePaths[i].Name);
|
||||||
personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personContainer.Key.Value);
|
personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personContainer.Key.Value);
|
||||||
results.Add(new(personContainer.Key.Value, personKeyFormatted, personContainer.DisplayDirectoryName, null, personContainer.DisplayDirectoryAllFilePaths[i]));
|
mappedFile = new(PersonKey: personContainer.Key.Value,
|
||||||
|
PersonKeyFormatted: personKeyFormatted,
|
||||||
|
PersonDisplayDirectoryName: personContainer.DisplayDirectoryName,
|
||||||
|
DirectoryNumber: null,
|
||||||
|
FilePath: personContainer.DisplayDirectoryAllFilePaths[i]);
|
||||||
|
results.Add(mappedFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
@ -462,6 +468,7 @@ internal abstract class MapLogic
|
|||||||
string checkFile;
|
string checkFile;
|
||||||
FilePath filePath;
|
FilePath filePath;
|
||||||
FileHolder fileHolder;
|
FileHolder fileHolder;
|
||||||
|
MappedFile mappedFile;
|
||||||
List<string> distinct = [];
|
List<string> distinct = [];
|
||||||
PersonBirthday? personBirthday;
|
PersonBirthday? personBirthday;
|
||||||
PersonContainer? personContainer;
|
PersonContainer? personContainer;
|
||||||
@ -481,7 +488,12 @@ internal abstract class MapLogic
|
|||||||
personDisplayDirectoryName = record.PersonDisplayDirectoryName;
|
personDisplayDirectoryName = record.PersonDisplayDirectoryName;
|
||||||
else
|
else
|
||||||
personDisplayDirectoryName = personContainer.DisplayDirectoryName;
|
personDisplayDirectoryName = personContainer.DisplayDirectoryName;
|
||||||
results.Add(new(personKey, record.PersonKeyFormatted, personDisplayDirectoryName, record.DirectoryNumber, record.MappedFaceFilePath));
|
mappedFile = new(PersonKey: personKey,
|
||||||
|
PersonKeyFormatted: record.PersonKeyFormatted,
|
||||||
|
PersonDisplayDirectoryName: personDisplayDirectoryName,
|
||||||
|
DirectoryNumber: record.DirectoryNumber,
|
||||||
|
FilePath: record.MappedFaceFilePath);
|
||||||
|
results.Add(mappedFile);
|
||||||
}
|
}
|
||||||
for (int i = results.Count - 1; i > -1; i--)
|
for (int i = results.Count - 1; i > -1; i--)
|
||||||
{
|
{
|
||||||
@ -501,7 +513,11 @@ internal abstract class MapLogic
|
|||||||
File.Move(filePath.FullName, checkFile);
|
File.Move(filePath.FullName, checkFile);
|
||||||
fileHolder = IFileHolder.Get(checkFile);
|
fileHolder = IFileHolder.Get(checkFile);
|
||||||
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
|
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
|
||||||
results[i] = new(results[i].PersonKey, results[i].PersonKeyFormatted, results[i].PersonDisplayDirectoryName, results[i].DirectoryNumber, filePath);
|
results[i] = new(PersonKey: results[i].PersonKey,
|
||||||
|
PersonKeyFormatted: results[i].PersonKeyFormatted,
|
||||||
|
PersonDisplayDirectoryName: results[i].PersonDisplayDirectoryName,
|
||||||
|
DirectoryNumber: results[i].DirectoryNumber,
|
||||||
|
FilePath: filePath);
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@ -791,6 +807,7 @@ internal abstract class MapLogic
|
|||||||
int? wholePercentages;
|
int? wholePercentages;
|
||||||
List<int> wholePercentagesCollection;
|
List<int> wholePercentagesCollection;
|
||||||
Dictionary<int, List<int>> idToWholePercentagesCollection = [];
|
Dictionary<int, List<int>> idToWholePercentagesCollection = [];
|
||||||
|
PersonKeyFormattedIdThenWholePercentages personKeyFormattedIdThenWholePercentages;
|
||||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||||
string message = $") {records.Count:000} join from ticks Director(ies) - C - {totalSeconds} total second(s)";
|
string message = $") {records.Count:000} join from ticks Director(ies) - C - {totalSeconds} total second(s)";
|
||||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||||
@ -808,7 +825,14 @@ internal abstract class MapLogic
|
|||||||
wholePercentagesCollection = idToWholePercentagesCollection[record.MappedFaceFilePath.Id.Value];
|
wholePercentagesCollection = idToWholePercentagesCollection[record.MappedFaceFilePath.Id.Value];
|
||||||
wholePercentagesCollection.Add(wholePercentages.Value);
|
wholePercentagesCollection.Add(wholePercentages.Value);
|
||||||
idToWholePercentagesCollection[record.MappedFaceFilePath.Id.Value].Add(wholePercentages.Value);
|
idToWholePercentagesCollection[record.MappedFaceFilePath.Id.Value].Add(wholePercentages.Value);
|
||||||
results.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.IsDefault, record.LinksCount, record.MappedFaceFilePath, record.MappedFaceFilePath.Id.Value, wholePercentages.Value));
|
personKeyFormattedIdThenWholePercentages = new(PersonKeyFormatted: record.PersonKeyFormatted,
|
||||||
|
PersonDisplayDirectoryName: record.PersonDisplayDirectoryName,
|
||||||
|
IsDefault: record.IsDefault,
|
||||||
|
LinksCount: record.LinksCount,
|
||||||
|
MappedFaceFilePath: record.MappedFaceFilePath,
|
||||||
|
Id: record.MappedFaceFilePath.Id.Value,
|
||||||
|
WholePercentages: wholePercentages.Value);
|
||||||
|
results.Add(personKeyFormattedIdThenWholePercentages);
|
||||||
}
|
}
|
||||||
return results.AsReadOnly();
|
return results.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
@ -34,10 +34,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MetadataExtractor" Version="2.8.1" />
|
<PackageReference Include="MetadataExtractor" Version="2.8.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
|
||||||
<PackageReference Include="System.Text.Json" Version="9.0.2" />
|
<PackageReference Include="System.Text.Json" Version="9.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Property\Property.csproj" />
|
|
||||||
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -148,7 +148,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
|
|||||||
DateTime? result = null;
|
DateTime? result = null;
|
||||||
DateTime? dateTime;
|
DateTime? dateTime;
|
||||||
DateTime checkDateTime;
|
DateTime checkDateTime;
|
||||||
string dateTimeFormat = Property.Models.Stateless.IProperty.DateTimeFormat();
|
string dateTimeFormat = Stateless.Methods.IMetadata.DateTimeFormat();
|
||||||
MetadataExtractor.Formats.Exif.ExifDirectoryBase? exifDirectoryBase = directories.OfType<MetadataExtractor.Formats.Exif.ExifDirectoryBase>().FirstOrDefault();
|
MetadataExtractor.Formats.Exif.ExifDirectoryBase? exifDirectoryBase = directories.OfType<MetadataExtractor.Formats.Exif.ExifDirectoryBase>().FirstOrDefault();
|
||||||
results.Add(new DateTime(filePath.CreationTicks));
|
results.Add(new DateTime(filePath.CreationTicks));
|
||||||
results.Add(new DateTime(filePath.LastWriteTicks));
|
results.Add(new DateTime(filePath.LastWriteTicks));
|
||||||
@ -158,7 +158,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
|
|||||||
results.Add(checkDateTime);
|
results.Add(checkDateTime);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTime));
|
dateTime = Stateless.Methods.IMetadata.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTime));
|
||||||
if (dateTime is not null)
|
if (dateTime is not null)
|
||||||
results.Add(dateTime.Value);
|
results.Add(dateTime.Value);
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
|
|||||||
results.Add(checkDateTime);
|
results.Add(checkDateTime);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeDigitized));
|
dateTime = Stateless.Methods.IMetadata.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeDigitized));
|
||||||
if (dateTime is not null)
|
if (dateTime is not null)
|
||||||
results.Add(dateTime.Value);
|
results.Add(dateTime.Value);
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeOriginal));
|
dateTime = Stateless.Methods.IMetadata.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeOriginal));
|
||||||
if (dateTime is not null)
|
if (dateTime is not null)
|
||||||
{
|
{
|
||||||
result ??= dateTime.Value;
|
result ??= dateTime.Value;
|
||||||
@ -195,7 +195,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, aviDirectory.GetString(MetadataExtractor.Formats.Avi.AviDirectory.TagDateTimeOriginal));
|
dateTime = Stateless.Methods.IMetadata.GetDateTime(dateTimeFormat, aviDirectory.GetString(MetadataExtractor.Formats.Avi.AviDirectory.TagDateTimeOriginal));
|
||||||
if (dateTime is not null)
|
if (dateTime is not null)
|
||||||
{
|
{
|
||||||
result ??= dateTime.Value;
|
result ??= dateTime.Value;
|
||||||
@ -213,7 +213,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, quickTimeMovieHeaderDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated));
|
dateTime = Stateless.Methods.IMetadata.GetDateTime(dateTimeFormat, quickTimeMovieHeaderDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated));
|
||||||
if (dateTime is not null)
|
if (dateTime is not null)
|
||||||
{
|
{
|
||||||
result ??= dateTime.Value;
|
result ??= dateTime.Value;
|
||||||
@ -231,7 +231,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, quickTimeTrackHeaderDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated));
|
dateTime = Stateless.Methods.IMetadata.GetDateTime(dateTimeFormat, quickTimeTrackHeaderDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated));
|
||||||
if (dateTime is not null)
|
if (dateTime is not null)
|
||||||
{
|
{
|
||||||
result ??= dateTime.Value;
|
result ??= dateTime.Value;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Globalization;
|
||||||
using View_by_Distance.Shared.Models;
|
using View_by_Distance.Shared.Models;
|
||||||
|
|
||||||
namespace View_by_Distance.Metadata.Models.Stateless.Methods;
|
namespace View_by_Distance.Metadata.Models.Stateless.Methods;
|
||||||
@ -47,4 +48,23 @@ internal static class Base
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
|
||||||
|
internal static DateTime? GetDateTime(string dateTimeFormat, string? value)
|
||||||
|
{
|
||||||
|
DateTime? result;
|
||||||
|
string alternateFormat = "ddd MMM dd HH:mm:ss yyyy";
|
||||||
|
if (value is not null && DateTime.TryParse(value, out DateTime dateTime))
|
||||||
|
result = dateTime;
|
||||||
|
else if (value is not null && value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
|
||||||
|
result = dateTime;
|
||||||
|
else if (value is not null && value.Length == alternateFormat.Length && DateTime.TryParseExact(value, alternateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
|
||||||
|
result = dateTime;
|
||||||
|
else
|
||||||
|
result = null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
|
||||||
}
|
}
|
@ -64,4 +64,14 @@ public interface IMetadata
|
|||||||
// static Dictionary<string, MetadataExtractorDirectory> GetMetadataCollection(FileInfo fileInfo, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions) =>
|
// static Dictionary<string, MetadataExtractorDirectory> GetMetadataCollection(FileInfo fileInfo, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions) =>
|
||||||
// Metadata.GetMetadataCollection(fileInfo, subFileTuples, parseExceptions);
|
// Metadata.GetMetadataCollection(fileInfo, subFileTuples, parseExceptions);
|
||||||
|
|
||||||
|
string TestStatic_DateTimeFormat() =>
|
||||||
|
DateTimeFormat();
|
||||||
|
static string DateTimeFormat() =>
|
||||||
|
"yyyy:MM:dd HH:mm:ss";
|
||||||
|
|
||||||
|
DateTime? TestStatic_GetDateTime(string dateTimeFormat, string? value) =>
|
||||||
|
GetDateTime(dateTimeFormat, value);
|
||||||
|
static DateTime? GetDateTime(string dateTimeFormat, string? value) =>
|
||||||
|
Base.GetDateTime(dateTimeFormat, value);
|
||||||
|
|
||||||
}
|
}
|
@ -239,7 +239,7 @@ public class A_Property
|
|||||||
SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName);
|
SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SavePropertyParallelWork(int maxDegreeOfParallelism, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, Container container, ReadOnlyCollection<Item> items, string message)
|
private void SavePropertyParallelWork(int maxDegreeOfParallelism, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, Container.Models.Container container, ReadOnlyCollection<Item> items, string message)
|
||||||
{
|
{
|
||||||
List<Tuple<string, DateTime>> sourceDirectoryFileTuples = [];
|
List<Tuple<string, DateTime>> sourceDirectoryFileTuples = [];
|
||||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||||
@ -268,14 +268,14 @@ public class A_Property
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SavePropertyParallelWork(long ticks, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, int t, Container[] containers)
|
public void SavePropertyParallelWork(long ticks, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, int t, Container.Models.Container[] containers)
|
||||||
{
|
{
|
||||||
int total = 0;
|
int total = 0;
|
||||||
string message;
|
string message;
|
||||||
int totalSeconds;
|
int totalSeconds;
|
||||||
Container container;
|
|
||||||
bool anyNullOrNoIsUniqueFileName;
|
bool anyNullOrNoIsUniqueFileName;
|
||||||
List<Exception> exceptions = [];
|
List<Exception> exceptions = [];
|
||||||
|
Container.Models.Container container;
|
||||||
int containersLength = containers.Length;
|
int containersLength = containers.Length;
|
||||||
const string outputResolution = "Original";
|
const string outputResolution = "Original";
|
||||||
List<Tuple<string, DateTime>> sourceDirectoryChanges = [];
|
List<Tuple<string, DateTime>> sourceDirectoryChanges = [];
|
||||||
|
@ -55,4 +55,24 @@ public interface IProperty
|
|||||||
static (DateTime?, DateTime[], int?, string?) Get(IPropertyConfiguration propertyConfiguration, bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
static (DateTime?, DateTime[], int?, string?) Get(IPropertyConfiguration propertyConfiguration, bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
||||||
Property.Get(populateId, metadata, FilePath.Get(propertyConfiguration, fileHolder, index: null), isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
Property.Get(populateId, metadata, FilePath.Get(propertyConfiguration, fileHolder, index: null), isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
||||||
|
|
||||||
|
TimeSpan TestStatic_GetThreeStandardDeviationHigh(int minimum, Container.Models.Container container) =>
|
||||||
|
GetThreeStandardDeviationHigh(minimum, container);
|
||||||
|
static TimeSpan GetThreeStandardDeviationHigh(int minimum, Container.Models.Container container) =>
|
||||||
|
Property.GetThreeStandardDeviationHigh(minimum, container);
|
||||||
|
|
||||||
|
(int, List<DateTime>, List<Shared.Models.Item>) TestStatic_Get(Container.Models.Container container, TimeSpan threeStandardDeviationHigh, int i) =>
|
||||||
|
Get(container, threeStandardDeviationHigh, i);
|
||||||
|
static (int, List<DateTime>, List<Shared.Models.Item>) Get(Container.Models.Container container, TimeSpan threeStandardDeviationHigh, int i) =>
|
||||||
|
Property.Get(container, threeStandardDeviationHigh, i);
|
||||||
|
|
||||||
|
bool TestStatic_Any(Container.Models.Container[] propertyHolderCollections) =>
|
||||||
|
Any(propertyHolderCollections);
|
||||||
|
static bool Any(Container.Models.Container[] propertyHolderCollections) =>
|
||||||
|
Property.Any(propertyHolderCollections);
|
||||||
|
|
||||||
|
double TestStatic_GetStandardDeviation(List<long> values, double average) =>
|
||||||
|
GetStandardDeviation(values, average);
|
||||||
|
static double GetStandardDeviation(List<long> values, double average) =>
|
||||||
|
Property.GetStandardDeviation(values, average);
|
||||||
|
|
||||||
}
|
}
|
@ -366,4 +366,112 @@ internal partial class Property
|
|||||||
return new(property?.DateTimeOriginal, dateTimes, property?.Id, message);
|
return new(property?.DateTimeOriginal, dateTimes, property?.Id, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static double GetStandardDeviation(List<long> values, double average)
|
||||||
|
{
|
||||||
|
double result = 0;
|
||||||
|
if (values.Count == 0)
|
||||||
|
throw new Exception("Collection must have at least one value!");
|
||||||
|
double sum = values.Sum(l => (l - average) * (l - average));
|
||||||
|
result = Math.Sqrt(sum / values.Count);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long GetThreeStandardDeviationHigh(ref List<long> ticksCollection, long min)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
ticksCollection = (from l in ticksCollection select l - min).ToList();
|
||||||
|
double sum = ticksCollection.Sum();
|
||||||
|
double average = sum / ticksCollection.Count;
|
||||||
|
double standardDeviation = GetStandardDeviation(ticksCollection, average);
|
||||||
|
result = (long)Math.Ceiling(average + min + (standardDeviation * 3));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static TimeSpan GetThreeStandardDeviationHigh(int minimum, Container.Models.Container container)
|
||||||
|
{
|
||||||
|
TimeSpan result;
|
||||||
|
DateTime? minimumDateTime;
|
||||||
|
List<long> ticksCollection = [];
|
||||||
|
foreach (Shared.Models.Item item in container.Items)
|
||||||
|
{
|
||||||
|
if (item.Property is null)
|
||||||
|
continue;
|
||||||
|
minimumDateTime = Shared.Models.Methods.IProperty.GetMinimumDateTime(item.Property);
|
||||||
|
if (minimumDateTime is null)
|
||||||
|
continue;
|
||||||
|
ticksCollection.Add(minimumDateTime.Value.Ticks);
|
||||||
|
}
|
||||||
|
long threeStandardDeviationHigh;
|
||||||
|
long min;
|
||||||
|
if (ticksCollection.Count == 0)
|
||||||
|
min = 0;
|
||||||
|
else
|
||||||
|
min = ticksCollection.Min();
|
||||||
|
if (ticksCollection.Count < minimum)
|
||||||
|
threeStandardDeviationHigh = long.MaxValue;
|
||||||
|
else
|
||||||
|
threeStandardDeviationHigh = GetThreeStandardDeviationHigh(ref ticksCollection, min);
|
||||||
|
result = new TimeSpan(threeStandardDeviationHigh - min);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static (int, List<DateTime>, List<Shared.Models.Item>) Get(Container.Models.Container container, TimeSpan threeStandardDeviationHigh, int i)
|
||||||
|
{
|
||||||
|
List<Shared.Models.Item> results = [];
|
||||||
|
int j = i;
|
||||||
|
long? ticks;
|
||||||
|
TimeSpan timeSpan;
|
||||||
|
Shared.Models.Item item;
|
||||||
|
DateTime? minimumDateTime;
|
||||||
|
Shared.Models.Item nextItem;
|
||||||
|
DateTime? nextMinimumDateTime;
|
||||||
|
List<DateTime> dateTimes = [];
|
||||||
|
for (; j < container.Items.Count; j++)
|
||||||
|
{
|
||||||
|
ticks = null;
|
||||||
|
item = container.Items[j];
|
||||||
|
if (item.Property is null)
|
||||||
|
continue;
|
||||||
|
minimumDateTime = Shared.Models.Methods.IProperty.GetMinimumDateTime(item.Property);
|
||||||
|
if (minimumDateTime is null)
|
||||||
|
continue;
|
||||||
|
for (int k = j + 1; k < container.Items.Count; k++)
|
||||||
|
{
|
||||||
|
nextItem = container.Items[k];
|
||||||
|
if (nextItem.Property is null)
|
||||||
|
continue;
|
||||||
|
nextMinimumDateTime = Shared.Models.Methods.IProperty.GetMinimumDateTime(nextItem.Property);
|
||||||
|
if (nextMinimumDateTime is null)
|
||||||
|
continue;
|
||||||
|
ticks = nextMinimumDateTime.Value.Ticks;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
results.Add(item);
|
||||||
|
dateTimes.Add(minimumDateTime.Value);
|
||||||
|
if (ticks.HasValue)
|
||||||
|
{
|
||||||
|
timeSpan = new(ticks.Value - minimumDateTime.Value.Ticks);
|
||||||
|
if (timeSpan > threeStandardDeviationHigh)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new(j, dateTimes, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool Any(Container.Models.Container[] containers)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
foreach (Container.Models.Container container in containers)
|
||||||
|
{
|
||||||
|
if (container.Items.Count == 0)
|
||||||
|
continue;
|
||||||
|
if ((from l in container.Items where l.Any() select true).Any())
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -46,6 +46,7 @@
|
|||||||
<PackageReference Include="System.Text.Json" Version="9.0.2" />
|
<PackageReference Include="System.Text.Json" Version="9.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Container\Container.csproj" />
|
||||||
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -315,7 +315,7 @@ public class C_Resize
|
|||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveResizedSubfile(Configuration configuration, string outputResolution, string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, Item item, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize)
|
public void SaveResizedSubfile(Property.Models.Configuration configuration, string outputResolution, string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, Item item, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize)
|
||||||
{
|
{
|
||||||
if (mappingFromItem.ResizedFileHolder is null)
|
if (mappingFromItem.ResizedFileHolder is null)
|
||||||
throw new NullReferenceException(nameof(mappingFromItem.ResizedFileHolder));
|
throw new NullReferenceException(nameof(mappingFromItem.ResizedFileHolder));
|
||||||
@ -462,7 +462,7 @@ public class C_Resize
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<string, int[]> GetResizeKeyValuePairs(Configuration configuration, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem)
|
public Dictionary<string, int[]> GetResizeKeyValuePairs(Property.Models.Configuration configuration, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem)
|
||||||
{
|
{
|
||||||
Dictionary<string, int[]>? results;
|
Dictionary<string, int[]>? results;
|
||||||
string json;
|
string json;
|
||||||
|
@ -3,7 +3,7 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace View_by_Distance.Shared.Models;
|
namespace View_by_Distance.Shared.Models;
|
||||||
|
|
||||||
internal record FilePair(string Path,
|
public record FilePair(string Path,
|
||||||
bool IsUnique,
|
bool IsUnique,
|
||||||
bool? IsNotUniqueAndNeedsReview,
|
bool? IsNotUniqueAndNeedsReview,
|
||||||
List<string> Collection,
|
List<string> Collection,
|
||||||
@ -20,6 +20,6 @@ internal record FilePair(string Path,
|
|||||||
|
|
||||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
[JsonSerializable(typeof(FilePair))]
|
[JsonSerializable(typeof(FilePair))]
|
||||||
internal partial class FilePairSourceGenerationContext : JsonSerializerContext
|
public partial class FilePairSourceGenerationContext : JsonSerializerContext
|
||||||
{
|
{
|
||||||
}
|
}
|
@ -1,8 +0,0 @@
|
|||||||
namespace View_by_Distance.Shared.Models.Methods;
|
|
||||||
|
|
||||||
public interface IContainer : Stateless.Methods.IContainer
|
|
||||||
{ // ...
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
}
|
|
@ -1,302 +0,0 @@
|
|||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
|
||||||
|
|
||||||
internal abstract class Container
|
|
||||||
{
|
|
||||||
|
|
||||||
private record FilePair(bool IsUnique, List<string> Collection, FilePath FilePath, Models.Item Item) { }
|
|
||||||
|
|
||||||
internal static DateTime[] GetContainerDateTimes(ReadOnlyCollection<Models.Item> items)
|
|
||||||
{
|
|
||||||
DateTime[] results;
|
|
||||||
long containerMinimumTicks = (from l in items select l.FilePath.LastWriteTicks).Min();
|
|
||||||
long containerMaximumTicks = (from l in items select l.FilePath.LastWriteTicks).Max();
|
|
||||||
results = [new(containerMinimumTicks), new(containerMaximumTicks)];
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static ReadOnlyCollection<Models.Item> GetValidImageItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container container)
|
|
||||||
{
|
|
||||||
List<Models.Item> results = [];
|
|
||||||
foreach (Models.Item item in container.Items)
|
|
||||||
{
|
|
||||||
if (!item.IsValidImageFormatExtension || propertyConfiguration.IgnoreExtensions.Contains(item.FilePath.ExtensionLowered))
|
|
||||||
continue;
|
|
||||||
results.Add(item);
|
|
||||||
}
|
|
||||||
return container.Items.Count == results.Count ? container.Items : results.AsReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Models.FilePair> GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
|
|
||||||
{
|
|
||||||
int renamed;
|
|
||||||
const bool useCeilingAverage = true;
|
|
||||||
List<Models.FilePair>? filePairs = null;
|
|
||||||
ReadOnlyCollection<string[]>? jsonFilesCollection = null;
|
|
||||||
IReadOnlyDictionary<string, List<string>>? compareFileNamesToFiles = null;
|
|
||||||
IReadOnlyDictionary<string, List<string>> fileNamesToFiles = XDirectory.GetFilesKeyValuePairs(filePathsCollection);
|
|
||||||
for (int i = 0; i < short.MaxValue; i++)
|
|
||||||
{
|
|
||||||
renamed = 0;
|
|
||||||
jsonFilesCollection = IDirectory.GetFilesCollection(aPropertySingletonDirectory, directorySearchFilter, extension, useCeilingAverage);
|
|
||||||
compareFileNamesToFiles = XDirectory.GetFilesKeyValuePairs(jsonFilesCollection);
|
|
||||||
renamed += XDirectory.LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension);
|
|
||||||
filePairs = XDirectory.GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, extension, compareFileNamesToFiles);
|
|
||||||
renamed += XDirectory.MaybeMove(propertyConfiguration, filePairs, aPropertySingletonDirectory, extension);
|
|
||||||
if (renamed == 0)
|
|
||||||
break;
|
|
||||||
if (i > 10)
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
if (filePairs is null || jsonFilesCollection is null || compareFileNamesToFiles is null)
|
|
||||||
throw new NullReferenceException(nameof(filePairs));
|
|
||||||
return filePairs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Models.Property? GetProperty(Models.FilePair filePair)
|
|
||||||
{
|
|
||||||
Models.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 void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, string fullFileName)
|
|
||||||
{
|
|
||||||
string[] segments = directory.Split(cei.Combined);
|
|
||||||
string? checkDirectory = segments.Length == 1 ?
|
|
||||||
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
|
||||||
segments.Length == 2 ?
|
|
||||||
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
|
||||||
null;
|
|
||||||
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
|
||||||
{
|
|
||||||
string checkFile = Path.Combine(checkDirectory, fileName);
|
|
||||||
if (File.Exists(checkFile))
|
|
||||||
File.Move(checkFile, fullFileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ParallelFor(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string extension, int rootDirectoryLength, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, Models.FilePair filePair, List<FilePair> results)
|
|
||||||
{
|
|
||||||
dlibDotNet?.Tick();
|
|
||||||
bool abandoned = false;
|
|
||||||
Models.FileHolder sourceDirectoryFileHolder;
|
|
||||||
Models.Property? property = GetProperty(filePair);
|
|
||||||
Models.FileHolder imageFileHolder = IFileHolder.Get(filePair.Path);
|
|
||||||
FilePath filePath = FilePath.Get(propertyConfiguration, imageFileHolder, 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 (shouldIgnore is not null)
|
|
||||||
{
|
|
||||||
if (shouldIgnore.Value)
|
|
||||||
{
|
|
||||||
FileInfo fileInfo = new(filePath.FullName);
|
|
||||||
if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden))
|
|
||||||
File.SetAttributes(imageFileHolder.FullName, FileAttributes.Hidden);
|
|
||||||
}
|
|
||||||
if (filePath.HasIgnoreKeyword is not null && filePath.HasIgnoreKeyword.Value != shouldIgnore.Value)
|
|
||||||
{
|
|
||||||
if (filePath.DirectoryFullPath.Contains("Results") && filePath.DirectoryFullPath.Contains("Resize"))
|
|
||||||
File.Delete(filePath.FullName);
|
|
||||||
else
|
|
||||||
throw new NotSupportedException($"Rename File! <{filePath.FileNameFirstSegment}>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
string relativePath = IPath.GetRelativePath(filePair.Path, rootDirectoryLength, forceExtensionToLower: true);
|
|
||||||
bool? lastWriteTimeChanged = property is not null ? propertyConfiguration.PropertiesChangedForProperty || property.LastWriteTime.Ticks != 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(aPropertySingletonDirectory, relativePath, extension)));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string fileName = Path.GetFileName(filePair.Path);
|
|
||||||
CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
|
|
||||||
string directory = Path.Combine(aPropertySingletonDirectory, 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)
|
|
||||||
{
|
|
||||||
File.SetCreationTime(sourceDirectoryFileHolder.FullName, new(filePath.LastWriteTicks));
|
|
||||||
File.SetLastWriteTime(sourceDirectoryFileHolder.FullName, sourceDirectoryFileHolder.LastWriteTime.Value);
|
|
||||||
}
|
|
||||||
Models.Item item = Models.Item.Get(filePath, sourceDirectoryFileHolder, relativePath, isArchive, filePair.IsNotUniqueAndNeedsReview, filePair.IsUnique, isValidImageFormatExtension, property, abandoned, fileSizeChanged, lastWriteTimeChanged);
|
|
||||||
lock (results)
|
|
||||||
results.Add(new(filePair.IsUnique, filePair.Collection, filePath, item));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<FilePair> GetFilePairs(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
|
|
||||||
{
|
|
||||||
List<FilePair> results = [];
|
|
||||||
const string extension = ".json";
|
|
||||||
int maxDegreeOfParallelism = Environment.ProcessorCount;
|
|
||||||
int filesCollectionDirectoryLength = filesCollectionDirectory.Length;
|
|
||||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
|
||||||
List<Models.FilePair> filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filePathsCollection);
|
|
||||||
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, extension, filesCollectionDirectoryLength, splatNineIdentifiers, filePairs[i], results));
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static (int, Models.Container[]) GetContainers(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
|
|
||||||
{
|
|
||||||
List<Models.Container> results = [];
|
|
||||||
string directory;
|
|
||||||
List<Models.Item>? items;
|
|
||||||
Models.Container container;
|
|
||||||
List<string> directories = [];
|
|
||||||
Dictionary<string, List<Models.Item>> directoryToItems = [];
|
|
||||||
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
|
|
||||||
{
|
|
||||||
if (filePaths.Count == 0)
|
|
||||||
continue;
|
|
||||||
directory = filePaths[0].DirectoryFullPath;
|
|
||||||
if (directory is null)
|
|
||||||
continue;
|
|
||||||
if (!directories.Contains(directory))
|
|
||||||
directories.Add(directory);
|
|
||||||
if (!directoryToItems.TryGetValue(directory, out items))
|
|
||||||
{
|
|
||||||
directoryToItems.Add(directory, []);
|
|
||||||
if (!directoryToItems.TryGetValue(directory, out items))
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
|
|
||||||
foreach (FilePair filePair in filePairs)
|
|
||||||
{
|
|
||||||
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
|
|
||||||
{
|
|
||||||
directoryToItems.Add(filePair.FilePath.DirectoryFullPath, []);
|
|
||||||
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
items.Add(filePair.Item);
|
|
||||||
}
|
|
||||||
foreach (KeyValuePair<string, List<Models.Item>> keyValuePair in directoryToItems)
|
|
||||||
{
|
|
||||||
if (keyValuePair.Value.Count == 0)
|
|
||||||
continue;
|
|
||||||
container = new(keyValuePair.Key, new(keyValuePair.Value));
|
|
||||||
results.Add(container);
|
|
||||||
}
|
|
||||||
return (filePairs.Count, results.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
|
|
||||||
{
|
|
||||||
Models.Container[] results;
|
|
||||||
const string directorySearchFilter = "*";
|
|
||||||
(_, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
|
|
||||||
return results.AsReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory)
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
Models.Container[] results;
|
|
||||||
IDlibDotNet? dlibDotNet = null;
|
|
||||||
const bool useCeilingAverage = true;
|
|
||||||
const string fileSearchFilter = "*";
|
|
||||||
const string directorySearchFilter = "*";
|
|
||||||
ReadOnlyCollection<string[]> filesCollection = IDirectory.GetFilesCollection(propertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
|
|
||||||
ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
|
|
||||||
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, propertyConfiguration.RootDirectory, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
|
|
||||||
return (count, results);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static List<int> GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers)
|
|
||||||
{
|
|
||||||
List<int> results = [];
|
|
||||||
ReadOnlyCollection<Models.Item> filteredItems;
|
|
||||||
foreach (Models.Container container in readOnlyContainers)
|
|
||||||
{
|
|
||||||
if (container.Items.Count == 0)
|
|
||||||
continue;
|
|
||||||
filteredItems = GetValidImageItems(propertyConfiguration, container);
|
|
||||||
if (filteredItems.Count == 0)
|
|
||||||
continue;
|
|
||||||
foreach (Models.Item item in filteredItems)
|
|
||||||
{
|
|
||||||
if (item.Property?.Id is null || item.ResizedFileHolder is null)
|
|
||||||
continue;
|
|
||||||
if (results.Contains(item.Property.Id.Value))
|
|
||||||
continue;
|
|
||||||
results.Add(item.Property.Id.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static List<string> GetFilteredDistinctFileNameFirstSegments(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers)
|
|
||||||
{
|
|
||||||
List<string> results = [];
|
|
||||||
ReadOnlyCollection<Models.Item> filteredItems;
|
|
||||||
foreach (Models.Container container in readOnlyContainers)
|
|
||||||
{
|
|
||||||
if (container.Items.Count == 0)
|
|
||||||
continue;
|
|
||||||
filteredItems = GetValidImageItems(propertyConfiguration, container);
|
|
||||||
if (filteredItems.Count == 0)
|
|
||||||
continue;
|
|
||||||
foreach (Models.Item item in filteredItems)
|
|
||||||
{
|
|
||||||
if (item.Property?.Id is null || item.ResizedFileHolder is null)
|
|
||||||
continue;
|
|
||||||
if (results.Contains(item.FilePath.FileNameFirstSegment))
|
|
||||||
continue;
|
|
||||||
results.Add(item.FilePath.FileNameFirstSegment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static ReadOnlyCollection<Models.Item> GetValidImageItems(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems)
|
|
||||||
{
|
|
||||||
List<Models.Item> results = [];
|
|
||||||
List<int> distinct = [];
|
|
||||||
ReadOnlyCollection<Models.Item> filteredItems;
|
|
||||||
foreach (Models.Container container in containers)
|
|
||||||
{
|
|
||||||
if (container.Items.Count == 0)
|
|
||||||
continue;
|
|
||||||
if (!filterItems)
|
|
||||||
filteredItems = container.Items;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
filteredItems = GetValidImageItems(propertyConfiguration, container);
|
|
||||||
if (filteredItems.Count == 0)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
foreach (Models.Item item in filteredItems)
|
|
||||||
{
|
|
||||||
if (item.Property?.Id is null || item.ResizedFileHolder is null)
|
|
||||||
continue;
|
|
||||||
if (distinctItems)
|
|
||||||
{
|
|
||||||
if (distinct.Contains(item.Property.Id.Value))
|
|
||||||
continue;
|
|
||||||
distinct.Add(item.Property.Id.Value);
|
|
||||||
}
|
|
||||||
results.Add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results.AsReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
using System.Collections.ObjectModel;
|
|
||||||
|
|
||||||
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
|
||||||
|
|
||||||
public interface IContainer
|
|
||||||
{
|
|
||||||
|
|
||||||
DateTime[] TestStatic_GetContainerDateTimes(ReadOnlyCollection<Models.Item> items) =>
|
|
||||||
GetContainerDateTimes(items);
|
|
||||||
static DateTime[] GetContainerDateTimes(ReadOnlyCollection<Models.Item> items) =>
|
|
||||||
Container.GetContainerDateTimes(items);
|
|
||||||
|
|
||||||
ReadOnlyCollection<Models.Item> TestStatic_GetValidImageItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
|
||||||
GetValidImageItems(propertyConfiguration, container);
|
|
||||||
static ReadOnlyCollection<Models.Item> GetValidImageItems(Properties.IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
|
||||||
Container.GetValidImageItems(propertyConfiguration, container);
|
|
||||||
|
|
||||||
(int, Models.Container[]) TestStatic_GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
|
||||||
GetContainers(propertyConfiguration, aPropertySingletonDirectory);
|
|
||||||
static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
|
||||||
GetContainers(propertyConfiguration, null, aPropertySingletonDirectory);
|
|
||||||
|
|
||||||
(int, Models.Container[]) TestStatic_GetContainers(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
|
|
||||||
GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
|
|
||||||
static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
|
|
||||||
Container.GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
|
|
||||||
|
|
||||||
ReadOnlyCollection<Models.Container> TestStatic_GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
|
|
||||||
GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, splatNineIdentifiers, filePathsCollection);
|
|
||||||
static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
|
|
||||||
Container.GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, splatNineIdentifiers, filePathsCollection);
|
|
||||||
|
|
||||||
List<int> TestStatic_GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
|
||||||
GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
|
||||||
static List<int> GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
|
||||||
Container.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
|
||||||
|
|
||||||
List<string> TestStatic_GetFilteredDistinctFileNameFirstSegments(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
|
||||||
GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
|
||||||
static List<string> GetFilteredDistinctFileNameFirstSegments(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
|
||||||
Container.GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
|
||||||
|
|
||||||
ReadOnlyCollection<Models.Item> TestStatic_GetValidImageItems(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
|
|
||||||
GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
|
|
||||||
static ReadOnlyCollection<Models.Item> GetValidImageItems(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
|
|
||||||
Container.GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
|
|
||||||
|
|
||||||
}
|
|
@ -50,4 +50,14 @@ public interface IDirectory
|
|||||||
static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) =>
|
static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) =>
|
||||||
XDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
|
XDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
|
||||||
|
|
||||||
|
List<FilePair> TestStatic_GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles) =>
|
||||||
|
GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, compareFileNamesToFiles);
|
||||||
|
static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles) =>
|
||||||
|
XDirectory.GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, compareFileNamesToFiles);
|
||||||
|
|
||||||
|
int TestStatic_MaybeMove(Properties.IPropertyConfiguration propertyConfiguration, List<FilePair> filePairs, string jsonGroupDirectory, string extension) =>
|
||||||
|
MaybeMove(propertyConfiguration, filePairs, jsonGroupDirectory, extension);
|
||||||
|
static int MaybeMove(Properties.IPropertyConfiguration propertyConfiguration, List<FilePair> filePairs, string jsonGroupDirectory, string extension) =>
|
||||||
|
XDirectory.MaybeMove(propertyConfiguration, filePairs, jsonGroupDirectory, extension);
|
||||||
|
|
||||||
}
|
}
|
@ -4,5 +4,7 @@ public interface IDlibDotNet
|
|||||||
{
|
{
|
||||||
|
|
||||||
void Tick();
|
void Tick();
|
||||||
|
(string, string) GetResultsFullGroupDirectories();
|
||||||
|
(string, string, string, string) GetResultsFullGroupDirectories(string outputResolution);
|
||||||
|
|
||||||
}
|
}
|
@ -23,29 +23,16 @@ public interface IId
|
|||||||
static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
|
static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
|
||||||
Id.GetPaddedId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
|
Id.GetPaddedId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
|
||||||
|
|
||||||
string TestStatic_GetIgnoreFullPath(FilePath filePath, Models.FileHolder fileHolder) =>
|
|
||||||
GetIgnoreFullPath(filePath, fileHolder);
|
|
||||||
static string GetIgnoreFullPath(FilePath filePath, Models.FileHolder fileHolder) =>
|
|
||||||
fileHolder.DirectoryFullPath is null ?
|
|
||||||
throw new NotSupportedException() :
|
|
||||||
filePath.Id > -1 ?
|
|
||||||
fileHolder.NameWithoutExtension[^1] == '9' ?
|
|
||||||
Path.Combine(fileHolder.DirectoryFullPath, $"{fileHolder.NameWithoutExtension[..^1]}8{fileHolder.ExtensionLowered}") :
|
|
||||||
throw new NotSupportedException("High") :
|
|
||||||
fileHolder.NameWithoutExtension[^1] == '1' ?
|
|
||||||
Path.Combine(fileHolder.DirectoryFullPath, $"{fileHolder.NameWithoutExtension[..^1]}2{fileHolder.ExtensionLowered}") :
|
|
||||||
throw new NotSupportedException("Low");
|
|
||||||
|
|
||||||
bool TestStatic_NameWithoutExtensionIsIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, string fileNameFirstSegment) =>
|
bool TestStatic_NameWithoutExtensionIsIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, string fileNameFirstSegment) =>
|
||||||
NameWithoutExtensionIsIntelligentIdFormat(propertyConfiguration, fileNameFirstSegment);
|
NameWithoutExtensionIsIntelligentIdFormat(propertyConfiguration, fileNameFirstSegment);
|
||||||
static bool NameWithoutExtensionIsIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, string fileNameFirstSegment) =>
|
static bool NameWithoutExtensionIsIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, string fileNameFirstSegment) =>
|
||||||
fileNameFirstSegment.Length - 1 == propertyConfiguration.IntMinValueLength && fileNameFirstSegment[^1] is '1' or '2' or '8' or '9' && fileNameFirstSegment.All(char.IsNumber);
|
fileNameFirstSegment.Length - 1 == propertyConfiguration.IntMinValueLength && fileNameFirstSegment[^1] is '1' or '2' or '3' or '7' or '8' or '9' && fileNameFirstSegment.All(char.IsNumber);
|
||||||
|
|
||||||
bool TestStatic_NameWithoutExtensionIsPaddedIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
bool TestStatic_NameWithoutExtensionIsPaddedIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
||||||
NameWithoutExtensionIsPaddedIntelligentIdFormat(propertyConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment);
|
NameWithoutExtensionIsPaddedIntelligentIdFormat(propertyConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment);
|
||||||
static bool NameWithoutExtensionIsPaddedIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
static bool NameWithoutExtensionIsPaddedIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
||||||
fileNameFirstSegment.Length == propertyConfiguration.IntMinValueLength + sortOrderOnlyLengthIndex + 1
|
fileNameFirstSegment.Length == propertyConfiguration.IntMinValueLength + sortOrderOnlyLengthIndex + 1
|
||||||
&& fileNameFirstSegment[^1] is '1' or '2' or '8' or '9'
|
&& fileNameFirstSegment[^1] is '1' or '2' or '3' or '7' or '8' or '9'
|
||||||
&& fileNameFirstSegment.All(char.IsNumber);
|
&& fileNameFirstSegment.All(char.IsNumber);
|
||||||
|
|
||||||
bool TestStatic_NameWithoutExtensionIsIdFormat(Properties.IPropertyConfiguration propertyConfiguration, Models.FileHolder fileHolder) =>
|
bool TestStatic_NameWithoutExtensionIsIdFormat(Properties.IPropertyConfiguration propertyConfiguration, Models.FileHolder fileHolder) =>
|
||||||
@ -58,4 +45,19 @@ public interface IId
|
|||||||
static int GetDeterministicHashCode(byte[] value) =>
|
static int GetDeterministicHashCode(byte[] value) =>
|
||||||
Id.GetDeterministicHashCode(value);
|
Id.GetDeterministicHashCode(value);
|
||||||
|
|
||||||
|
int TestStatic_GetHasIgnoreKeyword(FilePath filePath) =>
|
||||||
|
GetHasIgnoreKeyword(filePath);
|
||||||
|
static int GetHasIgnoreKeyword(FilePath filePath) =>
|
||||||
|
Id.GetHasIgnoreKeyword(filePath);
|
||||||
|
|
||||||
|
int TestStatic_GetMissingDateTimeOriginal(FilePath filePath) =>
|
||||||
|
GetMissingDateTimeOriginal(filePath);
|
||||||
|
static int GetMissingDateTimeOriginal(FilePath filePath) =>
|
||||||
|
Id.GetMissingDateTimeOriginal(filePath);
|
||||||
|
|
||||||
|
int TestStatic_GetHasDateTimeOriginal(FilePath filePath) =>
|
||||||
|
GetHasDateTimeOriginal(filePath);
|
||||||
|
static int GetHasDateTimeOriginal(FilePath filePath) =>
|
||||||
|
Id.GetHasDateTimeOriginal(filePath);
|
||||||
|
|
||||||
}
|
}
|
@ -72,4 +72,9 @@ public interface IPath
|
|||||||
static ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups) =>
|
static ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups) =>
|
||||||
XPath.GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, jsonGroups);
|
XPath.GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, jsonGroups);
|
||||||
|
|
||||||
|
byte TestStatic_GetEnum(FilePath filePath) =>
|
||||||
|
GetEnum(filePath);
|
||||||
|
static byte GetEnum(FilePath filePath) =>
|
||||||
|
XPath.GetEnum(filePath);
|
||||||
|
|
||||||
}
|
}
|
@ -23,11 +23,6 @@ public interface IProperty
|
|||||||
static string GetDiffRootDirectory(string diffPropertyDirectory) =>
|
static string GetDiffRootDirectory(string diffPropertyDirectory) =>
|
||||||
Property.GetDiffRootDirectory(diffPropertyDirectory);
|
Property.GetDiffRootDirectory(diffPropertyDirectory);
|
||||||
|
|
||||||
bool TestStatic_Any(Models.Container[] propertyHolderCollections) =>
|
|
||||||
Any(propertyHolderCollections);
|
|
||||||
static bool Any(Models.Container[] propertyHolderCollections) =>
|
|
||||||
Property.Any(propertyHolderCollections);
|
|
||||||
|
|
||||||
(bool?, string[]) TestStatic_IsWrongYear(string[] segments, string year) =>
|
(bool?, string[]) TestStatic_IsWrongYear(string[] segments, string year) =>
|
||||||
IsWrongYear(segments, year);
|
IsWrongYear(segments, year);
|
||||||
static (bool?, string[]) IsWrongYear(string[] segments, string year) =>
|
static (bool?, string[]) IsWrongYear(string[] segments, string year) =>
|
||||||
@ -43,21 +38,6 @@ public interface IProperty
|
|||||||
static List<DateTime> GetDateTimes(Models.Property property) =>
|
static List<DateTime> GetDateTimes(Models.Property property) =>
|
||||||
Property.GetDateTimes(property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeFromName, property.DateTimeOriginal, property.GPSDateStamp);
|
Property.GetDateTimes(property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeFromName, property.DateTimeOriginal, property.GPSDateStamp);
|
||||||
|
|
||||||
double TestStatic_GetStandardDeviation(List<long> values, double average) =>
|
|
||||||
GetStandardDeviation(values, average);
|
|
||||||
static double GetStandardDeviation(List<long> values, double average) =>
|
|
||||||
Property.GetStandardDeviation(values, average);
|
|
||||||
|
|
||||||
TimeSpan TestStatic_GetThreeStandardDeviationHigh(int minimum, Models.Container container) =>
|
|
||||||
GetThreeStandardDeviationHigh(minimum, container);
|
|
||||||
static TimeSpan GetThreeStandardDeviationHigh(int minimum, Models.Container container) =>
|
|
||||||
Property.GetThreeStandardDeviationHigh(minimum, container);
|
|
||||||
|
|
||||||
(int, List<DateTime>, List<Models.Item>) TestStatic_Get(Models.Container container, TimeSpan threeStandardDeviationHigh, int i) =>
|
|
||||||
Get(container, threeStandardDeviationHigh, i);
|
|
||||||
static (int, List<DateTime>, List<Models.Item>) Get(Models.Container container, TimeSpan threeStandardDeviationHigh, int i) =>
|
|
||||||
Property.Get(container, threeStandardDeviationHigh, i);
|
|
||||||
|
|
||||||
List<DateTime> TestStatic_GetDateTimes(DateTime creationTime, DateTime lastWriteTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, DateTime? gpsDateStamp) =>
|
List<DateTime> TestStatic_GetDateTimes(DateTime creationTime, DateTime lastWriteTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, DateTime? gpsDateStamp) =>
|
||||||
GetDateTimes(creationTime, lastWriteTime, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, gpsDateStamp);
|
GetDateTimes(creationTime, lastWriteTime, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, gpsDateStamp);
|
||||||
static List<DateTime> GetDateTimes(DateTime creationTime, DateTime lastWriteTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, DateTime? gpsDateStamp) =>
|
static List<DateTime> GetDateTimes(DateTime creationTime, DateTime lastWriteTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, DateTime? gpsDateStamp) =>
|
||||||
|
@ -28,13 +28,22 @@ internal abstract class Id
|
|||||||
_ = results.Append(intelligentId[i]);
|
_ = results.Append(intelligentId[i]);
|
||||||
_ = results.Append(intelligentId[^3]).Append(intelligentId[^2]);
|
_ = results.Append(intelligentId[^3]).Append(intelligentId[^2]);
|
||||||
result = int.Parse(results.ToString());
|
result = int.Parse(results.ToString());
|
||||||
if (intelligentId[^1] is '1' or '2')
|
if (intelligentId[^1] is '1' or '2' or '3')
|
||||||
result *= -1;
|
result *= -1;
|
||||||
else if (intelligentId[^1] is not '9' and not '8')
|
else if (intelligentId[^1] is not '9' and not '8' and not '7')
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static int GetHasIgnoreKeyword(FilePath filePath) =>
|
||||||
|
filePath.Id > -1 ? 8 : 2;
|
||||||
|
|
||||||
|
internal static int GetMissingDateTimeOriginal(FilePath filePath) =>
|
||||||
|
filePath.Id > -1 ? 7 : 3;
|
||||||
|
|
||||||
|
internal static int GetHasDateTimeOriginal(FilePath filePath) =>
|
||||||
|
filePath.Id > -1 ? 9 : 1;
|
||||||
|
|
||||||
internal static string GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal)
|
internal static string GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal)
|
||||||
{
|
{
|
||||||
string result;
|
string result;
|
||||||
@ -48,12 +57,12 @@ internal abstract class Id
|
|||||||
List<char> resultAllInOneSubdirectoryChars = [];
|
List<char> resultAllInOneSubdirectoryChars = [];
|
||||||
if (id > -1)
|
if (id > -1)
|
||||||
{
|
{
|
||||||
key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? 8 : 9;
|
key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? 8 : hasDateTimeOriginal is not null && hasDateTimeOriginal.Value ? 9 : 7;
|
||||||
value = id.ToString().PadLeft(propertyConfiguration.IntMinValueLength, '0');
|
value = id.ToString().PadLeft(propertyConfiguration.IntMinValueLength, '0');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? 2 : 1;
|
key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? 2 : hasDateTimeOriginal is not null && hasDateTimeOriginal.Value ? 1 : 3;
|
||||||
value = id.ToString()[1..].PadLeft(propertyConfiguration.IntMinValueLength, '0');
|
value = id.ToString()[1..].PadLeft(propertyConfiguration.IntMinValueLength, '0');
|
||||||
}
|
}
|
||||||
for (int i = value.Length - propertyConfiguration.ResultAllInOneSubdirectoryLength - 1; i > -1; i--)
|
for (int i = value.Length - propertyConfiguration.ResultAllInOneSubdirectoryLength - 1; i > -1; i--)
|
||||||
|
@ -171,112 +171,4 @@ internal abstract class Property
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static double GetStandardDeviation(List<long> values, double average)
|
|
||||||
{
|
|
||||||
double result = 0;
|
|
||||||
if (values.Count == 0)
|
|
||||||
throw new Exception("Collection must have at least one value!");
|
|
||||||
double sum = values.Sum(l => (l - average) * (l - average));
|
|
||||||
result = Math.Sqrt(sum / values.Count);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long GetThreeStandardDeviationHigh(ref List<long> ticksCollection, long min)
|
|
||||||
{
|
|
||||||
long result;
|
|
||||||
ticksCollection = (from l in ticksCollection select l - min).ToList();
|
|
||||||
double sum = ticksCollection.Sum();
|
|
||||||
double average = sum / ticksCollection.Count;
|
|
||||||
double standardDeviation = GetStandardDeviation(ticksCollection, average);
|
|
||||||
result = (long)Math.Ceiling(average + min + (standardDeviation * 3));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static TimeSpan GetThreeStandardDeviationHigh(int minimum, Models.Container container)
|
|
||||||
{
|
|
||||||
TimeSpan result;
|
|
||||||
DateTime? minimumDateTime;
|
|
||||||
List<long> ticksCollection = [];
|
|
||||||
foreach (Models.Item item in container.Items)
|
|
||||||
{
|
|
||||||
if (item.Property is null)
|
|
||||||
continue;
|
|
||||||
minimumDateTime = GetMinimumDateTime(item.Property);
|
|
||||||
if (minimumDateTime is null)
|
|
||||||
continue;
|
|
||||||
ticksCollection.Add(minimumDateTime.Value.Ticks);
|
|
||||||
}
|
|
||||||
long threeStandardDeviationHigh;
|
|
||||||
long min;
|
|
||||||
if (ticksCollection.Count == 0)
|
|
||||||
min = 0;
|
|
||||||
else
|
|
||||||
min = ticksCollection.Min();
|
|
||||||
if (ticksCollection.Count < minimum)
|
|
||||||
threeStandardDeviationHigh = long.MaxValue;
|
|
||||||
else
|
|
||||||
threeStandardDeviationHigh = GetThreeStandardDeviationHigh(ref ticksCollection, min);
|
|
||||||
result = new TimeSpan(threeStandardDeviationHigh - min);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static (int, List<DateTime>, List<Models.Item>) Get(Models.Container container, TimeSpan threeStandardDeviationHigh, int i)
|
|
||||||
{
|
|
||||||
List<Models.Item> results = [];
|
|
||||||
int j = i;
|
|
||||||
long? ticks;
|
|
||||||
Models.Item item;
|
|
||||||
TimeSpan timeSpan;
|
|
||||||
Models.Item nextItem;
|
|
||||||
DateTime? minimumDateTime;
|
|
||||||
DateTime? nextMinimumDateTime;
|
|
||||||
List<DateTime> dateTimes = [];
|
|
||||||
for (; j < container.Items.Count; j++)
|
|
||||||
{
|
|
||||||
ticks = null;
|
|
||||||
item = container.Items[j];
|
|
||||||
if (item.Property is null)
|
|
||||||
continue;
|
|
||||||
minimumDateTime = GetMinimumDateTime(item.Property);
|
|
||||||
if (minimumDateTime is null)
|
|
||||||
continue;
|
|
||||||
for (int k = j + 1; k < container.Items.Count; k++)
|
|
||||||
{
|
|
||||||
nextItem = container.Items[k];
|
|
||||||
if (nextItem.Property is null)
|
|
||||||
continue;
|
|
||||||
nextMinimumDateTime = GetMinimumDateTime(nextItem.Property);
|
|
||||||
if (nextMinimumDateTime is null)
|
|
||||||
continue;
|
|
||||||
ticks = nextMinimumDateTime.Value.Ticks;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
results.Add(item);
|
|
||||||
dateTimes.Add(minimumDateTime.Value);
|
|
||||||
if (ticks.HasValue)
|
|
||||||
{
|
|
||||||
timeSpan = new(ticks.Value - minimumDateTime.Value.Ticks);
|
|
||||||
if (timeSpan > threeStandardDeviationHigh)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new(j, dateTimes, results);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static bool Any(Models.Container[] containers)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
foreach (Models.Container container in containers)
|
|
||||||
{
|
|
||||||
if (container.Items.Count == 0)
|
|
||||||
continue;
|
|
||||||
if ((from l in container.Items where l.Any() select true).Any())
|
|
||||||
{
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -33,6 +33,7 @@ internal abstract partial class XDirectory
|
|||||||
internal static ReadOnlyCollection<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage)
|
internal static ReadOnlyCollection<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage)
|
||||||
{
|
{
|
||||||
List<string[]> results = [];
|
List<string[]> results = [];
|
||||||
|
string[] files;
|
||||||
if (!fileSearchFilter.Contains('*'))
|
if (!fileSearchFilter.Contains('*'))
|
||||||
fileSearchFilter = string.Concat('*', fileSearchFilter);
|
fileSearchFilter = string.Concat('*', fileSearchFilter);
|
||||||
if (!directorySearchFilter.Contains('*'))
|
if (!directorySearchFilter.Contains('*'))
|
||||||
@ -44,7 +45,12 @@ internal abstract partial class XDirectory
|
|||||||
foreach (string innerDirectory in directories)
|
foreach (string innerDirectory in directories)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{ results.Add(Directory.GetFiles(innerDirectory, fileSearchFilter, SearchOption.AllDirectories)); }
|
{
|
||||||
|
files = Directory.GetFiles(innerDirectory, fileSearchFilter, SearchOption.AllDirectories);
|
||||||
|
if (files.Length == 0)
|
||||||
|
continue;
|
||||||
|
results.Add(files);
|
||||||
|
}
|
||||||
catch (UnauthorizedAccessException)
|
catch (UnauthorizedAccessException)
|
||||||
{ continue; }
|
{ continue; }
|
||||||
}
|
}
|
||||||
@ -62,77 +68,6 @@ internal abstract partial class XDirectory
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<string[]> filesCollection)
|
|
||||||
{
|
|
||||||
Dictionary<string, List<string>> results = [];
|
|
||||||
string fileName;
|
|
||||||
List<string>? collection;
|
|
||||||
foreach (string[] files in filesCollection)
|
|
||||||
{
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
fileName = Path.GetFileName(file);
|
|
||||||
if (!results.TryGetValue(fileName, out collection))
|
|
||||||
{
|
|
||||||
results.Add(fileName, []);
|
|
||||||
if (!results.TryGetValue(fileName, out collection))
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
collection.Add(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
|
|
||||||
{
|
|
||||||
Dictionary<string, List<string>> results = [];
|
|
||||||
List<string>? collection;
|
|
||||||
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
|
|
||||||
{
|
|
||||||
foreach (FilePath filePath in filePaths)
|
|
||||||
{
|
|
||||||
if (!results.TryGetValue(filePath.Name, out collection))
|
|
||||||
{
|
|
||||||
results.Add(filePath.Name, []);
|
|
||||||
if (!results.TryGetValue(filePath.Name, out collection))
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
collection.Add(filePath.FullName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static int LookForAbandoned(ReadOnlyCollection<string[]> jsonFilesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension)
|
|
||||||
{
|
|
||||||
string fileName;
|
|
||||||
string fileNameWith;
|
|
||||||
List<string>? collection;
|
|
||||||
string fileNameUpperExtension;
|
|
||||||
int length = extension.Length;
|
|
||||||
List<string> renameCollection = [];
|
|
||||||
foreach (string[] files in jsonFilesCollection)
|
|
||||||
{
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
fileNameWith = Path.GetFileName(file);
|
|
||||||
if (fileNameWith.Length < length || !fileNameWith.EndsWith(extension))
|
|
||||||
throw new Exception();
|
|
||||||
fileName = fileNameWith[..^length];
|
|
||||||
if (!fileNamesToFiles.TryGetValue(fileName, out collection))
|
|
||||||
{
|
|
||||||
fileNameUpperExtension = string.Concat(Path.GetFileNameWithoutExtension(fileName), Path.GetExtension(fileName).ToUpper());
|
|
||||||
if (fileName == fileNameUpperExtension || !fileNamesToFiles.TryGetValue(fileNameUpperExtension, out collection))
|
|
||||||
renameCollection.Add(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (renameCollection.Count > 0)
|
|
||||||
IDirectory.MoveFiles(renameCollection, "{}", "{abd}");
|
|
||||||
return renameCollection.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool GetIsNotUniqueAndNeedsReview(string file, List<string> collection)
|
private static bool GetIsNotUniqueAndNeedsReview(string file, List<string> collection)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
@ -175,13 +110,15 @@ internal abstract partial class XDirectory
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles)
|
internal static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles)
|
||||||
{
|
{
|
||||||
List<FilePair> results = [];
|
List<FilePair> results = [];
|
||||||
string? match;
|
string? match;
|
||||||
|
FilePair filePair;
|
||||||
bool uniqueFileName;
|
bool uniqueFileName;
|
||||||
List<string>? collection;
|
List<string>? collection;
|
||||||
bool? isNotUniqueAndNeedsReview;
|
bool? isNotUniqueAndNeedsReview;
|
||||||
|
string fileNameWithoutExtensionMinusOne;
|
||||||
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
|
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
|
||||||
{
|
{
|
||||||
foreach (FilePath filePath in filePaths)
|
foreach (FilePath filePath in filePaths)
|
||||||
@ -189,25 +126,43 @@ internal abstract partial class XDirectory
|
|||||||
isNotUniqueAndNeedsReview = null;
|
isNotUniqueAndNeedsReview = null;
|
||||||
if (propertyConfiguration.IgnoreExtensions.Contains(filePath.ExtensionLowered))
|
if (propertyConfiguration.IgnoreExtensions.Contains(filePath.ExtensionLowered))
|
||||||
continue;
|
continue;
|
||||||
if (!fileNamesToFiles.TryGetValue(filePath.Name, out collection))
|
fileNameWithoutExtensionMinusOne = filePath.NameWithoutExtension[..^1];
|
||||||
|
if (!fileNamesToFiles.TryGetValue(fileNameWithoutExtensionMinusOne, out collection))
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
uniqueFileName = collection.Count == 1;
|
uniqueFileName = collection.Count == 1;
|
||||||
if (!uniqueFileName)
|
if (!uniqueFileName)
|
||||||
isNotUniqueAndNeedsReview = GetIsNotUniqueAndNeedsReview(filePath.FullName, collection);
|
isNotUniqueAndNeedsReview = GetIsNotUniqueAndNeedsReview(filePath.FullName, collection);
|
||||||
if (!compareFileNamesToFiles.TryGetValue(string.Concat(filePath.Name, extension), out collection))
|
if (!compareFileNamesToFiles.TryGetValue(fileNameWithoutExtensionMinusOne, out collection))
|
||||||
results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, [], null));
|
filePair = new(Path: filePath.FullName,
|
||||||
|
IsUnique: uniqueFileName,
|
||||||
|
IsNotUniqueAndNeedsReview: isNotUniqueAndNeedsReview,
|
||||||
|
Collection: [],
|
||||||
|
Match: null);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (collection.Count == 0)
|
if (collection.Count == 0)
|
||||||
results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, collection, null));
|
filePair = new(Path: filePath.FullName,
|
||||||
|
IsUnique: uniqueFileName,
|
||||||
|
IsNotUniqueAndNeedsReview: isNotUniqueAndNeedsReview,
|
||||||
|
Collection: collection,
|
||||||
|
Match: null);
|
||||||
else if (uniqueFileName && collection.Count == 1)
|
else if (uniqueFileName && collection.Count == 1)
|
||||||
results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, collection, collection.First()));
|
filePair = new(Path: filePath.FullName,
|
||||||
|
IsUnique: uniqueFileName,
|
||||||
|
IsNotUniqueAndNeedsReview: isNotUniqueAndNeedsReview,
|
||||||
|
Collection: collection,
|
||||||
|
Match: collection.First());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
match = GetMatch(filePath.FullName, collection);
|
match = GetMatch(filePath.FullName, collection);
|
||||||
results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, collection, match));
|
filePair = new(Path: filePath.FullName,
|
||||||
|
IsUnique: uniqueFileName,
|
||||||
|
IsNotUniqueAndNeedsReview: isNotUniqueAndNeedsReview,
|
||||||
|
Collection: collection,
|
||||||
|
Match: match);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
results.Add(filePair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
@ -458,6 +413,7 @@ internal abstract partial class XDirectory
|
|||||||
{
|
{
|
||||||
List<string> results = [];
|
List<string> results = [];
|
||||||
FileInfo fileInfo;
|
FileInfo fileInfo;
|
||||||
|
List<string> distinctExtensions = [];
|
||||||
foreach ((FilePath filePath, string to) in toDoCollection)
|
foreach ((FilePath filePath, string to) in toDoCollection)
|
||||||
{
|
{
|
||||||
tick?.Invoke();
|
tick?.Invoke();
|
||||||
@ -471,6 +427,8 @@ internal abstract partial class XDirectory
|
|||||||
results.Add(filePath.NameWithoutExtension);
|
results.Add(filePath.NameWithoutExtension);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (!distinctExtensions.Contains(filePath.ExtensionLowered))
|
||||||
|
distinctExtensions.Add(filePath.ExtensionLowered);
|
||||||
if (move || moveBack)
|
if (move || moveBack)
|
||||||
File.Move(filePath.FullName, to);
|
File.Move(filePath.FullName, to);
|
||||||
else
|
else
|
||||||
|
@ -292,6 +292,9 @@ internal abstract class XPath
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static byte GetEnum(FilePath filePath) =>
|
||||||
|
GetEnum(filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal);
|
||||||
|
|
||||||
internal static CombinedEnumAndIndex GetCombinedEnumAndIndex(int resultAllInOneSubdirectoryLength, FilePath filePath, string fileName)
|
internal static CombinedEnumAndIndex GetCombinedEnumAndIndex(int resultAllInOneSubdirectoryLength, FilePath filePath, string fileName)
|
||||||
{
|
{
|
||||||
CombinedEnumAndIndex result;
|
CombinedEnumAndIndex result;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user