11 Commits

Author SHA1 Message Date
e728838d25 CombinedEnumAndIndex 2025-03-08 16:44:08 -07:00
ac298166e9 Exif Size 2025-03-02 08:38:01 -07:00
0b793904b3 Format 2025-03-02 08:37:36 -07:00
e053dd5746 Bump 2025-03-02 08:32:03 -07:00
ee0219f321 Using PersonContainer for PersonDisplayDirectoryName 2024-12-29 11:51:08 -07:00
75cfb2a0d9 Alignment with AA 2024-12-28 19:36:44 -07:00
17be39bef9 Updated Offset date to update images from new camera 2024-12-08 19:05:54 -07:00
c085ac3f76 Random with Immich and IsArchive 2024-11-24 15:47:19 -07:00
a6b3318eec net9.0 2024-11-23 21:37:12 -07:00
49e9daea8f IgnoreExtensions 2024-11-09 09:38:28 -07:00
e2e6e15ea2 d8013da9 2024-11-09 09:38:20 -07:00
111 changed files with 1206 additions and 766 deletions

80
.vscode/launch.json vendored
View File

@ -10,8 +10,8 @@
"name": "Compare", "name": "Compare",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Compare/bin/Debug/net8.0/win-x64/Compare.dll", "program": "${workspaceFolder}/Compare/bin/Debug/net9.0/win-x64/Compare.dll",
"args": [ "args": [
"s" "s"
], ],
@ -27,8 +27,8 @@
"name": "Copy-Distinct", "name": "Copy-Distinct",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Copy-Distinct/bin/Debug/net8.0/win-x64/Copy-Distinct.dll", "program": "${workspaceFolder}/Copy-Distinct/bin/Debug/net9.0/win-x64/Copy-Distinct.dll",
"args": [], "args": [],
"env": { "env": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
@ -42,8 +42,8 @@
"name": "Duplicate-Search", "name": "Duplicate-Search",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Duplicate-Search/bin/Debug/net8.0/win-x64/Duplicate-Search.dll", "program": "${workspaceFolder}/Duplicate-Search/bin/Debug/net9.0/win-x64/Duplicate-Search.dll",
"args": [ "args": [
"s" "s"
], ],
@ -59,8 +59,8 @@
"name": "Date-Group", "name": "Date-Group",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Date-Group/bin/Debug/net8.0/win-x64/Date-Group.dll", "program": "${workspaceFolder}/Date-Group/bin/Debug/net9.0/win-x64/Date-Group.dll",
"args": [ "args": [
"s" "s"
], ],
@ -76,8 +76,8 @@
"name": "Delete-By-Distinct", "name": "Delete-By-Distinct",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Delete-By-Distinct/bin/Debug/net8.0/win-x64/Delete-By-Distinct.dll", "program": "${workspaceFolder}/Delete-By-Distinct/bin/Debug/net9.0/win-x64/Delete-By-Distinct.dll",
"args": [ "args": [
"s" "s"
], ],
@ -93,8 +93,8 @@
"name": "Delete-By-Relative", "name": "Delete-By-Relative",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Delete-By-Relative/bin/Debug/net8.0/win-x64/Delete-By-Relative.dll", "program": "${workspaceFolder}/Delete-By-Relative/bin/Debug/net9.0/win-x64/Delete-By-Relative.dll",
"args": [ "args": [
"s" "s"
], ],
@ -110,8 +110,8 @@
"name": "Drag-Drop", "name": "Drag-Drop",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Drag-Drop/bin/Debug/net8.0-windows/win-x64/Drag-Drop.dll", "program": "${workspaceFolder}/Drag-Drop/bin/Debug/net9.0-windows/win-x64/Drag-Drop.dll",
"args": [ "args": [
"s" "s"
], ],
@ -127,8 +127,8 @@
"name": "Drag-Drop-Explorer", "name": "Drag-Drop-Explorer",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Drag-Drop-Explorer/bin/Debug/net8.0-windows/win-x64/Drag-Drop-Explorer.dll", "program": "${workspaceFolder}/Drag-Drop-Explorer/bin/Debug/net9.0-windows/win-x64/Drag-Drop-Explorer.dll",
"args": [ "args": [
"s" "s"
], ],
@ -144,8 +144,8 @@
"name": "Drag-Drop-Move", "name": "Drag-Drop-Move",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Drag-Drop-Move/bin/Debug/net8.0-windows/win-x64/Drag-Drop-Move.dll", "program": "${workspaceFolder}/Drag-Drop-Move/bin/Debug/net9.0-windows/win-x64/Drag-Drop-Move.dll",
"args": [ "args": [
"s" "s"
], ],
@ -161,8 +161,8 @@
"name": "Drag-Drop-Set-Property-Item", "name": "Drag-Drop-Set-Property-Item",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Drag-Drop-Set-Property-Item/bin/Debug/net8.0-windows/win-x64/Drag-Drop-Set-Property-Item.dll", "program": "${workspaceFolder}/Drag-Drop-Set-Property-Item/bin/Debug/net9.0-windows/win-x64/Drag-Drop-Set-Property-Item.dll",
"args": [ "args": [
"s" "s"
], ],
@ -178,8 +178,8 @@
"name": "Instance", "name": "Instance",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildInstance",
"program": "${workspaceFolder}/Instance/bin/Debug/net8.0/win-x64/Instance.dll", "program": "${workspaceFolder}/Instance/bin/Debug/net9.0/win-x64/Instance.dll",
"args": [ "args": [
"s" "s"
], ],
@ -195,8 +195,8 @@
"name": "Mirror-Length", "name": "Mirror-Length",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Mirror-Length/bin/Debug/net8.0/win-x64/Mirror-Length.dll", "program": "${workspaceFolder}/Mirror-Length/bin/Debug/net9.0/win-x64/Mirror-Length.dll",
"args": [], "args": [],
"env": { "env": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
@ -210,8 +210,8 @@
"name": "Metadata-Query", "name": "Metadata-Query",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Metadata-Query/bin/Debug/net8.0/win-x64/Metadata-Query.dll", "program": "${workspaceFolder}/Metadata-Query/bin/Debug/net9.0/win-x64/Metadata-Query.dll",
"args": [ "args": [
"s" "s"
], ],
@ -227,8 +227,8 @@
"name": "Move-By-Id", "name": "Move-By-Id",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Move-By-Id/bin/Debug/net8.0/win-x64/Move-By-Id.dll", "program": "${workspaceFolder}/Move-By-Id/bin/Debug/net9.0/win-x64/Move-By-Id.dll",
"args": [ "args": [
"s" "s"
], ],
@ -244,8 +244,8 @@
"name": "Not-Copy-Copy", "name": "Not-Copy-Copy",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Not-Copy-Copy/bin/Debug/net8.0/win-x64/Not-Copy-Copy.dll", "program": "${workspaceFolder}/Not-Copy-Copy/bin/Debug/net9.0/win-x64/Not-Copy-Copy.dll",
"args": [ "args": [
"s" "s"
], ],
@ -261,8 +261,8 @@
"name": "Offset-Date-Time-Original", "name": "Offset-Date-Time-Original",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Offset-Date-Time-Original/bin/Debug/net8.0/win-x64/Offset-Date-Time-Original.dll", "program": "${workspaceFolder}/Offset-Date-Time-Original/bin/Debug/net9.0/win-x64/Offset-Date-Time-Original.dll",
"args": [ "args": [
"s" "s"
], ],
@ -278,8 +278,8 @@
"name": "PrepareForOld", "name": "PrepareForOld",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/PrepareForOld/bin/Debug/net8.0/win-x64/PrepareForOld.dll", "program": "${workspaceFolder}/PrepareForOld/bin/Debug/net9.0/win-x64/PrepareForOld.dll",
"args": [ "args": [
"s" "s"
], ],
@ -295,8 +295,8 @@
"name": "Person", "name": "Person",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Person/bin/Debug/net8.0/Person.dll", "program": "${workspaceFolder}/Person/bin/Debug/net9.0/Person.dll",
"args": [ "args": [
"s" "s"
], ],
@ -312,8 +312,8 @@
"name": "Rename", "name": "Rename",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Rename/bin/Debug/net8.0/win-x64/Rename.dll", "program": "${workspaceFolder}/Rename/bin/Debug/net9.0/win-x64/Rename.dll",
"args": [ "args": [
"s" "s"
], ],
@ -329,8 +329,8 @@
"name": "Set-Created-Date", "name": "Set-Created-Date",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildSolution",
"program": "${workspaceFolder}/Set-Created-Date/bin/Debug/net8.0/win-x64/Set-Created-Date.dll", "program": "${workspaceFolder}/Set-Created-Date/bin/Debug/net9.0/win-x64/Set-Created-Date.dll",
"args": [ "args": [
"s" "s"
], ],

5
.vscode/mklink.md vendored
View File

@ -13,3 +13,8 @@ mklink /J "D:\1-Images-A\Images-4083e56a-Results\A2)People\4083e56a\{}\!" "D:\1-
```bash ```bash
mklink /J "L:\Git\View-by-Distance-MKLink-Console\.Immich" "D:\1-Images-A\Images-c9dbce3b-Results\F)Immich\c9dbce3b\{}" mklink /J "L:\Git\View-by-Distance-MKLink-Console\.Immich" "D:\1-Images-A\Images-c9dbce3b-Results\F)Immich\c9dbce3b\{}"
``` ```
```bash 1740946894364 = 638765436943640000 = 2025-0.Winter = Sun Mar 02 2025 13:21:33 GMT-0700 (Mountain Standard Time)
mklink /J "V:\Tmp\Phares\Pictures-Results" "V:\6-Other-Large-Z\Current-Results-Test"
mklink /J "V:\1-Images-A\Images-0b793904-Results" "V:\6-Other-Large-Z\Current-Results"
```

View File

@ -23,6 +23,9 @@
"Immich", "Immich",
"jfif", "jfif",
"JOSN", "JOSN",
"makernote",
"Makernote",
"Makernotes",
"mmod", "mmod",
"Nicéphore", "Nicéphore",
"Niépce", "Niépce",
@ -32,6 +35,8 @@
"permyriad", "permyriad",
"Phares", "Phares",
"Phgtv", "Phgtv",
"photoshop",
"Photoshop",
"RDHC", "RDHC",
"Rects", "Rects",
"resnet", "resnet",

38
.vscode/tasks.json vendored
View File

@ -53,7 +53,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "build", "label": "buildSolution",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
@ -63,6 +63,42 @@
"/consoleloggerparameters:NoSummary" "/consoleloggerparameters:NoSummary"
], ],
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
},
{
"label": "buildInstance",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Instance/Instance.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "buildShared",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Shared/View-by-Distance.Shared.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "buildMetadata",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Metadata/Metadata.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
} }
] ]
} }

View File

@ -4,7 +4,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>BlurHash.Core</PackageId> <PackageId>BlurHash.Core</PackageId>
@ -18,6 +18,6 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Memory" Version="4.5.5" /> <PackageReference Include="System.Memory" Version="4.6.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -4,7 +4,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.BlurHash</PackageId> <PackageId>Phares.View.by.Distance.BlurHash</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -34,7 +34,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="8.0.10" /> <PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -11,20 +11,28 @@ public class C2_BlurHasher : IBlurHasher
{ {
private readonly IPropertyConfiguration _PropertyConfiguration; private readonly IPropertyConfiguration _PropertyConfiguration;
private readonly Dictionary<string, ReadOnlyCollection<string>> _FileGroups; private readonly ReadOnlyDictionary<byte, ReadOnlyCollection<string>>[] _ResultContentFileGroups;
private readonly ReadOnlyDictionary<byte, ReadOnlyCollection<string>>[] _ResultSingletonFileGroups;
public C2_BlurHasher(IPropertyConfiguration propertyConfiguration) public C2_BlurHasher(IPropertyConfiguration propertyConfiguration)
{ {
_FileGroups = [];
_PropertyConfiguration = propertyConfiguration; _PropertyConfiguration = propertyConfiguration;
_ResultContentFileGroups = [new(new Dictionary<byte, ReadOnlyCollection<string>>())];
_ResultSingletonFileGroups = [new(new Dictionary<byte, ReadOnlyCollection<string>>())];
} }
public void Update(string resultsFullGroupDirectory) public void Update(string resultsFullGroupDirectory)
{ {
_FileGroups.Clear(); ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, resultsFullGroupDirectory, [_PropertyConfiguration.ResultContent, _PropertyConfiguration.ResultSingleton]);
ReadOnlyDictionary<string, ReadOnlyCollection<string>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, resultsFullGroupDirectory, [_PropertyConfiguration.ResultContent, _PropertyConfiguration.ResultSingleton]); foreach (KeyValuePair<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePair in keyValuePairs)
foreach (KeyValuePair<string, ReadOnlyCollection<string>> keyValuePair in keyValuePairs) {
_FileGroups.Add(keyValuePair.Key, keyValuePair.Value); if (keyValuePair.Key == _PropertyConfiguration.ResultContent)
_ResultContentFileGroups[0] = keyValuePair.Value;
else if (keyValuePair.Key == _PropertyConfiguration.ResultSingleton)
_ResultSingletonFileGroups[0] = keyValuePair.Value;
else
throw new Exception();
}
} }
string IBlurHasher.Encode(FileHolder fileHolder) string IBlurHasher.Encode(FileHolder fileHolder)
@ -40,20 +48,39 @@ public class C2_BlurHasher : IBlurHasher
return result; 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);
}
}
string IBlurHasher.GetFile(FilePath filePath) string IBlurHasher.GetFile(FilePath filePath)
{ {
string result; string result;
if (_FileGroups.Count == 0) if (_ResultSingletonFileGroups[0].Count == 0)
throw new Exception("Call Update first!"); throw new Exception("Call Update first!");
(_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); string fileName = $"{filePath.Name}.csv";
result = Path.Combine(_FileGroups[_PropertyConfiguration.ResultSingleton][directoryIndex], $"{filePath.Name}.csv"); CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
string directory = _ResultSingletonFileGroups[0][cei.Enum][cei.Index];
result = Path.Combine(directory, fileName);
MoveIf(fileName, cei, directory, result);
return result; return result;
} }
string IBlurHasher.EncodeAndSave(FilePath filePath, FileHolder fileHolder) string IBlurHasher.EncodeAndSave(FilePath filePath, FileHolder fileHolder)
{ {
string result; string result;
if (_FileGroups.Count == 0) if (_ResultSingletonFileGroups[0].Count == 0)
throw new Exception("Call Update first!"); throw new Exception("Call Update first!");
int actualByte; int actualByte;
string extension = ".png"; string extension = ".png";
@ -70,15 +97,18 @@ public class C2_BlurHasher : IBlurHasher
byte[] blurHashBytes = Encoding.UTF8.GetBytes(result); byte[] blurHashBytes = Encoding.UTF8.GetBytes(result);
string joined = string.Join(string.Empty, blurHashBytes.Select(l => l.ToString("000"))); string joined = string.Join(string.Empty, blurHashBytes.Select(l => l.ToString("000")));
string fileNameWithoutExtension = $"{componentsX}x{componentsY}-{outputWidth}x{outputHeight}-{joined}"; string fileNameWithoutExtension = $"{componentsX}x{componentsY}-{outputWidth}x{outputHeight}-{joined}";
string fileName = $"{fileNameWithoutExtension}{extension}";
string contents = string.Concat(result, Environment.NewLine, fileNameWithoutExtension, Environment.NewLine, extension); string contents = string.Concat(result, Environment.NewLine, fileNameWithoutExtension, Environment.NewLine, extension);
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(file, contents, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(file, contents, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
(_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
file = Path.Combine(_FileGroups[_PropertyConfiguration.ResultContent][directoryIndex], $"{fileNameWithoutExtension}{extension}"); string directory = _ResultContentFileGroups[0][cei.Enum][cei.Index];
if (!File.Exists(file)) string fullFileName = Path.Combine(directory, fileName);
MoveIf(fileName, cei, directory, fullFileName);
if (!File.Exists(fullFileName))
{ {
try try
{ {
using FileStream fileStream = new(file, FileMode.CreateNew); using FileStream fileStream = new(fullFileName, FileMode.CreateNew);
actualImage.Save(fileStream, System.Drawing.Imaging.ImageFormat.Png); actualImage.Save(fileStream, System.Drawing.Imaging.ImageFormat.Png);
_ = fileStream.Seek(0, SeekOrigin.Begin); _ = fileStream.Seek(0, SeekOrigin.Begin);
actualByte = fileStream.ReadByte(); actualByte = fileStream.ReadByte();

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Compare</PackageId> <PackageId>Phares.View.by.Distance.Compare</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -33,14 +33,14 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.10" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" /> <PackageReference Include="Microsoft.Extensions.Options" Version="9.0.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" /> <PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Map\Map.csproj" /> <ProjectReference Include="..\Map\Map.csproj" />

View File

@ -4,13 +4,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<UserSecretsId>d862524f-2b48-4f47-b4c3-5a8615814ec2</UserSecretsId> <UserSecretsId>d862524f-2b48-4f47-b4c3-5a8615814ec2</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Copy.Distinct</PackageId> <PackageId>Phares.View.by.Distance.Copy.Distinct</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -35,9 +35,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -19,7 +19,7 @@ public class CopyDistinct
private readonly IsEnvironment _IsEnvironment; private readonly IsEnvironment _IsEnvironment;
private readonly IConfigurationRoot _ConfigurationRoot; private readonly IConfigurationRoot _ConfigurationRoot;
private readonly Property.Models.Configuration _PropertyConfiguration; private readonly Property.Models.Configuration _PropertyConfiguration;
private readonly ReadOnlyDictionary<string, ReadOnlyCollection<string>> _FileGroups; private readonly ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> _FileGroups;
public CopyDistinct(List<string> args, ILogger<Program> logger, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) public CopyDistinct(List<string> args, ILogger<Program> logger, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{ {

View File

@ -34,17 +34,15 @@ public class Configuration
} }
} }
private static Models.Configuration Get(Configuration? configuration) private static Models.Configuration Get(Configuration? configuration, Property.Models.Configuration propertyConfiguration)
{ {
Models.Configuration result; Models.Configuration result;
if (configuration is null) throw new NullReferenceException(nameof(configuration)); if (configuration is null) throw new NullReferenceException(nameof(configuration));
if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat)); if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat));
if (configuration.PropertyConfiguration is null) throw new NullReferenceException(nameof(configuration.PropertyConfiguration)); result = new(propertyConfiguration,
result = new( configuration.IgnoreExtensions,
configuration.IgnoreExtensions, configuration.PersonBirthdayFormat);
configuration.PersonBirthdayFormat,
configuration.PropertyConfiguration);
return result; return result;
} }
@ -66,7 +64,7 @@ public class Configuration
#pragma warning restore IL3050, IL2026 #pragma warning restore IL3050, IL2026
} }
PreVerify(configurationRoot, configuration); PreVerify(configurationRoot, configuration);
result = Get(configuration); result = Get(configuration, propertyConfiguration);
return result; return result;
} }

View File

@ -13,10 +13,9 @@ public class Configuration
public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration; public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration;
[JsonConstructor] [JsonConstructor]
public Configuration( public Configuration(Property.Models.Configuration propertyConfiguration,
string[] ignoreExtensions, string[] ignoreExtensions,
string personBirthdayFormat, string personBirthdayFormat)
Property.Models.Configuration propertyConfiguration)
{ {
IgnoreExtensions = ignoreExtensions; IgnoreExtensions = ignoreExtensions;
PersonBirthdayFormat = personBirthdayFormat; PersonBirthdayFormat = personBirthdayFormat;

View File

@ -4,13 +4,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<UserSecretsId>8004d966-1a9e-4545-a220-83f32b6a13e9</UserSecretsId> <UserSecretsId>8004d966-1a9e-4545-a220-83f32b6a13e9</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Date.Group</PackageId> <PackageId>Phares.View.by.Distance.Date.Group</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -34,15 +34,15 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.10" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" /> <PackageReference Include="Microsoft.Extensions.Options" Version="9.0.2" />
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" /> <PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -251,11 +251,11 @@ public class DateGroup
if (topDirectoryName.Length > 1) if (topDirectoryName.Length > 1)
_ = destinationDirectoryName.Append(topDirectoryName); _ = destinationDirectoryName.Append(topDirectoryName);
if (_Configuration.BySeason) if (_Configuration.BySeason)
directoryNames.AddRange(new string[] { $"{destinationDirectoryName} {year} {seasonName}" }); directoryNames.AddRange([$"{destinationDirectoryName} {year} {seasonName}"]);
else if (_Configuration.ByDay) else if (_Configuration.ByDay)
directoryNames.AddRange(new string[] { $"{destinationDirectoryName} {year}", $"{weekOfYear}) {year}-{day}" }); directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year}-{day}"]);
else if (_Configuration.ByWeek) else if (_Configuration.ByWeek)
directoryNames.AddRange(new string[] { $"{destinationDirectoryName} {year}", $"{weekOfYear}) {year} {month}" }); directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year} {month}"]);
else else
throw new Exception(); throw new Exception();
} }

View File

@ -4,13 +4,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<UserSecretsId>0589ecff-b296-48be-a3f7-7bf27f453975</UserSecretsId> <UserSecretsId>0589ecff-b296-48be-a3f7-7bf27f453975</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Delete.By.Distinct</PackageId> <PackageId>Phares.View.by.Distance.Delete.By.Distinct</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -34,14 +34,14 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.10" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" /> <PackageReference Include="Microsoft.Extensions.Options" Version="9.0.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" /> <PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -4,13 +4,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<UserSecretsId>ead2e5ee-5f40-4151-bdb6-31d630d94f28</UserSecretsId> <UserSecretsId>ead2e5ee-5f40-4151-bdb6-31d630d94f28</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Delete.By.Relative</PackageId> <PackageId>Phares.View.by.Distance.Delete.By.Relative</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -34,14 +34,14 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.10" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" /> <PackageReference Include="Microsoft.Extensions.Options" Version="9.0.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" /> <PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Distance</PackageId> <PackageId>Phares.View.by.Distance.Distance</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -36,7 +36,7 @@
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" /> <ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />

View File

@ -21,7 +21,7 @@ public class DistanceLimits : IDistanceLimits
int faceDistancePermyriad, int faceDistancePermyriad,
int[] rangeDaysDeltaTolerance, int[] rangeDaysDeltaTolerance,
float[] rangeDistanceTolerance, float[] rangeDistanceTolerance,
float[] rangeFaceAreaPermyriadTolerance, float[] rangeFaceAreaTolerance,
float[] rangeFaceConfidence, float[] rangeFaceConfidence,
int sortingMaximumPerFaceShouldBeHigh, int sortingMaximumPerFaceShouldBeHigh,
int? useFiltersCounter = null) int? useFiltersCounter = null)
@ -33,7 +33,7 @@ public class DistanceLimits : IDistanceLimits
{ {
RangeDaysDeltaTolerance = rangeDaysDeltaTolerance[1]; RangeDaysDeltaTolerance = rangeDaysDeltaTolerance[1];
FaceConfidencePercent = faceConfidencePercent * rangeFaceConfidence[1]; FaceConfidencePercent = faceConfidencePercent * rangeFaceConfidence[1];
FaceAreaPermyriad = faceAreaPermyriad * rangeFaceAreaPermyriadTolerance[1]; FaceAreaPermyriad = faceAreaPermyriad * rangeFaceAreaTolerance[1];
FaceDistancePermyriad = faceDistancePermyriad * rangeDistanceTolerance[1]; FaceDistancePermyriad = faceDistancePermyriad * rangeDistanceTolerance[1];
} }
else else
@ -41,7 +41,7 @@ public class DistanceLimits : IDistanceLimits
RangeDaysDeltaTolerance = ((rangeDaysDeltaTolerance[2] - rangeDaysDeltaTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeDaysDeltaTolerance[1]; RangeDaysDeltaTolerance = ((rangeDaysDeltaTolerance[2] - rangeDaysDeltaTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeDaysDeltaTolerance[1];
FaceConfidencePercent = faceConfidencePercent * ((rangeFaceConfidence[2] - rangeFaceConfidence[0]) * 0.01 * useFiltersCounter.Value) + rangeFaceConfidence[1]; FaceConfidencePercent = faceConfidencePercent * ((rangeFaceConfidence[2] - rangeFaceConfidence[0]) * 0.01 * useFiltersCounter.Value) + rangeFaceConfidence[1];
FaceDistancePermyriad = faceDistancePermyriad * ((rangeDistanceTolerance[2] - rangeDistanceTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeDistanceTolerance[1]; FaceDistancePermyriad = faceDistancePermyriad * ((rangeDistanceTolerance[2] - rangeDistanceTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeDistanceTolerance[1];
FaceAreaPermyriad = faceAreaPermyriad * ((rangeFaceAreaPermyriadTolerance[2] - rangeFaceAreaPermyriadTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeFaceAreaPermyriadTolerance[1]; FaceAreaPermyriad = faceAreaPermyriad * ((rangeFaceAreaTolerance[2] - rangeFaceAreaTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeFaceAreaTolerance[1];
} }
} }

View File

@ -358,7 +358,7 @@ public partial class E_Distance : IDistance
} }
results.Add(keyValuePair.Key, new(keyValuePairs)); results.Add(keyValuePair.Key, new(keyValuePairs));
} }
return new(results); return results.AsReadOnly();
} }
public static List<LocationContainer> GetPreFilterLocationContainer(int maxDegreeOfParallelism, Configuration configuration, string focusDirectory, string focusModel, int? skipPersonWithMoreThen, long ticks, MapLogic mapLogic, long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mapped, List<LocationContainer> available) public static List<LocationContainer> GetPreFilterLocationContainer(int maxDegreeOfParallelism, Configuration configuration, string focusDirectory, string focusModel, int? skipPersonWithMoreThen, long ticks, MapLogic mapLogic, long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mapped, List<LocationContainer> available)
@ -509,7 +509,7 @@ public partial class E_Distance : IDistance
faceDistanceContainer = new(face, faceDistance); faceDistanceContainer = new(face, faceDistance);
collection.Add(faceDistanceContainer); collection.Add(faceDistanceContainer);
} }
results = new(collection.ToArray()); results = collection.AsReadOnly();
return results; return results;
} }
@ -568,7 +568,7 @@ public partial class E_Distance : IDistance
foreach (KeyValuePair<int, LocationContainer> keyValue in keyValuePair.Value) foreach (KeyValuePair<int, LocationContainer> keyValue in keyValuePair.Value)
results.Add(keyValue.Value); results.Add(keyValue.Value);
} }
return new(results); return results.AsReadOnly();
} }
public static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(IDlibDotNet dlibDotNet, Configuration mapConfiguration, long ticks, MapLogic mapLogic, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedWithEncoding, List<LocationContainer> preFiltered, DistanceLimits distanceLimits, List<LocationContainer> postFiltered) public static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(IDlibDotNet dlibDotNet, Configuration mapConfiguration, long ticks, MapLogic mapLogic, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedWithEncoding, List<LocationContainer> preFiltered, DistanceLimits distanceLimits, List<LocationContainer> postFiltered)
@ -624,7 +624,7 @@ public partial class E_Distance : IDistance
results = ISortingContainer.Sort(results); results = ISortingContainer.Sort(results);
else else
results = ISortingContainer.SortUsingDaysDelta(results); results = ISortingContainer.SortUsingDaysDelta(results);
return new(results); return results.AsReadOnly();
} }
private static ReadOnlyCollection<RelationContainer> GetRelationCollections(IDistanceLimits distanceLimits, int faceDistancePermyriad, int locationContainerDistanceTake, float distanceTolerance, List<Record> records) private static ReadOnlyCollection<RelationContainer> GetRelationCollections(IDistanceLimits distanceLimits, int faceDistancePermyriad, int locationContainerDistanceTake, float distanceTolerance, List<Record> records)
@ -672,7 +672,7 @@ public partial class E_Distance : IDistance
mappedRelations = (from l in mappedRelations orderby l.DistancePermyriad select l).Take(locationContainerDistanceTake).ToList(); mappedRelations = (from l in mappedRelations orderby l.DistancePermyriad select l).Take(locationContainerDistanceTake).ToList();
results.Add(new(fileHolder, new(mappedRelations))); results.Add(new(fileHolder, new(mappedRelations)));
} }
return new(results); return results.AsReadOnly();
} }
ReadOnlyCollection<RelationContainer> IDistance.GetRelationContainers(IDistanceLimits distanceLimits, int faceDistancePermyriad, int locationContainerDistanceTake, float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer> locationContainers) ReadOnlyCollection<RelationContainer> IDistance.GetRelationContainers(IDistanceLimits distanceLimits, int faceDistancePermyriad, int locationContainerDistanceTake, float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer> locationContainers)

View File

@ -4,7 +4,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0-windows</TargetFramework> <TargetFramework>net9.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
@ -26,9 +26,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -6,10 +6,8 @@ public class Program
/// The main entry point for the application. /// The main entry point for the application.
/// </summary> /// </summary>
[STAThread] [STAThread]
private static void Main() private static void Main() =>
{ // ApplicationConfiguration.Initialize();
ApplicationConfiguration.Initialize();
Application.Run(new DragDropExplorer()); Application.Run(new DragDropExplorer());
}
} }

View File

@ -4,7 +4,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0-windows</TargetFramework> <TargetFramework>net9.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
@ -26,9 +26,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -6,10 +6,8 @@ public class Program
/// The main entry point for the application. /// The main entry point for the application.
/// </summary> /// </summary>
[STAThread] [STAThread]
private static void Main() private static void Main() =>
{ // ApplicationConfiguration.Initialize();
ApplicationConfiguration.Initialize();
Application.Run(new DragDropMove()); Application.Run(new DragDropMove());
}
} }

View File

@ -4,7 +4,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0-windows</TargetFramework> <TargetFramework>net9.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<UserSecretsId>7b153e3d-672b-4f7a-888a-cb31645a2439</UserSecretsId> <UserSecretsId>7b153e3d-672b-4f7a-888a-cb31645a2439</UserSecretsId>
</PropertyGroup> </PropertyGroup>
@ -27,9 +27,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" /> <ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />

View File

@ -8,11 +8,9 @@ public class Program
/// The main entry point for the application. /// The main entry point for the application.
/// </summary> /// </summary>
[STAThread] [STAThread]
private static void Main() private static void Main() =>
{ // 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 container)
{ {

View File

@ -4,7 +4,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0-windows</TargetFramework> <TargetFramework>net9.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<UserSecretsId>c64a15ed-0ba3-4378-8f80-0c19d0531747</UserSecretsId> <UserSecretsId>c64a15ed-0ba3-4378-8f80-0c19d0531747</UserSecretsId>
</PropertyGroup> </PropertyGroup>
@ -27,9 +27,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Metadata\Metadata.csproj" /> <ProjectReference Include="..\Metadata\Metadata.csproj" />

View File

@ -6,10 +6,8 @@ public class Program
/// The main entry point for the application. /// The main entry point for the application.
/// </summary> /// </summary>
[STAThread] [STAThread]
private static void Main() private static void Main() =>
{ // ApplicationConfiguration.Initialize();
ApplicationConfiguration.Initialize();
Application.Run(new DragDropSetPropertyItem()); Application.Run(new DragDropSetPropertyItem());
}
} }

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Duplicate-Search</PackageId> <PackageId>Phares.View.by.Distance.Duplicate-Search</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -33,14 +33,14 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.10" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" /> <PackageReference Include="Microsoft.Extensions.Options" Version="9.0.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" /> <PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -189,7 +189,7 @@ public class DuplicateSearch
if (mappingFromItem is not null) if (mappingFromItem is not null)
{ {
resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}")); resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}"));
collection[0] = new(mappingFromItem.ContainerDateTimes, item.Property.DateTimeDigitized, item.Property.DateTimeOriginal, mappingFromItem.Id, mappingFromItem.FilePath, mappingFromItem.IsWrongYear, item.Property.Keywords ?? [], mappingFromItem.MinimumDateTime, item.Property.Model, mappingFromItem.RelativePath, resizedFileHolder); collection[0] = new(mappingFromItem.ContainerDateTimes, item.Property.DateTimeDigitized, item.Property.DateTimeOriginal, mappingFromItem.Id, mappingFromItem.IsArchive, mappingFromItem.FilePath, mappingFromItem.IsWrongYear, item.Property.Keywords ?? [], mappingFromItem.MinimumDateTime, item.Property.Model, mappingFromItem.RelativePath, resizedFileHolder);
} }
} }
resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath)); resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath));

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Face</PackageId> <PackageId>Phares.View.by.Distance.Face</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -33,7 +33,7 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" /> <ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />

View File

@ -46,7 +46,8 @@ public class D_Face : IFaceD
private readonly EncoderParameters _HiddenEncoderParameters; private readonly EncoderParameters _HiddenEncoderParameters;
private readonly IPropertyConfiguration _PropertyConfiguration; private readonly IPropertyConfiguration _PropertyConfiguration;
private readonly JsonSerializerOptions _WriteIndentedAndWhenWritingNull; private readonly JsonSerializerOptions _WriteIndentedAndWhenWritingNull;
private readonly Dictionary<string, ReadOnlyCollection<string>> _FileGroups; private readonly ReadOnlyDictionary<byte, ReadOnlyCollection<string>>[] _ResultContentFileGroups;
private readonly ReadOnlyDictionary<byte, ReadOnlyCollection<string>>[] _ResultCollectionFileGroups;
public D_Face( public D_Face(
string argZero, string argZero,
@ -69,7 +70,6 @@ public class D_Face : IFaceD
float[] rectangleIntersectMinimums) float[] rectangleIntersectMinimums)
{ {
_ArgZero = argZero; _ArgZero = argZero;
_FileGroups = [];
_ImageCodecInfo = imageCodecInfo; _ImageCodecInfo = imageCodecInfo;
_EncoderParameters = encoderParameters; _EncoderParameters = encoderParameters;
_FileNameExtension = filenameExtension; _FileNameExtension = filenameExtension;
@ -84,6 +84,8 @@ public class D_Face : IFaceD
_RectangleIntersectMinimum = rectangleIntersectMinimums.Min(); _RectangleIntersectMinimum = rectangleIntersectMinimums.Min();
_FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor; _FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor;
_ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime; _ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime;
_ResultContentFileGroups = [new(new Dictionary<byte, ReadOnlyCollection<string>>())];
_ResultCollectionFileGroups = [new(new Dictionary<byte, ReadOnlyCollection<string>>())];
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(modelDirectory, modelName, predictorModelName); (Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(modelDirectory, modelName, predictorModelName);
_Model = model; _Model = model;
_PredictorModel = predictorModel; _PredictorModel = predictorModel;
@ -101,10 +103,16 @@ public class D_Face : IFaceD
public void Update(string dResultsFullGroupDirectory) public void Update(string dResultsFullGroupDirectory)
{ {
_FileGroups.Clear(); ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, dResultsFullGroupDirectory, [_PropertyConfiguration.ResultCollection, _PropertyConfiguration.ResultContent]);
ReadOnlyDictionary<string, ReadOnlyCollection<string>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, dResultsFullGroupDirectory, [_PropertyConfiguration.ResultCollection, _PropertyConfiguration.ResultContent]); foreach (KeyValuePair<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePair in keyValuePairs)
foreach (KeyValuePair<string, ReadOnlyCollection<string>> keyValuePair in keyValuePairs) {
_FileGroups.Add(keyValuePair.Key, keyValuePair.Value); if (keyValuePair.Key == _PropertyConfiguration.ResultContent)
_ResultContentFileGroups[0] = keyValuePair.Value;
else if (keyValuePair.Key == _PropertyConfiguration.ResultCollection)
_ResultCollectionFileGroups[0] = keyValuePair.Value;
else
throw new Exception();
}
} }
private static (Model model, PredictorModel predictorModel, ModelParameter modelParameter) GetModel(string modelDirectory, string modelName, string predictorModelName) private static (Model model, PredictorModel predictorModel, ModelParameter modelParameter) GetModel(string modelDirectory, string modelName, string predictorModelName)
@ -112,8 +120,8 @@ public class D_Face : IFaceD
(Model, PredictorModel, ModelParameter) result; (Model, PredictorModel, ModelParameter) result;
Array array; Array array;
Model? model = null; Model? model = null;
array = Enum.GetValues<Model>();
PredictorModel? predictorModel = null; PredictorModel? predictorModel = null;
array = Enum.GetValues(typeof(Model));
foreach (Model check in array) foreach (Model check in array)
{ {
if (modelName.Contains(check.ToString())) if (modelName.Contains(check.ToString()))
@ -125,7 +133,7 @@ public class D_Face : IFaceD
if (model is null) if (model is null)
throw new Exception("Destination directory must have Model name!"); throw new Exception("Destination directory must have Model name!");
model = model.Value; model = model.Value;
array = Enum.GetValues(typeof(PredictorModel)); array = Enum.GetValues<PredictorModel>();
foreach (PredictorModel check in array) foreach (PredictorModel check in array)
{ {
if (predictorModelName.Contains(check.ToString())) if (predictorModelName.Contains(check.ToString()))
@ -295,6 +303,25 @@ public class D_Face : IFaceD
#pragma warning restore CA1416 #pragma warning restore CA1416
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
{
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, fileInfo.FullName);
fileInfo.Refresh();
}
}
}
public List<Shared.Models.Face> GetFaces(string outputResolution, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection) public List<Shared.Models.Face> GetFaces(string outputResolution, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
{ {
List<Shared.Models.Face>? results; List<Shared.Models.Face>? results;
@ -302,8 +329,11 @@ public class D_Face : IFaceD
List<Location> locations; List<Location> locations;
string[] changesFrom = [nameof(A_Property), nameof(B_Metadata), nameof(C_Resize)]; string[] changesFrom = [nameof(A_Property), nameof(B_Metadata), nameof(C_Resize)];
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
(_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); string fileName = $"{mappingFromItem.FilePath.NameWithoutExtension}{mappingFromItem.FilePath.ExtensionLowered}.json";
FileInfo fileInfo = new(Path.Combine(_FileGroups[_PropertyConfiguration.ResultCollection][directoryIndex], $"{mappingFromItem.FilePath.NameWithoutExtension}{mappingFromItem.FilePath.ExtensionLowered}.json")); CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
string directory = _ResultCollectionFileGroups[0][cei.Enum][cei.Index];
FileInfo fileInfo = new(Path.Combine(directory, fileName));
MoveIf(fileName, cei, directory, fileInfo);
if (_ForceFaceLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) if (_ForceFaceLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
{ {
File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName);
@ -366,6 +396,25 @@ public class D_Face : IFaceD
return results; return results;
} }
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, DirectoryInfo directoryInfo)
{
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 (Directory.Exists(checkFile))
{
Directory.Move(checkFile, directoryInfo.FullName);
directoryInfo.Refresh();
}
}
}
public List<(Shared.Models.Face, FileHolder?, string, bool)> SaveFaces(FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces) public List<(Shared.Models.Face, FileHolder?, string, bool)> SaveFaces(FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces)
{ {
List<(Shared.Models.Face, FileHolder?, string, bool Save)> results = []; List<(Shared.Models.Face, FileHolder?, string, bool Save)> results = [];
@ -373,11 +422,13 @@ public class D_Face : IFaceD
FileInfo fileInfo; FileInfo fileInfo;
FileHolder fileHolder; FileHolder fileHolder;
string deterministicHashCodeKey; string deterministicHashCodeKey;
string fileName = mappingFromItem.FilePath.NameWithoutExtension;
string[] changesFrom = [nameof(A_Property), nameof(B_Metadata), nameof(C_Resize)]; string[] changesFrom = [nameof(A_Property), nameof(B_Metadata), nameof(C_Resize)];
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
(_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
string directory = Path.Combine(_FileGroups[_PropertyConfiguration.ResultContent][directoryIndex], mappingFromItem.FilePath.NameWithoutExtension); string directory = _ResultContentFileGroups[0][cei.Enum][cei.Index];
bool directoryExists = Directory.Exists(directory); DirectoryInfo directoryInfo = new(Path.Combine(directory, fileName));
MoveIf(fileName, cei, directory, directoryInfo);
foreach (Shared.Models.Face face in faces) foreach (Shared.Models.Face face in faces)
{ {
save = false; save = false;
@ -387,9 +438,9 @@ public class D_Face : IFaceD
continue; continue;
} }
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(filePath, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(filePath, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
fileInfo = new FileInfo(Path.Combine(directory, $"{deterministicHashCodeKey}{mappingFromItem.FilePath.ExtensionLowered}{_FileNameExtension}")); fileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, $"{deterministicHashCodeKey}{mappingFromItem.FilePath.ExtensionLowered}{_FileNameExtension}"));
fileHolder = FileHolder.Get(fileInfo); fileHolder = FileHolder.Get(fileInfo);
if (!directoryExists) if (!directoryInfo.Exists)
save = true; save = true;
else if (_OverrideForFaceImages) else if (_OverrideForFaceImages)
save = true; save = true;
@ -397,12 +448,12 @@ public class D_Face : IFaceD
save = true; save = true;
else if (_CheckDFaceAndUpWriteDates && dateTimes.Count > 0 && dateTimes.Max() > fileInfo.LastWriteTime) else if (_CheckDFaceAndUpWriteDates && dateTimes.Count > 0 && dateTimes.Max() > fileInfo.LastWriteTime)
save = true; save = true;
results.Add(new(face, fileHolder, Path.Combine(directory, $"{deterministicHashCodeKey}{mappingFromItem.FilePath.ExtensionLowered}{_HiddenFileNameExtension}"), save)); results.Add(new(face, fileHolder, Path.Combine(directoryInfo.FullName, $"{deterministicHashCodeKey}{mappingFromItem.FilePath.ExtensionLowered}{_HiddenFileNameExtension}"), save));
} }
if (results.Any(l => l.Save)) if (results.Any(l => l.Save))
{ {
if (!directoryExists) if (!directoryInfo.Exists)
_ = Directory.CreateDirectory(directory); _ = Directory.CreateDirectory(directoryInfo.FullName);
SaveFaces(mappingFromItem.ResizedFileHolder, exifDirectory, results); SaveFaces(mappingFromItem.ResizedFileHolder, exifDirectory, results);
} }
return results; return results;

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.FaceParts</PackageId> <PackageId>Phares.View.by.Distance.FaceParts</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -33,7 +33,7 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" /> <ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />

View File

@ -32,17 +32,17 @@ public class D2_FaceParts
private readonly bool _OverrideForFaceLandmarkImages; private readonly bool _OverrideForFaceLandmarkImages;
private readonly EncoderParameters _EncoderParameters; private readonly EncoderParameters _EncoderParameters;
private readonly IPropertyConfiguration _PropertyConfiguration; private readonly IPropertyConfiguration _PropertyConfiguration;
private readonly Dictionary<string, ReadOnlyCollection<string>> _FileGroups; private readonly ReadOnlyDictionary<byte, ReadOnlyCollection<string>>[] _ResultContentFileGroups;
public D2_FaceParts(IPropertyConfiguration propertyConfiguration, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension, bool checkDFaceAndUpWriteDates, bool overrideForFaceLandmarkImages) public D2_FaceParts(IPropertyConfiguration propertyConfiguration, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension, bool checkDFaceAndUpWriteDates, bool overrideForFaceLandmarkImages)
{ {
_FileGroups = [];
_ImageCodecInfo = imageCodecInfo; _ImageCodecInfo = imageCodecInfo;
_EncoderParameters = encoderParameters; _EncoderParameters = encoderParameters;
_FileNameExtension = filenameExtension; _FileNameExtension = filenameExtension;
_PropertyConfiguration = propertyConfiguration; _PropertyConfiguration = propertyConfiguration;
_CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates; _CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates;
_OverrideForFaceLandmarkImages = overrideForFaceLandmarkImages; _OverrideForFaceLandmarkImages = overrideForFaceLandmarkImages;
_ResultContentFileGroups = [new(new Dictionary<byte, ReadOnlyCollection<string>>())];
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, [], null) ?? throw new Exception(); ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, [], null) ?? throw new Exception();
_ConstructorInfo = constructorInfo; _ConstructorInfo = constructorInfo;
} }
@ -55,10 +55,14 @@ public class D2_FaceParts
public void Update(string dResultsFullGroupDirectory) public void Update(string dResultsFullGroupDirectory)
{ {
_FileGroups.Clear(); ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, dResultsFullGroupDirectory, [_PropertyConfiguration.ResultContent]);
ReadOnlyDictionary<string, ReadOnlyCollection<string>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, dResultsFullGroupDirectory, [_PropertyConfiguration.ResultContent]); foreach (KeyValuePair<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePair in keyValuePairs)
foreach (KeyValuePair<string, ReadOnlyCollection<string>> keyValuePair in keyValuePairs) {
_FileGroups.Add(keyValuePair.Key, keyValuePair.Value); if (keyValuePair.Key == _PropertyConfiguration.ResultContent)
_ResultContentFileGroups[0] = keyValuePair.Value;
else
throw new Exception();
}
} }
private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum) private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum)
@ -380,6 +384,25 @@ public class D2_FaceParts
#pragma warning restore CA1416 #pragma warning restore CA1416
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, DirectoryInfo directoryInfo)
{
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 (Directory.Exists(checkFile))
{
Directory.Move(checkFile, directoryInfo.FullName);
directoryInfo.Refresh();
}
}
}
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(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;
@ -390,11 +413,13 @@ public class D2_FaceParts
string deterministicHashCodeKey; string deterministicHashCodeKey;
bool updateDateWhenMatches = false; bool updateDateWhenMatches = false;
List<(Shared.Models.Face, string, string)> collection = []; List<(Shared.Models.Face, string, string)> collection = [];
string fileName = mappingFromItem.FilePath.NameWithoutExtension;
string[] changesFrom = [nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face)]; string[] changesFrom = [nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face)];
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
(_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
string directory = Path.Combine(_FileGroups[_PropertyConfiguration.ResultContent][directoryIndex], mappingFromItem.FilePath.NameWithoutExtension); string directory = _ResultContentFileGroups[0][cei.Enum][cei.Index];
bool directoryExists = Directory.Exists(directory); DirectoryInfo directoryInfo = new(Path.Combine(directory, mappingFromItem.FilePath.NameWithoutExtension));
MoveIf(fileName, cei, directory, directoryInfo);
foreach (Shared.Models.Face face in faces) foreach (Shared.Models.Face face in faces)
{ {
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
@ -403,14 +428,14 @@ public class D2_FaceParts
continue; continue;
} }
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(filePath, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(filePath, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
fileInfo = new FileInfo(Path.Combine(directory, $"{deterministicHashCodeKey}{mappingFromItem.FilePath.ExtensionLowered}{_FileNameExtension}")); fileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, $"{deterministicHashCodeKey}{mappingFromItem.FilePath.ExtensionLowered}{_FileNameExtension}"));
if (string.IsNullOrEmpty(fileInfo.DirectoryName)) if (string.IsNullOrEmpty(fileInfo.DirectoryName))
continue; continue;
rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKey} - R{mappingFromItem.FilePath.ExtensionLowered}{_FileNameExtension}")); rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKey} - R{mappingFromItem.FilePath.ExtensionLowered}{_FileNameExtension}"));
collection.Add(new(face, fileInfo.FullName, rotatedFileInfo.FullName)); collection.Add(new(face, fileInfo.FullName, rotatedFileInfo.FullName));
if (check) if (check)
continue; continue;
else if (!directoryExists) else if (!directoryInfo.Exists)
check = true; check = true;
else if (_OverrideForFaceLandmarkImages) else if (_OverrideForFaceLandmarkImages)
check = true; check = true;
@ -428,8 +453,8 @@ public class D2_FaceParts
} }
if (check) if (check)
{ {
if (!directoryExists) if (!directoryInfo.Exists)
_ = Directory.CreateDirectory(directory); _ = Directory.CreateDirectory(directoryInfo.FullName);
SaveFaceParts(mappingFromItem, exifDirectory, collection); SaveFaceParts(mappingFromItem, exifDirectory, collection);
if (saveRotated) if (saveRotated)
SaveRotated(mappingFromItem, collection); SaveRotated(mappingFromItem, collection);

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.FaceRecognitionDotNet</PackageId> <PackageId>Phares.View.by.Distance.FaceRecognitionDotNet</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>

View File

@ -113,11 +113,11 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetJpegLowQuality(); (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetJpegLowQuality();
_FaceParts = new D2_FaceParts(_Configuration.PropertyConfiguration, imageCodecInfo, encoderParameters, filenameExtension, configuration.CheckDFaceAndUpWriteDates, configuration.OverrideForFaceLandmarkImages); _FaceParts = new D2_FaceParts(_Configuration.PropertyConfiguration, imageCodecInfo, encoderParameters, filenameExtension, configuration.CheckDFaceAndUpWriteDates, configuration.OverrideForFaceLandmarkImages);
} }
_DistanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaPermyriadTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh); _DistanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh);
_MapConfiguration = Get(configuration, _DistanceLimits, _Faces.FileNameExtension, _Faces.HiddenFileNameExtension, _FaceParts.FileNameExtension); _MapConfiguration = Get(configuration, _DistanceLimits, _Faces.FileNameExtension, _Faces.HiddenFileNameExtension, _FaceParts.FileNameExtension);
_Distance = new(configuration.DistanceMoveUnableToMatch, configuration.DistanceRenameToMatch, configuration.FaceConfidencePercent, configuration.RangeDistanceTolerance, configuration.RectangleIntersectMinimums); _Distance = new(configuration.DistanceMoveUnableToMatch, configuration.DistanceRenameToMatch, configuration.FaceConfidencePercent, configuration.RangeDistanceTolerance, configuration.RectangleIntersectMinimums);
if (_PropertyRootExistedBefore || !_ArgZeroIsConfigurationRootDirectory) if (_PropertyRootExistedBefore || !_ArgZeroIsConfigurationRootDirectory)
personContainers = new(new List<PersonContainer>()); personContainers = new([]);
else else
{ {
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
@ -183,8 +183,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
throw new NullReferenceException(nameof(configuration.RangeDaysDeltaTolerance)); throw new NullReferenceException(nameof(configuration.RangeDaysDeltaTolerance));
if (configuration.RangeDistanceTolerance.Length != 3) if (configuration.RangeDistanceTolerance.Length != 3)
throw new NullReferenceException(nameof(configuration.RangeDistanceTolerance)); throw new NullReferenceException(nameof(configuration.RangeDistanceTolerance));
if (configuration.RangeFaceAreaPermyriadTolerance.Length != 3) if (configuration.RangeFaceAreaTolerance.Length != 3)
throw new NullReferenceException(nameof(configuration.RangeFaceAreaPermyriadTolerance)); throw new NullReferenceException(nameof(configuration.RangeFaceAreaTolerance));
if (configuration.RangeFaceConfidence.Length != 3) if (configuration.RangeFaceConfidence.Length != 3)
throw new NullReferenceException(nameof(configuration.RangeFaceConfidence)); throw new NullReferenceException(nameof(configuration.RangeFaceConfidence));
if (configuration.LocationContainerDistanceTolerance is null && !string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory)) if (configuration.LocationContainerDistanceTolerance is null && !string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory))
@ -254,31 +254,6 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
throw new Exception("Configuration has SaveSortingWithoutPerson and FocusDirectory!"); throw new Exception("Configuration has SaveSortingWithoutPerson and FocusDirectory!");
} }
private ReadOnlyCollection<int> GetNotNineCollection(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{
List<int> results = [];
FileInfo fileInfo;
FileHolder fileHolder;
FilePath checkFilePath;
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{
foreach (FilePath filePath in filePaths)
{
if (!filePath.FullName.Contains(" !9"))
continue;
fileInfo = new(filePath.FullName);
fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(fileInfo);
if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden))
File.SetAttributes(fileHolder.FullName, FileAttributes.Hidden);
checkFilePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: null);
if (checkFilePath.Id is null)
continue;
results.Add(checkFilePath.Id.Value);
}
}
return new(results);
}
private static void DeleteContinueFiles(ReadOnlyCollection<PersonContainer> personContainers) private static void DeleteContinueFiles(ReadOnlyCollection<PersonContainer> personContainers)
{ {
foreach (PersonContainer personContainer in personContainers) foreach (PersonContainer personContainer in personContainers)
@ -337,9 +312,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
const string directorySearchFilter = "*"; const string directorySearchFilter = "*";
string? filesCollectionRootDirectory = null; string? filesCollectionRootDirectory = null;
bool configurationOutputResolutionsHas = false; bool configurationOutputResolutionsHas = false;
ReadOnlyCollection<Container> readOnlyContainers;
ReadOnlyCollection<int>? notNineCollection = null;
ReadOnlyDictionary<long, List<int>> personKeyToIds; ReadOnlyDictionary<long, List<int>> personKeyToIds;
ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers = 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) = GetResultsFullGroupDirectories();
@ -361,8 +335,7 @@ 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);
SaveDistinctIds(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, filePathsCollection); splatNineIdentifiers = GetSplatNineIdentifiersAndHideSplatNine(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, filePathsCollection);
notNineCollection = GetNotNineCollection(filePathsCollection);
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);
@ -396,7 +369,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
continue; continue;
(cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution); (cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution);
filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent); filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollectionRootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage: true); filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, directorySearchFilter, fileSearchFilter, filesCollectionRootDirectory, useCeilingAverage: true);
break; break;
} }
} }
@ -408,7 +381,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
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);
readOnlyContainers = Shared.Models.Stateless.Methods.IContainer.GetContainers(this, _Configuration.PropertyConfiguration, aPropertySingletonDirectory, filesCollectionRootDirectory, filePathsCollection); ReadOnlyCollection<Container> readOnlyContainers = Shared.Models.Stateless.Methods.IContainer.GetContainers(this, _Configuration.PropertyConfiguration, aPropertySingletonDirectory, filesCollectionRootDirectory, 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);
@ -455,8 +428,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
&& _Exceptions.Count == 0) && _Exceptions.Count == 0)
MapLogic(ticks, readOnlyContainers, fPhotoPrismContentDirectory, mapLogic, outputResolution, new(personKeyToIds), distinctValidImageFaces, distinctValidImageMappingCollection); MapLogic(ticks, readOnlyContainers, fPhotoPrismContentDirectory, mapLogic, outputResolution, new(personKeyToIds), distinctValidImageFaces, distinctValidImageMappingCollection);
if (runToDoCollectionFirst && _Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Count > 0 && distinctValidImageMappingCollection.Count > 0) if (runToDoCollectionFirst && _Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Count > 0 && splatNineIdentifiers is not null && distinctValidImageMappingCollection.Count > 0)
_Random.Random(_Configuration.PropertyConfiguration, _Configuration.ImmichAssetsFile, _Configuration.RadomUseBirthdayMinimum, _Configuration.ValidKeyWordsToIgnoreInRandom, personKeyToIds, notNineCollection, distinctValidImageMappingCollection); _Random.Random(_Configuration.PropertyConfiguration, _Configuration.ImmichAssetsFile, _Configuration.ImmichOwnerId, _Configuration.ImmichRoot, _Configuration.RadomUseBirthdayMinimum, _Configuration.ValidKeyWordsToIgnoreInRandom, personKeyToIds, splatNineIdentifiers, distinctValidImageMappingCollection);
if (_IsEnvironment.Development) if (_IsEnvironment.Development)
continue; continue;
if (!_IsEnvironment.Development) if (!_IsEnvironment.Development)
@ -498,8 +471,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
[ [
Path.Combine(rootDirectory, "Ancestry"), Path.Combine(rootDirectory, "Ancestry"),
Path.Combine(rootDirectory, "Facebook"), Path.Combine(rootDirectory, "Facebook"),
Path.Combine(rootDirectory, "LinkedIn"), Path.Combine(rootDirectory, "LinkedIn")
rootDirectory,
]; ];
foreach (string checkDirectory in checkDirectories) foreach (string checkDirectory in checkDirectories)
{ {
@ -570,7 +542,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
isValidImageFormatExtension = _Configuration.PropertyConfiguration.ValidImageFormatExtensions.Contains(extensionLowered); isValidImageFormatExtension = _Configuration.PropertyConfiguration.ValidImageFormatExtensions.Contains(extensionLowered);
fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(sourceDirectoryFile); fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(sourceDirectoryFile);
filePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: null); filePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: null);
_ = new Item(filePath, fileHolder, relativePath, isValidImageFormatExtension); _ = Item.Get(filePath, fileHolder, relativePath, isValidImageFormatExtension);
// container.Items.Add(item); // container.Items.Add(item);
} }
_Logger?.LogInformation(". . ."); _Logger?.LogInformation(". . .");
@ -664,57 +636,55 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
} }
private static ReadOnlyDictionary<int, List<FilePath>> GetKeyValuePairs(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) private static ReadOnlyDictionary<int, Identifier> GetSplatNineIdentifiersAndHideSplatNine(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
Dictionary<int, List<FilePath>> results = []; Dictionary<int, Identifier> results = [];
List<FilePath>? collection; ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>> keyValuePairs = FilePath.GetKeyValuePairs(filePathsCollection);
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{
if (filePaths.Count == 0)
continue;
foreach (FilePath filePath in filePaths)
{
if (filePath.Id is null)
continue;
if (!results.TryGetValue(filePath.Id.Value, out collection))
{
results.Add(filePath.Id.Value, []);
if (!results.TryGetValue(filePath.Id.Value, out collection))
throw new Exception();
}
collection.Add(filePath);
}
}
return new(results);
}
private static void SaveDistinctIds(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{
ReadOnlyDictionary<int, List<FilePath>> keyValuePairs = GetKeyValuePairs(filePathsCollection);
if (keyValuePairs.Count > 0) if (keyValuePairs.Count > 0)
{ {
string json;
string paddedId; string paddedId;
FileInfo fileInfo;
FilePath filePath; FilePath filePath;
FileHolder fileHolder;
Identifier identifier; Identifier identifier;
string[] directoryNames; string[] directoryNames;
List<int> distinct = [];
List<Identifier> identifiers = []; 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))
_ = Directory.CreateDirectory(bMetadataCollectionDirectory); _ = Directory.CreateDirectory(bMetadataCollectionDirectory);
foreach (KeyValuePair<int, List<FilePath>> keyValuePair in keyValuePairs) foreach (KeyValuePair<int, ReadOnlyCollection<FilePath>> keyValuePair in keyValuePairs)
{ {
filePath = keyValuePair.Value[0]; for (int i = 0; i < keyValuePair.Value.Count; i++)
if (filePath.Id is null) {
continue; filePath = keyValuePair.Value[0];
directoryNames = keyValuePair.Value.Select(l => l.DirectoryFullPath.Replace('\\', '/')).ToArray(); if (filePath.Id is null)
paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal, index: null); continue;
identifier = new(directoryNames, filePath.HasDateTimeOriginal, filePath.Id.Value, filePath.Length, paddedId, filePath.LastWriteTicks); directoryNames = keyValuePair.Value.Select(l => l.DirectoryFullPath.Replace('\\', '/')).ToArray();
identifiers.Add(identifier); paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal, index: null);
identifier = new(directoryNames, filePath.ExtensionLowered, filePath.HasDateTimeOriginal, filePath.Id.Value, filePath.Length, paddedId, filePath.LastWriteTicks);
if (i == 0)
identifiers.Add(identifier);
if (!filePath.FullName.Contains(" !9"))
continue;
fileInfo = new(filePath.FullName);
fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(fileInfo);
if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden))
File.SetAttributes(fileHolder.FullName, FileAttributes.Hidden);
if (distinct.Contains(keyValuePair.Key))
continue;
distinct.Add(keyValuePair.Key);
results.Add(keyValuePair.Key, identifier);
}
} }
string json = JsonSerializer.Serialize((from l in identifiers orderby l.DirectoryNames.Length descending, l.Id select l).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);
json = JsonSerializer.Serialize((from l in identifiers orderby l.DirectoryNames.Length descending, l.Id 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();
} }
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> readOnlyContainers, MapLogic mapLogic, bool distinctItems)
@ -771,7 +741,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
if (_Configuration.MoveToDecade && _Configuration.LocationContainerDistanceTolerance is null) if (_Configuration.MoveToDecade && _Configuration.LocationContainerDistanceTolerance is null)
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(eDistanceContentDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
return new(results); return results.AsReadOnly();
} }
private static void SavePropertyShortcutsForOutputResolutions(string eDistanceContentDirectory, ReadOnlyCollection<Item> distinctValidImageItems) private static void SavePropertyShortcutsForOutputResolutions(string eDistanceContentDirectory, ReadOnlyCollection<Item> distinctValidImageItems)
@ -880,7 +850,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
continue; continue;
results.Add(filePath); results.Add(filePath);
} }
return new(results); return results.AsReadOnly();
} }
public ReadOnlyDictionary<string, LocationContainer> GetOnlyOne(IDistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> matrix) public ReadOnlyDictionary<string, LocationContainer> GetOnlyOne(IDistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> matrix)
@ -908,7 +878,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
added.Add(locationContainer.LengthSource.Name); added.Add(locationContainer.LengthSource.Name);
results.Add(locationContainer.LengthSource.Name, locationContainer); results.Add(locationContainer.LengthSource.Name, locationContainer);
} }
return new(results); return results.AsReadOnly();
} }
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)
@ -932,7 +902,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
results = []; results = [];
else else
{ {
DistanceLimits distanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaPermyriadTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh); DistanceLimits distanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh);
List<LocationContainer> postFiltered = E_Distance.GetPostFilterLocationContainer(mapLogic, preFiltered, distanceLimits); List<LocationContainer> postFiltered = E_Distance.GetPostFilterLocationContainer(mapLogic, preFiltered, distanceLimits);
if (postFiltered.Count == 0) if (postFiltered.Count == 0)
results = []; results = [];
@ -947,7 +917,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
results = []; results = [];
else else
{ {
ReadOnlyDictionary<long, PersonContainer> personKeyToPersonContainer = mapLogic.GetPersonKeyToPersonContainer(); ReadOnlyDictionary<long, PersonContainer> personKeyToPersonContainer = PersonContainer.Extract(personContainers);
results = mapLogic.GetSaveContainers(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, distanceLimits, onlyOne, personKeyToPersonContainer); results = mapLogic.GetSaveContainers(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, distanceLimits, onlyOne, personKeyToPersonContainer);
} }
} }
@ -1054,7 +1024,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);
mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson);
} }
mapping = new(item.FilePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection); mapping = Mapping.Get(item.FilePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection);
notMapped += mapLogic.UpdateMappingFromPerson(wholePercentagesToPersonContainers, mapping); notMapped += mapLogic.UpdateMappingFromPerson(wholePercentagesToPersonContainers, mapping);
face.SetMapping(mapping); face.SetMapping(mapping);
} }
@ -1114,7 +1084,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
bool? canReMap = Map.Models.Stateless.Methods.IMapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); bool? canReMap = Map.Models.Stateless.Methods.IMapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);
bool? isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); bool? isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);
MappingFromFilterPost mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); MappingFromFilterPost mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson);
result = new(item.FilePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection: null); result = Mapping.Get(item.FilePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection: null);
int notMapped = mapLogic.UpdateMappingFromPerson(wholePercentagesToPersonContainers, result); int notMapped = mapLogic.UpdateMappingFromPerson(wholePercentagesToPersonContainers, result);
return (result, notMapped); return (result, notMapped);
} }
@ -1129,7 +1099,6 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
List<Tuple<string, DateTime>> sourceDirectoryChanges, List<Tuple<string, DateTime>> sourceDirectoryChanges,
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection, Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection,
Container container, Container container,
int index,
Item item, Item item,
DateTime[] containerDateTimes, DateTime[] containerDateTimes,
bool? isFocusRelativePath) bool? isFocusRelativePath)
@ -1312,7 +1281,6 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
sourceDirectoryChanges, sourceDirectoryChanges,
fileNameToCollection, fileNameToCollection,
container, container,
index: i,
filteredItems[i], filteredItems[i],
containerDateTimes, containerDateTimes,
isFocusRelativePath); isFocusRelativePath);
@ -1388,7 +1356,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
ReadOnlyCollection<SortingContainer> sortingContainers; ReadOnlyCollection<SortingContainer> sortingContainers;
FaceDistanceContainer[] filteredFaceDistanceContainers; FaceDistanceContainer[] filteredFaceDistanceContainers;
long? skipOlderThan = _Configuration.SkipOlderThanDays is null ? null : new DateTime(ticks).AddDays(-_Configuration.SkipOlderThanDays.Value).Ticks; long? skipOlderThan = _Configuration.SkipOlderThanDays is null ? null : new DateTime(ticks).AddDays(-_Configuration.SkipOlderThanDays.Value).Ticks;
distanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaPermyriadTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh); distanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh);
filteredFaceDistanceContainers = E_Distance.FilteredPostLoadFaceDistanceContainers(mapLogic, faceDistanceContainers, skipOlderThan, distanceLimits); filteredFaceDistanceContainers = E_Distance.FilteredPostLoadFaceDistanceContainers(mapLogic, faceDistanceContainers, skipOlderThan, distanceLimits);
if (filteredFaceDistanceContainers.Length == 0) if (filteredFaceDistanceContainers.Length == 0)
_Logger?.LogInformation("All images have been filtered!"); _Logger?.LogInformation("All images have been filtered!");
@ -1399,7 +1367,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
{ {
for (useFiltersCounter = 1; useFiltersCounter < _Configuration.UseFilterTries; useFiltersCounter++) for (useFiltersCounter = 1; useFiltersCounter < _Configuration.UseFilterTries; useFiltersCounter++)
{ {
distanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaPermyriadTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh, useFiltersCounter); distanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh, useFiltersCounter);
filteredFaceDistanceContainers = E_Distance.FilteredPostLoadFaceDistanceContainers(mapLogic, faceDistanceContainers, skipOlderThan, distanceLimits); filteredFaceDistanceContainers = E_Distance.FilteredPostLoadFaceDistanceContainers(mapLogic, faceDistanceContainers, skipOlderThan, distanceLimits);
if (filteredFaceDistanceContainers.Length == 0) if (filteredFaceDistanceContainers.Length == 0)
_Logger?.LogInformation("All images have been filtered!"); _Logger?.LogInformation("All images have been filtered!");
@ -1494,8 +1462,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
ProgressBar progressBar; ProgressBar progressBar;
string filesCollectionRootDirectory = _Configuration.PropertyConfiguration.RootDirectory; string filesCollectionRootDirectory = _Configuration.PropertyConfiguration.RootDirectory;
(string cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution); (string cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution);
IReadOnlyDictionary<string, 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, filesCollectionRootDirectory, directorySearchFilter, fileSearchFilter, 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();
bool filesCollectionCountIsOne = IsFilesCollectionCountIsOne(filePathsCollection); bool filesCollectionCountIsOne = IsFilesCollectionCountIsOne(filePathsCollection);
string message = $") Selecting for ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)"; string message = $") Selecting for ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";

View File

@ -4,13 +4,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<UserSecretsId>2999dda1-5329-4d9f-9d68-cccfabe0e47f</UserSecretsId> <UserSecretsId>2999dda1-5329-4d9f-9d68-cccfabe0e47f</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Instance</PackageId> <PackageId>Phares.View.by.Distance.Instance</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -34,12 +34,12 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.10" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" /> <PackageReference Include="Microsoft.Extensions.Options" Version="9.0.2" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" /> <PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />

View File

@ -27,6 +27,8 @@ public class Configuration
public bool? ForceResizeLastWriteTimeToCreationTime { get; set; } public bool? ForceResizeLastWriteTimeToCreationTime { get; set; }
public string? GenealogicalDataCommunicationFile { get; set; } public string? GenealogicalDataCommunicationFile { get; set; }
public string? ImmichAssetsFile { get; set; } public string? ImmichAssetsFile { get; set; }
public string? ImmichOwnerId { get; set; }
public string? ImmichRoot { get; set; }
public string[]? IgnoreExtensions { get; set; } public string[]? IgnoreExtensions { get; set; }
public string[]? JLinks { get; set; } public string[]? JLinks { get; set; }
public string? LinkedAlpha { get; set; } public string? LinkedAlpha { get; set; }
@ -147,6 +149,8 @@ public class Configuration
if (configuration?.ForceResizeLastWriteTimeToCreationTime is null) throw new NullReferenceException(nameof(configuration.ForceResizeLastWriteTimeToCreationTime)); if (configuration?.ForceResizeLastWriteTimeToCreationTime is null) throw new NullReferenceException(nameof(configuration.ForceResizeLastWriteTimeToCreationTime));
if (configuration?.GenealogicalDataCommunicationFile is null) throw new NullReferenceException(nameof(configuration.GenealogicalDataCommunicationFile)); if (configuration?.GenealogicalDataCommunicationFile is null) throw new NullReferenceException(nameof(configuration.GenealogicalDataCommunicationFile));
if (configuration?.ImmichAssetsFile is null) throw new NullReferenceException(nameof(configuration.ImmichAssetsFile)); if (configuration?.ImmichAssetsFile is null) throw new NullReferenceException(nameof(configuration.ImmichAssetsFile));
if (configuration?.ImmichOwnerId is null) throw new NullReferenceException(nameof(configuration.ImmichOwnerId));
if (configuration?.ImmichRoot is null) throw new NullReferenceException(nameof(configuration.ImmichRoot));
// if (configuration?.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); // if (configuration?.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
// if (configuration?.JLinks is null) throw new NullReferenceException(nameof(configuration.JLinks)); // if (configuration?.JLinks is null) throw new NullReferenceException(nameof(configuration.JLinks));
// if (configuration?.LinkedAlpha is null) throw new NullReferenceException(nameof(configuration.LinkedAlpha)); // if (configuration?.LinkedAlpha is null) throw new NullReferenceException(nameof(configuration.LinkedAlpha));
@ -239,6 +243,8 @@ public class Configuration
configuration.ForceResizeLastWriteTimeToCreationTime.Value, configuration.ForceResizeLastWriteTimeToCreationTime.Value,
configuration.GenealogicalDataCommunicationFile, configuration.GenealogicalDataCommunicationFile,
configuration.ImmichAssetsFile, configuration.ImmichAssetsFile,
configuration.ImmichOwnerId,
configuration.ImmichRoot,
configuration.IgnoreExtensions ?? [], configuration.IgnoreExtensions ?? [],
configuration.JLinks ?? [], configuration.JLinks ?? [],
configuration.LinkedAlpha, configuration.LinkedAlpha,

View File

@ -54,7 +54,7 @@ public class Place
results.Add(Get(place)); results.Add(Get(place));
} }
} }
return new(results); return results.AsReadOnly();
} }
} }

View File

@ -21,6 +21,8 @@ public record Configuration(Property.Models.Configuration PropertyConfiguration,
bool ForceResizeLastWriteTimeToCreationTime, bool ForceResizeLastWriteTimeToCreationTime,
string GenealogicalDataCommunicationFile, string GenealogicalDataCommunicationFile,
string ImmichAssetsFile, string ImmichAssetsFile,
string ImmichOwnerId,
string ImmichRoot,
string[] IgnoreExtensions, string[] IgnoreExtensions,
string[] JLinks, string[] JLinks,
string? LinkedAlpha, string? LinkedAlpha,
@ -62,7 +64,7 @@ public record Configuration(Property.Models.Configuration PropertyConfiguration,
int RadomUseBirthdayMinimum, int RadomUseBirthdayMinimum,
int[] RangeDaysDeltaTolerance, int[] RangeDaysDeltaTolerance,
float[] RangeDistanceTolerance, float[] RangeDistanceTolerance,
float[] RangeFaceAreaPermyriadTolerance, float[] RangeFaceAreaTolerance,
float[] RangeFaceConfidence, float[] RangeFaceConfidence,
float[] RectangleIntersectMinimums, float[] RectangleIntersectMinimums,
bool ReMap, bool ReMap,

View File

@ -1,32 +0,0 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Instance.Models;
internal sealed record Identifier(string[] DirectoryNames,
bool? HasDateTimeOriginal,
int Id,
long Length,
string PaddedId,
long Ticks)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, IdentifierSourceGenerationContext.Default.Identifier);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Identifier))]
internal partial class IdentifierSourceGenerationContext : JsonSerializerContext
{
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Identifier[]))]
internal partial class IdentifierCollectionSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -25,7 +25,7 @@ internal class F_Random
return result; return result;
} }
private static ReadOnlyDictionary<string, List<string>> GetDayToRelativePaths(ReadOnlyCollection<Mapping> distinctValidImageMappingCollection, string dateFormat, Dictionary<string, ImmichAsset> immichAssets, ReadOnlyDictionary<int, List<long>> idToPersonKeys) private static ReadOnlyDictionary<string, List<string>> GetDayToRelativePaths(ReadOnlyCollection<Mapping> distinctValidImageMappingCollection, string dateFormat, string immichOwnerId, string immichRoot, Dictionary<string, ImmichAsset> immichAssets, ReadOnlyDictionary<int, List<long>> idToPersonKeys)
{ {
Dictionary<string, List<string>> results = []; Dictionary<string, List<string>> results = [];
string key; string key;
@ -56,12 +56,14 @@ internal class F_Random
relativePaths.Add(mapping.MappingFromItem.RelativePath); relativePaths.Add(mapping.MappingFromItem.RelativePath);
else else
{ {
if (!immichAssets.TryGetValue(mapping.MappingFromItem.RelativePath, out immichAsset)) if (!immichAssets.TryGetValue($"{immichRoot}{mapping.MappingFromItem.RelativePath}", out immichAsset))
continue; continue;
relativePaths.Add(immichAsset.PreviewPath); if (!immichAsset.Path.Contains(immichOwnerId))
continue;
relativePaths.Add(immichAsset.Path.Split(immichOwnerId)[1]);
} }
} }
return new(results); return results.AsReadOnly();
} }
private static Dictionary<string, ImmichAsset> GetImmichAssets(string immichAssetsFile) private static Dictionary<string, ImmichAsset> GetImmichAssets(string immichAssetsFile)
@ -80,7 +82,7 @@ internal class F_Random
return results; return results;
} }
internal void Random(Property.Models.Configuration configuration, string immichAssetsFile, int radomUseBirthdayMinimum, string[] validKeyWordsToIgnoreInRandom, ReadOnlyDictionary<long, List<int>> personKeyToIds, ReadOnlyCollection<int>? notNineCollection, ReadOnlyCollection<Mapping> distinctValidImageMappingCollection) internal void Random(Property.Models.Configuration configuration, string immichAssetsFile, string immichOwnerId, string immichRoot, int radomUseBirthdayMinimum, string[] validKeyWordsToIgnoreInRandom, ReadOnlyDictionary<long, List<int>> personKeyToIds, ReadOnlyDictionary<int, Identifier> splatNineIdentifiers, ReadOnlyCollection<Mapping> distinctValidImageMappingCollection)
{ {
string key; string key;
string json; string json;
@ -93,8 +95,9 @@ internal class F_Random
List<int> distinctCollection = []; List<int> distinctCollection = [];
DateTime dateTime = new(2024, 1, 1); //Leap year DateTime dateTime = new(2024, 1, 1); //Leap year
Dictionary<string, ImmichAsset> immichAssets = GetImmichAssets(immichAssetsFile); Dictionary<string, ImmichAsset> immichAssets = GetImmichAssets(immichAssetsFile);
int[] splatNineIdentifiersKeys = splatNineIdentifiers.Select(l => l.Key).ToArray();
ReadOnlyDictionary<int, List<long>> idToPersonKeys = Map.Models.Stateless.Methods.IMapLogic.GetIdToPersonKeys(personKeyToIds); ReadOnlyDictionary<int, List<long>> idToPersonKeys = Map.Models.Stateless.Methods.IMapLogic.GetIdToPersonKeys(personKeyToIds);
ReadOnlyDictionary<string, List<string>> dayToRelativePaths = GetDayToRelativePaths(distinctValidImageMappingCollection, dateFormat, immichAssets, idToPersonKeys); ReadOnlyDictionary<string, List<string>> dayToRelativePaths = GetDayToRelativePaths(distinctValidImageMappingCollection, dateFormat, immichOwnerId, immichRoot, immichAssets, idToPersonKeys);
string fRandomCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(F_Random), "[]"); string fRandomCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(F_Random), "[]");
string[] files = Directory.GetFiles(fRandomCollectionDirectory, "*", SearchOption.TopDirectoryOnly); string[] files = Directory.GetFiles(fRandomCollectionDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files) foreach (string file in files)
@ -102,11 +105,13 @@ internal class F_Random
bool immichAssetsCountIsZero = immichAssets.Count == 0; bool immichAssetsCountIsZero = immichAssets.Count == 0;
foreach (Mapping mapping in distinctValidImageMappingCollection) foreach (Mapping mapping in distinctValidImageMappingCollection)
{ {
if (mapping.MappingFromItem.IsArchive is not null && mapping.MappingFromItem.IsArchive.Value)
continue;
if (distinctCollection.Contains(mapping.MappingFromItem.Id)) if (distinctCollection.Contains(mapping.MappingFromItem.Id))
continue; continue;
if (mapping.MappingFromItem.FilePath.DirectoryFullPath is null) if (mapping.MappingFromItem.FilePath.DirectoryFullPath is null)
continue; continue;
if (notNineCollection is not null && notNineCollection.Contains(mapping.MappingFromItem.Id)) if (!splatNineIdentifiersKeys.Contains(mapping.MappingFromItem.Id))
continue; continue;
if (mapping.MappingFromItem.Keywords is not null && mapping.MappingFromItem.Keywords.Any(l => validKeyWordsToIgnoreInRandom.Contains(l))) if (mapping.MappingFromItem.Keywords is not null && mapping.MappingFromItem.Keywords.Any(l => validKeyWordsToIgnoreInRandom.Contains(l)))
continue; continue;
@ -114,9 +119,11 @@ internal class F_Random
relativePaths.Add(mapping.MappingFromItem.RelativePath); relativePaths.Add(mapping.MappingFromItem.RelativePath);
else else
{ {
if (!immichAssets.TryGetValue(mapping.MappingFromItem.RelativePath, out immichAsset)) if (!immichAssets.TryGetValue($"{immichRoot}{mapping.MappingFromItem.RelativePath}", out immichAsset))
continue; continue;
relativePaths.Add(immichAsset.PreviewPath); if (!immichAsset.Path.Contains(immichOwnerId))
continue;
relativePaths.Add(immichAsset.Path.Split(immichOwnerId)[1]);
} }
distinctCollection.Add(mapping.MappingFromItem.Id); distinctCollection.Add(mapping.MappingFromItem.Id);
} }

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Map</PackageId> <PackageId>Phares.View.by.Distance.Map</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -37,7 +37,7 @@
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -264,7 +264,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
{ {
List<string> personKeyFormattedCollection = []; List<string> personKeyFormattedCollection = [];
Dictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted = []; Dictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted = [];
Stateless.MapLogic.SetPersonCollections(configuration, personContainers, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection); Stateless.MapLogic.SetPersonCollectionsAfterSetSkipCollections(configuration, personContainers, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection);
readOnlyPersonKeyFormattedCollection = new(personKeyFormattedCollection); readOnlyPersonKeyFormattedCollection = new(personKeyFormattedCollection);
readOnlyPersonKeyFormattedToNewestPersonKeyFormatted = new(personKeyFormattedToNewestPersonKeyFormatted); readOnlyPersonKeyFormattedToNewestPersonKeyFormatted = new(personKeyFormattedToNewestPersonKeyFormatted);
} }
@ -356,13 +356,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
else else
results = []; results = [];
} }
return new(results); return results.AsReadOnly();
}
public ReadOnlyDictionary<long, PersonContainer> GetPersonKeyToPersonContainer()
{
Dictionary<long, PersonContainer> results = [];
return new(results);
} }
public ReadOnlyDictionary<long, List<int>> GetPersonKeyToIds() public ReadOnlyDictionary<long, List<int>> GetPersonKeyToIds()
@ -399,7 +393,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
} }
if (shouldMove.Count > 0) if (shouldMove.Count > 0)
throw new Exception(string.Join(Environment.NewLine, shouldMove)); throw new Exception(string.Join(Environment.NewLine, shouldMove));
return new(results); return results.AsReadOnly();
} }
(bool, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>?) Shared.Models.Methods.IMapLogic.GetWholePercentagesToPersonContainers(int id) (bool, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>?) Shared.Models.Methods.IMapLogic.GetWholePercentagesToPersonContainers(int id)
@ -1095,7 +1089,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
results.Add(new(keyMapping, sortingContainer.Sorting, sortingContainer.Source)); results.Add(new(keyMapping, sortingContainer.Sorting, sortingContainer.Source));
} }
} }
return new(results); return results.AsReadOnly();
} }
private (string, PersonBirthday?) GetPersonBirthday(string[] directoryNames) private (string, PersonBirthday?) GetPersonBirthday(string[] directoryNames)
@ -1265,6 +1259,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
{ {
if (_Configuration is null) if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration)); throw new NullReferenceException(nameof(_Configuration));
int? updated = null;
FileHolder fileHolder; FileHolder fileHolder;
SaveContainer? saveContainer; SaveContainer? saveContainer;
List<SaveContainer> saveContainers = []; List<SaveContainer> saveContainers = [];
@ -1277,7 +1272,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
saveContainer = new(fileHolder, filteredOriginalImage.CheckFile, filteredOriginalImage.Directory); saveContainer = new(fileHolder, filteredOriginalImage.CheckFile, filteredOriginalImage.Directory);
saveContainers.Add(saveContainer); saveContainers.Add(saveContainer);
} }
SaveContainers(null, saveContainers); SaveContainers(updated, saveContainers);
} }
public void SaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, ReadOnlyDictionary<long, List<int>> personKeyToIds, ReadOnlyCollection<Mapping> distinctValidImageMappingCollection) public void SaveShortcutsForOutputResolutionsPreMapLogic(string eDistanceContentDirectory, ReadOnlyDictionary<long, List<int>> personKeyToIds, ReadOnlyCollection<Mapping> distinctValidImageMappingCollection)

View File

@ -64,21 +64,22 @@ internal abstract class FaceFileLogic
exifDirectory = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(mappedFile.FilePath); exifDirectory = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(mappedFile.FilePath);
RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value); RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value);
personDisplayDirectoryName = mappedFile.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : mappedFile.PersonDisplayDirectoryName; personDisplayDirectoryName = mappedFile.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : mappedFile.PersonDisplayDirectoryName;
LocationContainer locationContainer = new(dateOnly,
exifDirectory,
mappedFile.DirectoryNumber,
personDisplayDirectoryName,
null,
null,
mappedFile.FilePath,
fromDistanceContent,
id.Value,
null,
null,
mappedFile.PersonKey,
rectangle,
wholePercentages.Value);
lock (locationContainers) lock (locationContainers)
locationContainers.Add(new(dateOnly, locationContainers.Add(locationContainer);
exifDirectory,
mappedFile.DirectoryNumber,
personDisplayDirectoryName,
null,
null,
mappedFile.FilePath,
fromDistanceContent,
id.Value,
null,
null,
mappedFile.PersonKey,
rectangle,
wholePercentages.Value));
} }
private static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetReadOnly(Dictionary<int, Dictionary<int, LocationContainer>> keyValuePairs) private static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetReadOnly(Dictionary<int, Dictionary<int, LocationContainer>> keyValuePairs)
@ -86,40 +87,33 @@ internal abstract class FaceFileLogic
Dictionary<int, ReadOnlyDictionary<int, LocationContainer>> results = []; Dictionary<int, ReadOnlyDictionary<int, LocationContainer>> results = [];
foreach (KeyValuePair<int, Dictionary<int, LocationContainer>> keyValuePair in keyValuePairs) foreach (KeyValuePair<int, Dictionary<int, LocationContainer>> keyValuePair in keyValuePairs)
results.Add(keyValuePair.Key, new(keyValuePair.Value)); results.Add(keyValuePair.Key, new(keyValuePair.Value));
return new(results); return results.AsReadOnly();
} }
internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetMapped(int maxDegreeOfParallelism, Property.Models.Configuration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetMapped(int maxDegreeOfParallelism, Property.Models.Configuration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory)
{ {
Dictionary<int, Dictionary<int, LocationContainer>> results = []; Dictionary<int, Dictionary<int, LocationContainer>> results = [];
List<LocationContainer> locationContainers = []; List<LocationContainer> locationContainers = [];
List<string> personKeyFormattedCollection = [];
Dictionary<int, LocationContainer>? keyValuePairs; Dictionary<int, LocationContainer>? keyValuePairs;
Dictionary<int, List<(string, int)>> skipCollection = []; Dictionary<int, List<(string, int)>> skipCollection = [];
Dictionary<int, List<(string, int)>> skipNotSkipCollection = []; Dictionary<int, List<(string, int)>> skipNotSkipCollection = [];
ReadOnlyCollection<string> readOnlyPersonKeyFormattedCollection; Dictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted = [];
ReadOnlyDictionary<string, string> readOnlyPersonKeyFormattedToNewestPersonKeyFormatted;
SetSkipCollections(configuration, personContainers, a2PeopleSingletonDirectory, skipCollection, skipNotSkipCollection); SetSkipCollections(configuration, personContainers, a2PeopleSingletonDirectory, skipCollection, skipNotSkipCollection);
{ SetPersonCollectionsAfterSetSkipCollections(configuration, personContainers, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection);
List<string> personKeyFormattedCollection = []; List<Record> records = DistanceLogic.DeleteEmptyDirectoriesAndGetCollection(propertyConfiguration, configuration, ticks, eDistanceContentDirectory, personKeyFormattedToNewestPersonKeyFormatted.AsReadOnly(), personKeyFormattedCollection.AsReadOnly());
Dictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted = [];
SetPersonCollections(configuration, personContainers, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection);
readOnlyPersonKeyFormattedCollection = new(personKeyFormattedCollection);
readOnlyPersonKeyFormattedToNewestPersonKeyFormatted = new(personKeyFormattedToNewestPersonKeyFormatted);
}
List<Record> records = DistanceLogic.DeleteEmptyDirectoriesAndGetCollection(propertyConfiguration, configuration, ticks, eDistanceContentDirectory, readOnlyPersonKeyFormattedToNewestPersonKeyFormatted, readOnlyPersonKeyFormattedCollection);
List<MappedFile> mappedFiles = GetMappedFiles(propertyConfiguration, configuration, personContainers, records); List<MappedFile> mappedFiles = GetMappedFiles(propertyConfiguration, configuration, personContainers, records);
if (mappedFiles.Count > 0) if (mappedFiles.Count > 0)
{ {
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 Mapped Face Files Collection - {totalSeconds} total second(s)"; string message = $") Building Mapped Face Files Collection - {totalSeconds} total second(s)";
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
ReadOnlyDictionary<int, List<(string, int)>> readOnlySkipNotSkipCollection = new(skipCollection);
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
using ProgressBar progressBar = new(mappedFiles.Count, message, options); using ProgressBar progressBar = new(mappedFiles.Count, message, options);
_ = Parallel.For(0, mappedFiles.Count, parallelOptions, (i, state) => _ = Parallel.For(0, mappedFiles.Count, parallelOptions, (i, state) =>
{ {
progressBar.Tick(); progressBar.Tick();
MappedParallelFor(propertyConfiguration, configuration, readOnlySkipNotSkipCollection, locationContainers, mappedFiles[i]); MappedParallelFor(propertyConfiguration, configuration, skipCollection.AsReadOnly(), locationContainers, mappedFiles[i]);
}); });
} }
foreach (LocationContainer locationContainer in locationContainers) foreach (LocationContainer locationContainer in locationContainers)
@ -176,21 +170,22 @@ internal abstract class FaceFileLogic
RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value); RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value);
if (rectangle is null) if (rectangle is null)
return; return;
LocationContainer locationContainer = new(dateOnly,
exifDirectory,
null,
null,
null,
faceFile,
filePath,
fromDistanceContent,
filePath.Id.Value,
null,
null,
null,
rectangle,
wholePercentages.Value);
lock (locationContainers) lock (locationContainers)
locationContainers.Add(new(dateOnly, locationContainers.Add(locationContainer);
exifDirectory,
null,
null,
null,
faceFile,
filePath,
fromDistanceContent,
filePath.Id.Value,
null,
null,
null,
rectangle,
wholePercentages.Value));
} }
internal static List<LocationContainer> GetAvailable(int maxDegreeOfParallelism, Configuration configuration, IFaceD dFace, long ticks, ReadOnlyCollection<FilePath> filePaths) internal static List<LocationContainer> GetAvailable(int maxDegreeOfParallelism, Configuration configuration, IFaceD dFace, long ticks, ReadOnlyCollection<FilePath> filePaths)

View File

@ -83,7 +83,7 @@ internal abstract class MapLogic
} }
} }
internal static void SetPersonCollections(Configuration configuration, ReadOnlyCollection<PersonContainer> personContainers, Dictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted, List<string> personKeyFormattedCollection) internal static void SetPersonCollectionsAfterSetSkipCollections(Configuration configuration, ReadOnlyCollection<PersonContainer> personContainers, Dictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted, List<string> personKeyFormattedCollection)
{ {
string personKeyFormatted; string personKeyFormatted;
string newestPersonKeyFormatted; string newestPersonKeyFormatted;
@ -174,7 +174,7 @@ internal abstract class MapLogic
results.Add(face); results.Add(face);
} }
} }
return new(results); return results.AsReadOnly();
} }
internal static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, MappingFromItem mappingFromItem) internal static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, MappingFromItem mappingFromItem)
@ -234,11 +234,28 @@ internal abstract class MapLogic
} }
} }
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);
}
}
internal static string GetFacesDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dFacesContentDirectory, FilePath filePath, MappingFromItem mappingFromItem) internal static string GetFacesDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dFacesContentDirectory, FilePath filePath, MappingFromItem mappingFromItem)
{ {
string result; string result;
(string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
result = Path.Combine(dFacesContentDirectory, directoryName, mappingFromItem.FilePath.NameWithoutExtension); result = Path.Combine(dFacesContentDirectory, cei.Combined, mappingFromItem.FilePath.NameWithoutExtension);
MoveIf(mappingFromItem.FilePath.NameWithoutExtension, cei, dFacesContentDirectory, result);
return result; return result;
} }
@ -369,7 +386,7 @@ internal abstract class MapLogic
} }
results.Add(idTo.Key, new(keyValuePairs)); results.Add(idTo.Key, new(keyValuePairs));
} }
return new(results); return results.AsReadOnly();
} }
private static ReadOnlyDictionary<int, ReadOnlyDictionary<int, Mapping>> GetReadOnly(Dictionary<int, Dictionary<int, Mapping>> keyValuePairs) private static ReadOnlyDictionary<int, ReadOnlyDictionary<int, Mapping>> GetReadOnly(Dictionary<int, Dictionary<int, Mapping>> keyValuePairs)
@ -377,7 +394,7 @@ internal abstract class MapLogic
Dictionary<int, ReadOnlyDictionary<int, Mapping>> results = []; Dictionary<int, ReadOnlyDictionary<int, Mapping>> results = [];
foreach (KeyValuePair<int, Dictionary<int, Mapping>> keyValuePair in keyValuePairs) foreach (KeyValuePair<int, Dictionary<int, Mapping>> keyValuePair in keyValuePairs)
results.Add(keyValuePair.Key, new(keyValuePair.Value)); results.Add(keyValuePair.Key, new(keyValuePair.Value));
return new(results); return results.AsReadOnly();
} }
private static List<PersonContainer> GetNonSpecificPeopleCollection(Configuration configuration, long ticks, List<long> personKeys, ReadOnlyDictionary<long, int> personKeyToCount) private static List<PersonContainer> GetNonSpecificPeopleCollection(Configuration configuration, long ticks, List<long> personKeys, ReadOnlyDictionary<long, int> personKeyToCount)
@ -418,7 +435,7 @@ internal abstract class MapLogic
if (check) if (check)
continue; continue;
personBirthday = IPersonBirthday.GetPersonBirthday(personKey + (oneHour * 2)); personBirthday = IPersonBirthday.GetPersonBirthday(personKey + (oneHour * 2));
personContainer = new(approximateYears, [personBirthday], new(personDisplayDirectoryAllFilePaths), configuration.MappingDefaultName, personKey); personContainer = PersonContainer.Get(approximateYears, [personBirthday], new(personDisplayDirectoryAllFilePaths), configuration.MappingDefaultName, personKey);
results.Add(personContainer); results.Add(personContainer);
if (results.Count > 99) if (results.Count > 99)
break; break;
@ -447,6 +464,9 @@ internal abstract class MapLogic
FileHolder fileHolder; FileHolder fileHolder;
List<string> distinct = []; List<string> distinct = [];
PersonBirthday? personBirthday; PersonBirthday? personBirthday;
PersonContainer? personContainer;
string? personDisplayDirectoryName;
ReadOnlyDictionary<long, PersonContainer> keyValuePairs = PersonContainer.Extract(personContainers);
results.AddRange(GetDisplayDirectoryAllFiles(configuration.FacesFileNameExtension, configuration.PersonBirthdayFormat, personContainers)); results.AddRange(GetDisplayDirectoryAllFiles(configuration.FacesFileNameExtension, configuration.PersonBirthdayFormat, personContainers));
foreach (Record record in records) foreach (Record record in records)
{ {
@ -455,9 +475,13 @@ internal abstract class MapLogic
continue; continue;
if (distinct.Contains(record.MappedFaceFilePath.Name)) if (distinct.Contains(record.MappedFaceFilePath.Name))
continue; continue;
distinct.Add(record.MappedFaceFilePath.Name);
personKey = personBirthday.Value.Ticks; personKey = personBirthday.Value.Ticks;
results.Add(new(personKey, record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.DirectoryNumber, record.MappedFaceFilePath)); distinct.Add(record.MappedFaceFilePath.Name);
if (!keyValuePairs.TryGetValue(personKey, out personContainer))
personDisplayDirectoryName = record.PersonDisplayDirectoryName;
else
personDisplayDirectoryName = personContainer.DisplayDirectoryName;
results.Add(new(personKey, record.PersonKeyFormatted, personDisplayDirectoryName, record.DirectoryNumber, record.MappedFaceFilePath));
} }
for (int i = results.Count - 1; i > -1; i--) for (int i = results.Count - 1; i > -1; i--)
{ {
@ -535,21 +559,22 @@ internal abstract class MapLogic
exifDirectory = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(mappedFile.FilePath); exifDirectory = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(mappedFile.FilePath);
RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value); RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value);
personDisplayDirectoryName = mappedFile.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : mappedFile.PersonDisplayDirectoryName; personDisplayDirectoryName = mappedFile.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : mappedFile.PersonDisplayDirectoryName;
LocationContainer locationContainer = new(dateOnly,
exifDirectory,
mappedFile.DirectoryNumber,
personDisplayDirectoryName,
null,
null,
mappedFile.FilePath,
fromDistanceContent,
id.Value,
null,
null,
mappedFile.PersonKey,
rectangle,
wholePercentages.Value);
lock (locationContainers) lock (locationContainers)
locationContainers.Add(new(dateOnly, locationContainers.Add(locationContainer);
exifDirectory,
mappedFile.DirectoryNumber,
personDisplayDirectoryName,
null,
null,
mappedFile.FilePath,
fromDistanceContent,
id.Value,
null,
null,
mappedFile.PersonKey,
rectangle,
wholePercentages.Value));
} }
private static void LookForPossibleDuplicates(Configuration configuration, ReadOnlyCollection<LocationContainer> locationContainers) private static void LookForPossibleDuplicates(Configuration configuration, ReadOnlyCollection<LocationContainer> locationContainers)
@ -739,7 +764,7 @@ internal abstract class MapLogic
group = IPerson.GetHourGroup(personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName, personBirthday.Value.Hour); group = IPerson.GetHourGroup(personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName, personBirthday.Value.Hour);
(status, sex, first) = IPerson.GetPersonHour(personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName, personBirthday.Value.Hour); (status, sex, first) = IPerson.GetPersonHour(personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName, personBirthday.Value.Hour);
personDirectory = new(matches.First(), group, status, sex, first); personDirectory = new(matches.First(), group, status, sex, first);
personContainer = new(configuration.PersonCharacters.ToArray(), personBirthday, personDisplayDirectoryName, personDirectory); personContainer = PersonContainer.Get(configuration.PersonCharacters.ToArray(), personBirthday, personDisplayDirectoryName, personDirectory);
personKeyFormattedToPersonContainer.Add(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, personContainer); personKeyFormattedToPersonContainer.Add(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, personContainer);
} }
if (personContainer.Key is null) if (personContainer.Key is null)
@ -785,7 +810,7 @@ internal abstract class MapLogic
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)); results.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.IsDefault, record.LinksCount, record.MappedFaceFilePath, record.MappedFaceFilePath.Id.Value, wholePercentages.Value));
} }
return new(results); return results.AsReadOnly();
} }
internal static List<PersonContainer> GetNotMappedPersonContainers(Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, ReadOnlyDictionary<long, int> personKeyToCount) internal static List<PersonContainer> GetNotMappedPersonContainers(Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, ReadOnlyDictionary<long, int> personKeyToCount)
@ -839,9 +864,9 @@ internal abstract class MapLogic
continue; continue;
personBirthday = IPersonBirthday.GetPersonBirthday(keyValuePair.Key); personBirthday = IPersonBirthday.GetPersonBirthday(keyValuePair.Key);
if (!personKeyToPersonContainerCollection.TryGetValue(keyValuePair.Key, out collection)) if (!personKeyToPersonContainerCollection.TryGetValue(keyValuePair.Key, out collection))
personContainer = new(approximateYears, personBirthday, displayDirectoryName, keyValuePair.Key); personContainer = PersonContainer.Get(approximateYears, personBirthday, displayDirectoryName, keyValuePair.Key);
else else
personContainer = new(approximateYears, personBirthday, collection[zero].PersonDirectory, displayDirectoryName, keyValuePair.Key); personContainer = PersonContainer.Get(approximateYears, personBirthday, collection[zero].PersonDirectory, displayDirectoryName, keyValuePair.Key);
personKeyToPersonContainer.Add(keyValuePair.Key, personContainer); personKeyToPersonContainer.Add(keyValuePair.Key, personContainer);
} }
} }
@ -990,24 +1015,26 @@ internal abstract class MapLogic
internal static string GetFacePartsDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string d2FacePartsContentDirectory, FilePath filePath, MappingFromItem mappingFromItem) internal static string GetFacePartsDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string d2FacePartsContentDirectory, FilePath filePath, MappingFromItem mappingFromItem)
{ {
string result; string result;
(string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
result = Path.Combine(d2FacePartsContentDirectory, directoryName, mappingFromItem.FilePath.NameWithoutExtension); result = Path.Combine(d2FacePartsContentDirectory, cei.Combined, mappingFromItem.FilePath.NameWithoutExtension);
MoveIf(mappingFromItem.FilePath.NameWithoutExtension, cei, d2FacePartsContentDirectory, result);
return result; return result;
} }
internal static string GetFacePartsDirectoryX(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string d2FacePartsContentDirectory, FilePath filePath) internal static string GetFacePartsDirectoryX(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string d2FacePartsContentDirectory, FilePath filePath)
{ {
string result; string result;
(string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
result = Path.Combine(d2FacePartsContentDirectory, directoryName, filePath.NameWithoutExtension); result = Path.Combine(d2FacePartsContentDirectory, cei.Combined, filePath.NameWithoutExtension);
MoveIf(filePath.NameWithoutExtension, cei, d2FacePartsContentDirectory, result);
return result; return result;
} }
internal static string GetResizeContentDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string cContentDirectory, FilePath filePath) internal static string GetResizeContentDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string cContentDirectory, FilePath filePath)
{ {
string result; string result;
(string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
result = Path.Combine(cContentDirectory, directoryName); result = Path.Combine(cContentDirectory, cei.Combined);
return result; return result;
} }
@ -1116,7 +1143,7 @@ internal abstract class MapLogic
collection.Add(keyValuePair.Key); collection.Add(keyValuePair.Key);
} }
} }
return new(results); return results.AsReadOnly();
} }
internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, Mapping>> GetIdToWholePercentagesToFace(ReadOnlyCollection<Mapping> distinctValidImageMappingCollection) internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, Mapping>> GetIdToWholePercentagesToFace(ReadOnlyCollection<Mapping> distinctValidImageMappingCollection)
@ -1266,7 +1293,7 @@ internal abstract class MapLogic
foreach ((string _, int wholePercentage) in keyValuePair.Value) foreach ((string _, int wholePercentage) in keyValuePair.Value)
wholePercentagesCollection.Add(wholePercentage); wholePercentagesCollection.Add(wholePercentage);
} }
return new(results); return results.AsReadOnly();
} }
internal static ReadOnlyDictionary<int, List<int>> ConvertSkipNotSkip(Dictionary<int, List<(string, int)>> skipNotSkipCollection) internal static ReadOnlyDictionary<int, List<int>> ConvertSkipNotSkip(Dictionary<int, List<(string, int)>> skipNotSkipCollection)
@ -1284,7 +1311,7 @@ internal abstract class MapLogic
foreach ((string _, int wholePercentage) in keyValuePair.Value) foreach ((string _, int wholePercentage) in keyValuePair.Value)
wholePercentagesCollection.Add(wholePercentage); wholePercentagesCollection.Add(wholePercentage);
} }
return new(results); return results.AsReadOnly();
} }
internal static ReadOnlyDictionary<int, List<LocationContainer>> ConvertLocationContainers(List<LocationContainer> locationContainers) internal static ReadOnlyDictionary<int, List<LocationContainer>> ConvertLocationContainers(List<LocationContainer> locationContainers)
@ -1296,7 +1323,7 @@ internal abstract class MapLogic
results.Add(locationContainer.Id, []); results.Add(locationContainer.Id, []);
results[locationContainer.Id].Add(locationContainer); results[locationContainer.Id].Add(locationContainer);
} }
return new(results); return results.AsReadOnly();
} }
internal static bool? CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, int wholePercentages) internal static bool? CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, int wholePercentages)

View File

@ -82,12 +82,12 @@ internal abstract class RelationLogic
locationContainer = collection[0]; locationContainer = collection[0];
if (locationContainer.PersonKey is null) if (locationContainer.PersonKey is null)
continue; continue;
results.Add(new(key, locationContainer.PersonKey.Value, new(collection))); results.Add(new(key, locationContainer.PersonKey.Value, collection.AsReadOnly()));
collection = []; collection = [];
years.Clear(); years.Clear();
} }
} }
return new(results); return results.AsReadOnly();
} }
private static ReadOnlyDictionary<string, string> MoveFiles(Configuration configuration, string key, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers, List<List<string>> linked) private static ReadOnlyDictionary<string, string> MoveFiles(Configuration configuration, string key, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers, List<List<string>> linked)
@ -202,7 +202,7 @@ internal abstract class RelationLogic
_ = Directory.CreateDirectory(checkDirectory); _ = Directory.CreateDirectory(checkDirectory);
} }
} }
return new(results); return results.AsReadOnly();
} }
private static string? GetDisplayDirectoryName(ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, long personKey, string personKeyFormatted) private static string? GetDisplayDirectoryName(ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, long personKey, string personKeyFormatted)

View File

@ -4,13 +4,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<UserSecretsId>f89b7242-dbb0-4349-b950-657eb8cf87ef</UserSecretsId> <UserSecretsId>f89b7242-dbb0-4349-b950-657eb8cf87ef</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Metadata.Query</PackageId> <PackageId>Phares.View.by.Distance.Metadata.Query</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -35,10 +35,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -34,17 +34,15 @@ public class Configuration
} }
} }
private static Models.Configuration Get(Configuration? configuration) private static Models.Configuration Get(Configuration? configuration, Property.Models.Configuration propertyConfiguration)
{ {
Models.Configuration result; Models.Configuration result;
if (configuration is null) throw new NullReferenceException(nameof(configuration)); if (configuration is null) throw new NullReferenceException(nameof(configuration));
if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat)); if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat));
if (configuration.PropertyConfiguration is null) throw new NullReferenceException(nameof(configuration.PropertyConfiguration)); result = new(propertyConfiguration,
result = new( configuration.IgnoreExtensions,
configuration.IgnoreExtensions, configuration.PersonBirthdayFormat);
configuration.PersonBirthdayFormat,
configuration.PropertyConfiguration);
return result; return result;
} }
@ -66,7 +64,7 @@ public class Configuration
#pragma warning restore IL3050, IL2026 #pragma warning restore IL3050, IL2026
} }
PreVerify(configurationRoot, configuration); PreVerify(configurationRoot, configuration);
result = Get(configuration); result = Get(configuration, propertyConfiguration);
return result; return result;
} }

View File

@ -13,10 +13,9 @@ public class Configuration
public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration; public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration;
[JsonConstructor] [JsonConstructor]
public Configuration( public Configuration(Property.Models.Configuration propertyConfiguration,
string[] ignoreExtensions, string[] ignoreExtensions,
string personBirthdayFormat, string personBirthdayFormat)
Property.Models.Configuration propertyConfiguration)
{ {
IgnoreExtensions = ignoreExtensions; IgnoreExtensions = ignoreExtensions;
PersonBirthdayFormat = personBirthdayFormat; PersonBirthdayFormat = personBirthdayFormat;

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Metadata</PackageId> <PackageId>Phares.View.by.Distance.Metadata</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -34,7 +34,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -17,15 +17,23 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
private readonly IPropertyConfiguration _PropertyConfiguration; private readonly IPropertyConfiguration _PropertyConfiguration;
private readonly bool _ForceMetadataLastWriteTimeToCreationTime; private readonly bool _ForceMetadataLastWriteTimeToCreationTime;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
private readonly ReadOnlyDictionary<string, ReadOnlyCollection<string>> _FileGroups; private readonly ReadOnlyDictionary<byte, ReadOnlyCollection<string>>[] _ResultSingletonFileGroups;
public B_Metadata(IPropertyConfiguration propertyConfiguration) public B_Metadata(IPropertyConfiguration propertyConfiguration)
{ {
_PropertiesChangedForMetadata = false; _PropertiesChangedForMetadata = false;
_PropertyConfiguration = propertyConfiguration; _PropertyConfiguration = propertyConfiguration;
_ForceMetadataLastWriteTimeToCreationTime = false; _ForceMetadataLastWriteTimeToCreationTime = false;
_ResultSingletonFileGroups = [new(new Dictionary<byte, ReadOnlyCollection<string>>())];
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
_FileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, null, [propertyConfiguration.ResultSingleton]); ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, null, [propertyConfiguration.ResultSingleton]);
foreach (KeyValuePair<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePair in keyValuePairs)
{
if (keyValuePair.Key == _PropertyConfiguration.ResultSingleton)
_ResultSingletonFileGroups[0] = keyValuePair.Value;
else
throw new Exception();
}
} }
public B_Metadata(IPropertyConfiguration propertyConfiguration, bool forceMetadataLastWriteTimeToCreationTime, bool propertiesChangedForMetadata, string bResultsFullGroupDirectory) public B_Metadata(IPropertyConfiguration propertyConfiguration, bool forceMetadataLastWriteTimeToCreationTime, bool propertiesChangedForMetadata, string bResultsFullGroupDirectory)
@ -33,8 +41,16 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
_PropertyConfiguration = propertyConfiguration; _PropertyConfiguration = propertyConfiguration;
_PropertiesChangedForMetadata = propertiesChangedForMetadata; _PropertiesChangedForMetadata = propertiesChangedForMetadata;
_ForceMetadataLastWriteTimeToCreationTime = forceMetadataLastWriteTimeToCreationTime; _ForceMetadataLastWriteTimeToCreationTime = forceMetadataLastWriteTimeToCreationTime;
_ResultSingletonFileGroups = [new(new Dictionary<byte, ReadOnlyCollection<string>>())];
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
_FileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, bResultsFullGroupDirectory, [propertyConfiguration.ResultSingleton]); ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, bResultsFullGroupDirectory, [propertyConfiguration.ResultSingleton]);
foreach (KeyValuePair<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePair in keyValuePairs)
{
if (keyValuePair.Key == _PropertyConfiguration.ResultSingleton)
_ResultSingletonFileGroups[0] = keyValuePair.Value;
else
throw new Exception();
}
} }
public override string ToString() public override string ToString()
@ -43,12 +59,34 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
return result; return result;
} }
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
{
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 && System.IO.Directory.Exists(checkDirectory))
{
string checkFile = Path.Combine(checkDirectory, fileName);
if (File.Exists(checkFile))
{
File.Move(checkFile, fileInfo.FullName);
fileInfo.Refresh();
}
}
}
public ExifDirectory GetMetadataCollection(FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string[] changesFrom, MappingFromItem mappingFromItem) public ExifDirectory GetMetadataCollection(FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string[] changesFrom, MappingFromItem mappingFromItem)
{ {
ExifDirectory? result = null; ExifDirectory? result = null;
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
(_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
FileInfo fileInfo = new(Path.Combine(_FileGroups[_PropertyConfiguration.ResultSingleton][directoryIndex], $"{mappingFromItem.FilePath.NameWithoutExtension}{mappingFromItem.FilePath.ExtensionLowered}.json")); string fileName = $"{mappingFromItem.FilePath.NameWithoutExtension}{mappingFromItem.FilePath.ExtensionLowered}.json";
string directory = _ResultSingletonFileGroups[0][cei.Enum][cei.Index];
FileInfo fileInfo = new(Path.Combine(directory, fileName));
MoveIf(fileName, cei, directory, fileInfo);
if (_ForceMetadataLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) if (_ForceMetadataLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
{ {
File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName);

View File

@ -484,7 +484,7 @@ internal abstract class Exif
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.ExifDirectory Covert(Shared.Models.FilePath filePath, System.Drawing.Size? size, IReadOnlyList<MetadataExtractor.Directory> directories) private static Shared.Models.ExifDirectory Covert(Shared.Models.FilePath filePath, IReadOnlyList<MetadataExtractor.Directory> directories, System.Drawing.Size? size)
{ {
Shared.Models.ExifDirectory result; Shared.Models.ExifDirectory result;
Shared.Models.AviDirectory[] aviDirectories = GetAviDirectories(directories); Shared.Models.AviDirectory[] aviDirectories = GetAviDirectories(directories);
@ -502,12 +502,12 @@ internal abstract class Exif
result = new(aviDirectories, result = new(aviDirectories,
exifBaseDirectories, exifBaseDirectories,
fileMetadataDirectories, fileMetadataDirectories,
filePath,
gifHeaderDirectories, gifHeaderDirectories,
gpsDirectories, gpsDirectories,
size?.Height, size?.Height,
jpegDirectories, jpegDirectories,
makernoteDirectories, makernoteDirectories,
filePath.Name,
photoshopDirectories, photoshopDirectories,
pngDirectories, pngDirectories,
quickTimeMovieHeaderDirectories, quickTimeMovieHeaderDirectories,
@ -520,13 +520,13 @@ internal abstract class Exif
internal static Shared.Models.ExifDirectory GetExifDirectory(Shared.Models.FilePath filePath) internal static Shared.Models.ExifDirectory GetExifDirectory(Shared.Models.FilePath filePath)
{ {
Shared.Models.ExifDirectory result; Shared.Models.ExifDirectory result;
IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(filePath.FullName);
System.Drawing.Size? size; System.Drawing.Size? size;
try try
{ size = Dimensions.GetDimensions(filePath.FullName); } { size = Dimensions.GetDimensions(filePath.FullName); }
catch (Exception) catch (Exception)
{ size = null; } { size = null; }
IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(filePath.FullName); result = Covert(filePath, directories, size);
result = Covert(filePath, size, directories);
return result; return result;
} }

View File

@ -4,13 +4,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<UserSecretsId>fa06c6db-0226-42ca-8728-68b1e336184d</UserSecretsId> <UserSecretsId>fa06c6db-0226-42ca-8728-68b1e336184d</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Mirror.Length</PackageId> <PackageId>Phares.View.by.Distance.Mirror.Length</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -35,10 +35,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -193,6 +193,7 @@ public class MirrorLength
{ {
string message = nameof(MirrorLength); string message = nameof(MirrorLength);
List<(string, string, int)> collectionForMarkDown; List<(string, string, int)> collectionForMarkDown;
logger?.LogDebug("{method}", nameof(MirrorLengthFilesInDirectories));
bool inPlaceSave = _PropertyConfiguration.RootDirectory.First() == _AppSettings.Destination; bool inPlaceSave = _PropertyConfiguration.RootDirectory.First() == _AppSettings.Destination;
if (!inPlaceSave) if (!inPlaceSave)
collectionForMarkDown = []; collectionForMarkDown = [];

View File

@ -34,17 +34,15 @@ public class Configuration
} }
} }
private static Models.Configuration Get(Configuration? configuration) private static Models.Configuration Get(Configuration? configuration, Property.Models.Configuration propertyConfiguration)
{ {
Models.Configuration result; Models.Configuration result;
if (configuration is null) throw new NullReferenceException(nameof(configuration)); if (configuration is null) throw new NullReferenceException(nameof(configuration));
if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat)); if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat));
if (configuration.PropertyConfiguration is null) throw new NullReferenceException(nameof(configuration.PropertyConfiguration)); result = new(propertyConfiguration,
result = new( configuration.IgnoreExtensions,
configuration.IgnoreExtensions, configuration.PersonBirthdayFormat);
configuration.PersonBirthdayFormat,
configuration.PropertyConfiguration);
return result; return result;
} }
@ -66,7 +64,7 @@ public class Configuration
#pragma warning restore IL3050, IL2026 #pragma warning restore IL3050, IL2026
} }
PreVerify(configurationRoot, configuration); PreVerify(configurationRoot, configuration);
result = Get(configuration); result = Get(configuration, propertyConfiguration);
return result; return result;
} }

View File

@ -13,10 +13,9 @@ public class Configuration
public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration; public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration;
[JsonConstructor] [JsonConstructor]
public Configuration( public Configuration(Property.Models.Configuration propertyConfiguration,
string[] ignoreExtensions, string[] ignoreExtensions,
string personBirthdayFormat, string personBirthdayFormat)
Property.Models.Configuration propertyConfiguration)
{ {
IgnoreExtensions = ignoreExtensions; IgnoreExtensions = ignoreExtensions;
PersonBirthdayFormat = personBirthdayFormat; PersonBirthdayFormat = personBirthdayFormat;

View File

@ -34,17 +34,15 @@ public class Configuration
} }
} }
private static Models.Configuration Get(Configuration? configuration) private static Models.Configuration Get(Configuration? configuration, Property.Models.Configuration propertyConfiguration)
{ {
Models.Configuration result; Models.Configuration result;
if (configuration is null) throw new NullReferenceException(nameof(configuration)); if (configuration is null) throw new NullReferenceException(nameof(configuration));
if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat)); if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat));
if (configuration.PropertyConfiguration is null) throw new NullReferenceException(nameof(configuration.PropertyConfiguration)); result = new(propertyConfiguration,
result = new( configuration.IgnoreExtensions,
configuration.IgnoreExtensions, configuration.PersonBirthdayFormat);
configuration.PersonBirthdayFormat,
configuration.PropertyConfiguration);
return result; return result;
} }
@ -66,7 +64,7 @@ public class Configuration
#pragma warning restore IL3050, IL2026 #pragma warning restore IL3050, IL2026
} }
PreVerify(configurationRoot, configuration); PreVerify(configurationRoot, configuration);
result = Get(configuration); result = Get(configuration, propertyConfiguration);
return result; return result;
} }

View File

@ -13,10 +13,9 @@ public class Configuration
public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration; public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration;
[JsonConstructor] [JsonConstructor]
public Configuration( public Configuration(Property.Models.Configuration propertyConfiguration,
string[] ignoreExtensions, string[] ignoreExtensions,
string personBirthdayFormat, string personBirthdayFormat)
Property.Models.Configuration propertyConfiguration)
{ {
IgnoreExtensions = ignoreExtensions; IgnoreExtensions = ignoreExtensions;
PersonBirthdayFormat = personBirthdayFormat; PersonBirthdayFormat = personBirthdayFormat;

View File

@ -4,13 +4,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<UserSecretsId>ce31220e-ef92-4e68-89c5-91b027a94dca</UserSecretsId> <UserSecretsId>ce31220e-ef92-4e68-89c5-91b027a94dca</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Move.By.Id</PackageId> <PackageId>Phares.View.by.Distance.Move.By.Id</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -35,9 +35,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -34,17 +34,15 @@ public class Configuration
} }
} }
private static Models.Configuration Get(Configuration? configuration) private static Models.Configuration Get(Configuration? configuration, Property.Models.Configuration propertyConfiguration)
{ {
Models.Configuration result; Models.Configuration result;
if (configuration is null) throw new NullReferenceException(nameof(configuration)); if (configuration is null) throw new NullReferenceException(nameof(configuration));
if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat)); if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat));
if (configuration.PropertyConfiguration is null) throw new NullReferenceException(nameof(configuration.PropertyConfiguration)); result = new(propertyConfiguration,
result = new( configuration.IgnoreExtensions,
configuration.IgnoreExtensions, configuration.PersonBirthdayFormat);
configuration.PersonBirthdayFormat,
configuration.PropertyConfiguration);
return result; return result;
} }
@ -66,7 +64,7 @@ public class Configuration
#pragma warning restore IL3050, IL2026 #pragma warning restore IL3050, IL2026
} }
PreVerify(configurationRoot, configuration); PreVerify(configurationRoot, configuration);
result = Get(configuration); result = Get(configuration, propertyConfiguration);
return result; return result;
} }

View File

@ -13,10 +13,9 @@ public class Configuration
public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration; public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration;
[JsonConstructor] [JsonConstructor]
public Configuration( public Configuration(Property.Models.Configuration propertyConfiguration,
string[] ignoreExtensions, string[] ignoreExtensions,
string personBirthdayFormat, string personBirthdayFormat)
Property.Models.Configuration propertyConfiguration)
{ {
IgnoreExtensions = ignoreExtensions; IgnoreExtensions = ignoreExtensions;
PersonBirthdayFormat = personBirthdayFormat; PersonBirthdayFormat = personBirthdayFormat;

View File

@ -4,13 +4,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<UserSecretsId>ae069946-d0c0-4e4f-94f6-9c526e4ae4e7</UserSecretsId> <UserSecretsId>ae069946-d0c0-4e4f-94f6-9c526e4ae4e7</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Offset.Date.Time.Original</PackageId> <PackageId>Phares.View.by.Distance.Offset.Date.Time.Original</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -35,10 +35,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -216,6 +216,17 @@ public class OffsetDateTimeOriginal
{ {
TimeSpan timeSpan = new(targetDateTimeOriginal.Value.Ticks - badDateTimeOriginal.Value.Ticks); TimeSpan timeSpan = new(targetDateTimeOriginal.Value.Ticks - badDateTimeOriginal.Value.Ticks);
DateFix(sourceDirectory, asciiEncoding, checkDirectory, minimumDateTime, maximumDateTime, timeSpan.Ticks); DateFix(sourceDirectory, asciiEncoding, checkDirectory, minimumDateTime, maximumDateTime, timeSpan.Ticks);
// DateTime a = new(2020, 01, 04, 02, 12, 51, 32);
// // DateTime a = new(2020, 01, 05, 18, 17, 15, 97);
// DateTime b = new(2020, 01, 05, 19, 52, 30, 17);
// DateTime c = new(2024, 12, 07, 11, 19, 06, 13);
// // DateTime d = new(2024, 12, 07, 12, 07, 30, 38);
// long e = new DateTime(c.Ticks - b.Ticks).AddMinutes(-5).Ticks;
// if (a != DateTime.MinValue)
// minimumDateTime = a.AddTicks(e).AddHours(-1);
// if (c != DateTime.MinValue)
// maximumDateTime = c;
// DateFix(sourceDirectory, asciiEncoding, checkDirectory, minimumDateTime, maximumDateTime, e);
} }
} }
} }

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.PhotoPrism</PackageId> <PackageId>Phares.View.by.Distance.PhotoPrism</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -37,7 +37,7 @@
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.PrepareForOld</PackageId> <PackageId>Phares.View.by.Distance.PrepareForOld</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -33,14 +33,14 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" /> <PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.10" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" /> <PackageReference Include="Microsoft.Extensions.Options" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Property.Compare</PackageId> <PackageId>Phares.View.by.Distance.Property.Compare</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -35,7 +35,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" /> <PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -22,19 +22,27 @@ public class A_Property
private readonly Configuration _Configuration; private readonly Configuration _Configuration;
private readonly List<string> _AngleBracketCollection; private readonly List<string> _AngleBracketCollection;
private readonly IPropertyConfiguration _PropertyConfiguration; private readonly IPropertyConfiguration _PropertyConfiguration;
private readonly ReadOnlyDictionary<string, ReadOnlyCollection<string>> _FileGroups; private readonly ReadOnlyDictionary<byte, ReadOnlyCollection<string>>[] _ResultSingletonFileGroups;
public A_Property(int maxDegreeOfParallelism, Configuration propertyConfiguration, string outputExtension, bool reverse, string aResultsFullGroupDirectory) public A_Property(int maxDegreeOfParallelism, Configuration propertyConfiguration, string outputExtension, bool reverse, string aResultsFullGroupDirectory)
{ {
Reverse = reverse; Reverse = reverse;
_ExceptionsDirectories = []; _ExceptionsDirectories = [];
_AngleBracketCollection = [];
_OutputExtension = outputExtension; _OutputExtension = outputExtension;
_ASCIIEncoding = new ASCIIEncoding(); _ASCIIEncoding = new ASCIIEncoding();
_Configuration = propertyConfiguration; _Configuration = propertyConfiguration;
_AngleBracketCollection = [];
_PropertyConfiguration = propertyConfiguration; _PropertyConfiguration = propertyConfiguration;
_MaxDegreeOfParallelism = maxDegreeOfParallelism; _MaxDegreeOfParallelism = maxDegreeOfParallelism;
_FileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, aResultsFullGroupDirectory, [propertyConfiguration.ResultSingleton]); _ResultSingletonFileGroups = [new(new Dictionary<byte, ReadOnlyCollection<string>>())];
ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, aResultsFullGroupDirectory, [propertyConfiguration.ResultSingleton]);
foreach (KeyValuePair<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePair in keyValuePairs)
{
if (keyValuePair.Key == _PropertyConfiguration.ResultSingleton)
_ResultSingletonFileGroups[0] = keyValuePair.Value;
else
throw new Exception();
}
} }
public override string ToString() public override string ToString()
@ -43,6 +51,25 @@ public class A_Property
return result; return result;
} }
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
{
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, fileInfo.FullName);
fileInfo.Refresh();
}
}
}
private Shared.Models.Property GetImageProperty(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension) private Shared.Models.Property GetImageProperty(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension)
{ {
Shared.Models.Property? result; Shared.Models.Property? result;
@ -57,8 +84,11 @@ public class A_Property
fileInfo = new(Path.Combine(angleBracket.Replace("<>", _PropertyConfiguration.ResultSingleton), $"{item.FilePath.NameWithoutExtension}{item.FilePath.ExtensionLowered}.json")); fileInfo = new(Path.Combine(angleBracket.Replace("<>", _PropertyConfiguration.ResultSingleton), $"{item.FilePath.NameWithoutExtension}{item.FilePath.ExtensionLowered}.json"));
else else
{ {
(_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, item.FilePath); string fileName = $"{item.FilePath.NameWithoutExtension}{item.FilePath.ExtensionLowered}.json";
fileInfo = new(Path.Combine(_FileGroups[_PropertyConfiguration.ResultSingleton][directoryIndex], $"{item.FilePath.NameWithoutExtension}{item.FilePath.ExtensionLowered}.json")); CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, item.FilePath);
string directory = _ResultSingletonFileGroups[0][cei.Enum][cei.Index];
fileInfo = new(Path.Combine(directory, fileName));
MoveIf(fileName, cei, directory, fileInfo);
} }
List<DateTime> dateTimes = (from l in sourceDirectoryFileTuples where l is not null && changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in sourceDirectoryFileTuples where l is not null && changesFrom.Contains(l.Item1) select l.Item2).ToList();
if (_Configuration.ForcePropertyLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) if (_Configuration.ForcePropertyLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
@ -168,7 +198,7 @@ public class A_Property
{ {
_AngleBracketCollection.Clear(); _AngleBracketCollection.Clear();
if (!anyNullOrNoIsUniqueFileName) if (!anyNullOrNoIsUniqueFileName)
_AngleBracketCollection.AddRange(new[] { Path.Combine(aResultsFullGroupDirectory, "<>") }); _AngleBracketCollection.AddRange([Path.Combine(aResultsFullGroupDirectory, "<>")]);
else else
_AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(_PropertyConfiguration, _AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(_PropertyConfiguration,
sourceDirectory, sourceDirectory,

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Property</PackageId> <PackageId>Phares.View.by.Distance.Property</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -40,10 +40,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="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" /> <PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -251,7 +251,7 @@ public class Rename
catch (Exception) { continue; } catch (Exception) { continue; }
CommandTask<CommandResult> result = Cli.Wrap("ffmpeg.exe") CommandTask<CommandResult> result = Cli.Wrap("ffmpeg.exe")
// .WithArguments(new[] { "-ss", "00:00:00", "-t", "00:00:00", "-i", files[i], "-qscale:v", "2", "-r", "0.01", $"{fileHolder.Name}-%4d.jpg" }) // .WithArguments(new[] { "-ss", "00:00:00", "-t", "00:00:00", "-i", files[i], "-qscale:v", "2", "-r", "0.01", $"{fileHolder.Name}-%4d.jpg" })
.WithArguments(new[] { "-i", files[i], "-vframes", "1", $"{fileHolder.Name}-%4d.jpg" }) .WithArguments(["-i", files[i], "-vframes", "1", $"{fileHolder.Name}-%4d.jpg"])
.WithWorkingDirectory(fileHolder.DirectoryFullPath) .WithWorkingDirectory(fileHolder.DirectoryFullPath)
.ExecuteAsync(); .ExecuteAsync();
result.Task.Wait(); result.Task.Wait();

View File

@ -4,13 +4,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<UserSecretsId>6e026d2f-9edf-4c6c-a042-162758114e9a</UserSecretsId> <UserSecretsId>6e026d2f-9edf-4c6c-a042-162758114e9a</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Rename</PackageId> <PackageId>Phares.View.by.Distance.Rename</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -34,11 +34,11 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CliWrap" Version="3.6.6" /> <PackageReference Include="CliWrap" Version="3.8.1" />
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Metadata\Metadata.csproj" /> <ProjectReference Include="..\Metadata\Metadata.csproj" />

View File

@ -40,11 +40,10 @@ public class C_Resize
private readonly bool _ForceResizeLastWriteTimeToCreationTime; private readonly bool _ForceResizeLastWriteTimeToCreationTime;
private readonly IPropertyConfiguration _PropertyConfiguration; private readonly IPropertyConfiguration _PropertyConfiguration;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
private readonly Dictionary<string, ReadOnlyCollection<string>> _FileGroups; private readonly ReadOnlyDictionary<byte, ReadOnlyCollection<string>>[] _ResultSingletonFileGroups;
public C_Resize(IPropertyConfiguration propertyConfiguration, bool forceResizeLastWriteTimeToCreationTime, bool overrideForResizeImages, bool propertiesChangedForResize, string[] validResolutions, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) public C_Resize(IPropertyConfiguration propertyConfiguration, bool forceResizeLastWriteTimeToCreationTime, bool overrideForResizeImages, bool propertiesChangedForResize, string[] validResolutions, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension)
{ {
_FileGroups = [];
_Original = "Original"; _Original = "Original";
_TempResolutionWidth = 3; _TempResolutionWidth = 3;
_TempResolutionHeight = 4; _TempResolutionHeight = 4;
@ -61,6 +60,7 @@ public class C_Resize
_OverrideForResizeImages = overrideForResizeImages; _OverrideForResizeImages = overrideForResizeImages;
_PropertiesChangedForResize = propertiesChangedForResize; _PropertiesChangedForResize = propertiesChangedForResize;
_ForceResizeLastWriteTimeToCreationTime = forceResizeLastWriteTimeToCreationTime; _ForceResizeLastWriteTimeToCreationTime = forceResizeLastWriteTimeToCreationTime;
_ResultSingletonFileGroups = [new(new Dictionary<byte, ReadOnlyCollection<string>>())];
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, [], null) ?? throw new Exception(); ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, [], null) ?? throw new Exception();
_ConstructorInfo = constructorInfo; _ConstructorInfo = constructorInfo;
@ -74,10 +74,14 @@ public class C_Resize
public void Update(string cResultsFullGroupDirectory) public void Update(string cResultsFullGroupDirectory)
{ {
_FileGroups.Clear(); ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, [_PropertyConfiguration.ResultSingleton]);
ReadOnlyDictionary<string, ReadOnlyCollection<string>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, [_PropertyConfiguration.ResultSingleton]); foreach (KeyValuePair<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePair in keyValuePairs)
foreach (KeyValuePair<string, ReadOnlyCollection<string>> keyValuePair in keyValuePairs) {
_FileGroups.Add(keyValuePair.Key, keyValuePair.Value); if (keyValuePair.Key == _PropertyConfiguration.ResultSingleton)
_ResultSingletonFileGroups[0] = keyValuePair.Value;
else
throw new Exception();
}
} }
public void SetAngleBracketCollection(string cResultsFullGroupDirectory, string sourceDirectory) public void SetAngleBracketCollection(string cResultsFullGroupDirectory, string sourceDirectory)
@ -98,7 +102,8 @@ public class C_Resize
{ {
(ImageCodecInfo, EncoderParameters, string) result; (ImageCodecInfo, EncoderParameters, string) result;
ImageFormat imageFormat = ImageFormat.Jpeg; ImageFormat imageFormat = ImageFormat.Jpeg;
ImageCodecInfo imageCodecInfo = (from l in ImageCodecInfo.GetImageEncoders() where l.FormatID == imageFormat.Guid select l).First(); ImageCodecInfo[] imageCodecInfoCollection = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo imageCodecInfo = (from l in imageCodecInfoCollection where l.FormatID == imageFormat.Guid select l).First();
EncoderParameters encoderParameters = new(1); EncoderParameters encoderParameters = new(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L); encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L);
if (string.IsNullOrEmpty(imageCodecInfo.FilenameExtension)) if (string.IsNullOrEmpty(imageCodecInfo.FilenameExtension))
@ -111,7 +116,8 @@ public class C_Resize
{ {
(ImageCodecInfo, EncoderParameters, string) result; (ImageCodecInfo, EncoderParameters, string) result;
ImageFormat imageFormat = ImageFormat.Png; ImageFormat imageFormat = ImageFormat.Png;
ImageCodecInfo imageCodecInfo = (from l in ImageCodecInfo.GetImageEncoders() where l.FormatID == imageFormat.Guid select l).First(); ImageCodecInfo[] imageCodecInfoCollection = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo imageCodecInfo = (from l in imageCodecInfoCollection where l.FormatID == imageFormat.Guid select l).First();
EncoderParameters encoderParameters = new(1); EncoderParameters encoderParameters = new(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L); encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L);
if (string.IsNullOrEmpty(imageCodecInfo.FilenameExtension)) if (string.IsNullOrEmpty(imageCodecInfo.FilenameExtension))
@ -135,7 +141,8 @@ public class C_Resize
".tiff" => ImageFormat.Tiff, ".tiff" => ImageFormat.Tiff,
_ => throw new Exception(), _ => throw new Exception(),
}; };
ImageCodecInfo imageCodecInfo = (from l in ImageCodecInfo.GetImageEncoders() where l.FormatID == imageFormat.Guid select l).First(); ImageCodecInfo[] imageCodecInfoCollection = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo imageCodecInfo = (from l in imageCodecInfoCollection where l.FormatID == imageFormat.Guid select l).First();
EncoderParameters encoderParameters = new(1); EncoderParameters encoderParameters = new(1);
// encoderParameters.Param[0] = New EncoderParameter(Encoder.Quality, CType(75L, Int32)) 'Default // encoderParameters.Param[0] = New EncoderParameter(Encoder.Quality, CType(75L, Int32)) 'Default
// encoderParameters.Param[0] = New EncoderParameter(Encoder.Quality, CType(95L, Int32)) 'Paint // encoderParameters.Param[0] = New EncoderParameter(Encoder.Quality, CType(95L, Int32)) 'Paint
@ -424,8 +431,8 @@ public class C_Resize
result = Shared.Models.Stateless.Methods.IFileHolder.Get(Path.Combine(AngleBracketCollection[0].Replace("<>", _PropertyConfiguration.ResultContent), fileName)); result = Shared.Models.Stateless.Methods.IFileHolder.Get(Path.Combine(AngleBracketCollection[0].Replace("<>", _PropertyConfiguration.ResultContent), fileName));
else else
{ {
(string directoryName, _) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
result = Shared.Models.Stateless.Methods.IFileHolder.Get(Path.Combine(cResultsFullGroupDirectory, _PropertyConfiguration.ResultContent, directoryName, fileName)); result = Shared.Models.Stateless.Methods.IFileHolder.Get(Path.Combine(cResultsFullGroupDirectory, _PropertyConfiguration.ResultContent, cei.Combined, fileName));
} }
return result; return result;
} }
@ -436,14 +443,36 @@ public class C_Resize
public FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, Item item, bool outputResolutionHasNumber, int id) => public FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, Item item, bool outputResolutionHasNumber, int id) =>
GetResizedFileHolder(cResultsFullGroupDirectory, item.FilePath, outputResolutionHasNumber, $"{id}{item.FilePath.ExtensionLowered}"); GetResizedFileHolder(cResultsFullGroupDirectory, item.FilePath, outputResolutionHasNumber, $"{id}{item.FilePath.ExtensionLowered}");
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
{
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, fileInfo.FullName);
fileInfo.Refresh();
}
}
}
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(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;
string[] changesFrom = [nameof(A_Property), nameof(B_Metadata)]; string[] changesFrom = [nameof(A_Property), nameof(B_Metadata)];
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
(_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath); CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
FileInfo fileInfo = new(Path.Combine(_FileGroups[_PropertyConfiguration.ResultSingleton][directoryIndex], $"{mappingFromItem.FilePath.NameWithoutExtension}{mappingFromItem.FilePath.ExtensionLowered}.json")); string fileName = $"{mappingFromItem.FilePath.NameWithoutExtension}{mappingFromItem.FilePath.ExtensionLowered}.json";
string directory = _ResultSingletonFileGroups[0][cei.Enum][cei.Index];
FileInfo fileInfo = new(Path.Combine(directory, fileName));
MoveIf(fileName, cei, directory, fileInfo);
if (_ForceResizeLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) if (_ForceResizeLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
{ {
File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName);

View File

@ -4,12 +4,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Resize</PackageId> <PackageId>Phares.View.by.Distance.Resize</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -35,7 +35,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" /> <PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> <PackageReference Include="System.Text.Json" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -34,17 +34,15 @@ public class Configuration
} }
} }
private static Models.Configuration Get(Configuration? configuration) private static Models.Configuration Get(Configuration? configuration, Property.Models.Configuration propertyConfiguration)
{ {
Models.Configuration result; Models.Configuration result;
if (configuration is null) throw new NullReferenceException(nameof(configuration)); if (configuration is null) throw new NullReferenceException(nameof(configuration));
if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat)); if (configuration.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat));
if (configuration.PropertyConfiguration is null) throw new NullReferenceException(nameof(configuration.PropertyConfiguration)); result = new(propertyConfiguration,
result = new( configuration.IgnoreExtensions,
configuration.IgnoreExtensions, configuration.PersonBirthdayFormat);
configuration.PersonBirthdayFormat,
configuration.PropertyConfiguration);
return result; return result;
} }
@ -66,7 +64,7 @@ public class Configuration
#pragma warning restore IL3050, IL2026 #pragma warning restore IL3050, IL2026
} }
PreVerify(configurationRoot, configuration); PreVerify(configurationRoot, configuration);
result = Get(configuration); result = Get(configuration, propertyConfiguration);
return result; return result;
} }

View File

@ -13,10 +13,9 @@ public class Configuration
public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration; public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration;
[JsonConstructor] [JsonConstructor]
public Configuration( public Configuration(Property.Models.Configuration propertyConfiguration,
string[] ignoreExtensions, string[] ignoreExtensions,
string personBirthdayFormat, string personBirthdayFormat)
Property.Models.Configuration propertyConfiguration)
{ {
IgnoreExtensions = ignoreExtensions; IgnoreExtensions = ignoreExtensions;
PersonBirthdayFormat = personBirthdayFormat; PersonBirthdayFormat = personBirthdayFormat;

View File

@ -4,13 +4,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<UserSecretsId>b3bbcc69-1439-4e86-9bbf-75c8e8839cc0</UserSecretsId> <UserSecretsId>b3bbcc69-1439-4e86-9bbf-75c8e8839cc0</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Set.Created.Date</PackageId> <PackageId>Phares.View.by.Distance.Set.Created.Date</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>8.0.101.1</Version> <Version>9.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -35,9 +35,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Metadata\Metadata.csproj" /> <ProjectReference Include="..\Metadata\Metadata.csproj" />

View File

@ -22,7 +22,7 @@ public class SetCreatedDate
private readonly IsEnvironment _IsEnvironment; private readonly IsEnvironment _IsEnvironment;
private readonly IConfigurationRoot _ConfigurationRoot; private readonly IConfigurationRoot _ConfigurationRoot;
private readonly Property.Models.Configuration _PropertyConfiguration; private readonly Property.Models.Configuration _PropertyConfiguration;
private readonly ReadOnlyDictionary<string, ReadOnlyCollection<string>> _FileGroups; private readonly ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> _FileGroups;
public SetCreatedDate(List<string> args, ILogger<Program> logger, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) public SetCreatedDate(List<string> args, ILogger<Program> logger, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{ {

View File

@ -0,0 +1,23 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public record CombinedEnumAndIndex(string Combined,
byte Enum,
int Index)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, CombinedEnumAndIndexSourceGenerationContext.Default.CombinedEnumAndIndex);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(CombinedEnumAndIndex))]
internal partial class CombinedEnumAndIndexSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -4,7 +4,7 @@ namespace View_by_Distance.Shared.Models;
public record Datum( public record Datum(
[property: JsonPropertyName("accessRuleIds")] IReadOnlyList<object> AccessRuleIds, [property: JsonPropertyName("accessRuleIds")] IReadOnlyList<object> AccessRuleIds,
[property: JsonPropertyName("childAssetTypeInfo")] IReadOnlyList<object> ChildAssetTypeInfo, [property: JsonPropertyName("childAssetTyceinfo")] IReadOnlyList<object> ChildAssetTyceinfo,
[property: JsonPropertyName("contentProperties")] ContentProperties ContentProperties, [property: JsonPropertyName("contentProperties")] ContentProperties ContentProperties,
[property: JsonPropertyName("createdBy")] string CreatedBy, [property: JsonPropertyName("createdBy")] string CreatedBy,
[property: JsonPropertyName("createdDate")] DateTime CreatedDate, [property: JsonPropertyName("createdDate")] DateTime CreatedDate,

View File

@ -6,12 +6,12 @@ namespace View_by_Distance.Shared.Models;
public record ExifDirectory(AviDirectory[] AviDirectories, public record ExifDirectory(AviDirectory[] AviDirectories,
ExifDirectoryBase[] ExifBaseDirectories, ExifDirectoryBase[] ExifBaseDirectories,
FileMetadataDirectory[] FileMetadataDirectories, FileMetadataDirectory[] FileMetadataDirectories,
FilePath FilePath,
GifHeaderDirectory[] GifHeaderDirectories, GifHeaderDirectory[] GifHeaderDirectories,
GpsDirectory[] GpsDirectories, GpsDirectory[] GpsDirectories,
int? Height, int? Height,
JpegDirectory[] JpegDirectories, JpegDirectory[] JpegDirectories,
MakernoteDirectory[] MakernoteDirectories, MakernoteDirectory[] MakernoteDirectories,
string OriginalFileName,
PhotoshopDirectory[] PhotoshopDirectories, PhotoshopDirectory[] PhotoshopDirectories,
PngDirectory[] PngDirectories, PngDirectory[] PngDirectories,
QuickTimeMovieHeaderDirectory[] QuickTimeMovieHeaderDirectories, QuickTimeMovieHeaderDirectory[] QuickTimeMovieHeaderDirectories,

View File

@ -40,8 +40,14 @@ public record class FaceDistance : Properties.IFaceDistance
public override string ToString() public override string ToString()
{ {
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); string result = JsonSerializer.Serialize(this, FaceDistanceSourceGenerationContext.Default.FaceDistance);
return result; return result;
} }
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(FaceDistance))]
internal partial class FaceDistanceSourceGenerationContext : JsonSerializerContext
{
} }

View File

@ -1,3 +1,4 @@
using System.Collections.ObjectModel;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Stateless.Methods; using View_by_Distance.Shared.Models.Stateless.Methods;
@ -83,6 +84,33 @@ public record FilePath(long CreationTicks,
return result; return result;
} }
public static ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>> GetKeyValuePairs(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{
Dictionary<int, ReadOnlyCollection<FilePath>> results = [];
List<FilePath>? collection;
Dictionary<int, List<FilePath>> keyValuePairs = [];
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{
if (filePaths.Count == 0)
continue;
foreach (FilePath filePath in filePaths)
{
if (filePath.Id is null)
continue;
if (!keyValuePairs.TryGetValue(filePath.Id.Value, out collection))
{
keyValuePairs.Add(filePath.Id.Value, []);
if (!keyValuePairs.TryGetValue(filePath.Id.Value, out collection))
throw new Exception();
}
collection.Add(filePath);
}
}
foreach (KeyValuePair<int, List<FilePath>> keyValuePair in keyValuePairs)
results.Add(keyValuePair.Key, new(keyValuePair.Value));
return results.AsReadOnly();
}
} }
[JsonSourceGenerationOptions(WriteIndented = true)] [JsonSourceGenerationOptions(WriteIndented = true)]

View File

@ -0,0 +1,33 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public sealed record Identifier(string[] DirectoryNames,
string Extension,
bool? HasDateTimeOriginal,
int Id,
long Length,
string PaddedId,
long Ticks)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, IdentifierSourceGenerationContext.Default.Identifier);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Identifier))]
public partial class IdentifierSourceGenerationContext : JsonSerializerContext
{
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Identifier[]))]
public partial class IdentifierCollectionSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -5,11 +5,33 @@ namespace View_by_Distance.Shared.Models;
public record ImmichAsset([property: JsonPropertyName("id")] string Id, public record ImmichAsset([property: JsonPropertyName("id")] string Id,
[property: JsonPropertyName("deviceAssetId")] string DeviceAssetId, [property: JsonPropertyName("deviceAssetId")] string DeviceAssetId,
// [property: JsonPropertyName("ownerId")] string OwnerId,
// [property: JsonPropertyName("deviceId")] string DeviceId,
// [property: JsonPropertyName("type")] string Type,
[property: JsonPropertyName("originalPath")] string OriginalPath, [property: JsonPropertyName("originalPath")] string OriginalPath,
[property: JsonPropertyName("previewPath")] string PreviewPath, // [property: JsonPropertyName("fileCreatedAt")] DateTime FileCreatedAt,
[property: JsonPropertyName("isFavorite")] bool IsFavorite, // [property: JsonPropertyName("fileModifiedAt")] DateTime FileModifiedAt,
[property: JsonPropertyName("thumbnailPath")] string ThumbnailPath, // [property: JsonPropertyName("isFavorite")] bool IsFavorite,
[property: JsonPropertyName("thumbhash")] string Thumbhash) // [property: JsonPropertyName("duration")] string? Duration,
// [property: JsonPropertyName("encodedVideoPath")] string EncodedVideoPath,
// [property: JsonPropertyName("checksum")] string Checksum,
// [property: JsonPropertyName("isVisible")] bool IsVisible,
// [property: JsonPropertyName("livePhotoVideoId")] object? LivePhotoVideoId,
// [property: JsonPropertyName("updatedAt")] DateTime UpdatedAt,
// [property: JsonPropertyName("createdAt")] DateTime CreatedAt,
// [property: JsonPropertyName("isArchived")] bool IsArchived,
[property: JsonPropertyName("originalFileName")] string OriginalFileName,
// [property: JsonPropertyName("sidecarPath")] object? SidecarPath,
// [property: JsonPropertyName("thumbhash")] string Thumbhash,
// [property: JsonPropertyName("isOffline")] bool IsOffline,
// [property: JsonPropertyName("libraryId")] string LibraryId,
// [property: JsonPropertyName("isExternal")] bool IsExternal,
// [property: JsonPropertyName("deletedAt")] object? DeletedAt,
// [property: JsonPropertyName("localDateTime")] DateTime LocalDateTime,
// [property: JsonPropertyName("stackId")]? object? StackId,
[property: JsonPropertyName("duplicateId")] string? DuplicateId,
// [property: JsonPropertyName("status")] string Status,
[property: JsonPropertyName("path")] string Path)
{ {
public override string ToString() public override string ToString()

View File

@ -9,6 +9,7 @@ public class Item : Properties.IItem
protected List<Face> _Faces; protected List<Face> _Faces;
protected readonly bool? _FileSizeChanged; protected readonly bool? _FileSizeChanged;
protected readonly FilePath _FilePath; protected readonly FilePath _FilePath;
protected bool? _IsArchive;
protected bool? _IsNotUniqueAndNeedsReview; protected bool? _IsNotUniqueAndNeedsReview;
protected bool _IsUniqueFileName; protected bool _IsUniqueFileName;
protected bool _IsValidImageFormatExtension; protected bool _IsValidImageFormatExtension;
@ -21,6 +22,7 @@ public class Item : Properties.IItem
public List<Face> Faces => _Faces; public List<Face> Faces => _Faces;
public bool? FileSizeChanged => _FileSizeChanged; public bool? FileSizeChanged => _FileSizeChanged;
public FilePath FilePath => _FilePath; public FilePath FilePath => _FilePath;
public bool? IsArchive => _IsArchive;
public bool? IsNotUniqueAndNeedsReview => _IsNotUniqueAndNeedsReview; public bool? IsNotUniqueAndNeedsReview => _IsNotUniqueAndNeedsReview;
public bool IsUniqueFileName => _IsUniqueFileName; public bool IsUniqueFileName => _IsUniqueFileName;
public bool IsValidImageFormatExtension => _IsValidImageFormatExtension; public bool IsValidImageFormatExtension => _IsValidImageFormatExtension;
@ -32,11 +34,12 @@ public class Item : Properties.IItem
public FileHolder SourceDirectoryFileHolder => _SourceDirectoryFileHolder; public FileHolder SourceDirectoryFileHolder => _SourceDirectoryFileHolder;
[JsonConstructor] [JsonConstructor]
public Item(List<Face> faces, FilePath filePath, bool? fileSizeChanged, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, bool? lastWriteTimeChanged, bool? moved, Property? property, string relativePath, FileHolder? resizedFileHolder, FileHolder sourceDirectoryFileHolder) public Item(List<Face> faces, FilePath filePath, bool? fileSizeChanged, bool? isArchive, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, bool? lastWriteTimeChanged, bool? moved, Property? property, string relativePath, FileHolder? resizedFileHolder, FileHolder sourceDirectoryFileHolder)
{ {
_Faces = faces; _Faces = faces;
_FilePath = filePath; _FilePath = filePath;
_FileSizeChanged = fileSizeChanged; _FileSizeChanged = fileSizeChanged;
_IsArchive = isArchive;
_IsNotUniqueAndNeedsReview = isNotUniqueAndNeedsReview; _IsNotUniqueAndNeedsReview = isNotUniqueAndNeedsReview;
_IsUniqueFileName = isUniqueFileName; _IsUniqueFileName = isUniqueFileName;
_IsValidImageFormatExtension = isValidImageFormatExtension; _IsValidImageFormatExtension = isValidImageFormatExtension;
@ -48,18 +51,19 @@ public class Item : Properties.IItem
_SourceDirectoryFileHolder = sourceDirectoryFileHolder; _SourceDirectoryFileHolder = sourceDirectoryFileHolder;
} }
public Item(FilePath filePath, FileHolder sourceDirectoryFileHolder, string relativePath, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, Property? property, bool? abandoned, bool? fileSizeChanged, bool? lastWriteTimeChanged) : public static Item Get(FilePath filePath, FileHolder sourceDirectoryFileHolder, string relativePath, bool? isArchive, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, Property? property, bool? abandoned, bool? fileSizeChanged, bool? lastWriteTimeChanged)
this([], filePath, fileSizeChanged, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, lastWriteTimeChanged, null, property, relativePath, null, sourceDirectoryFileHolder)
{ {
Item result;
if (relativePath.EndsWith(".json")) if (relativePath.EndsWith(".json"))
throw new ArgumentException("Can not be a *.json file!"); throw new ArgumentException("Can not be a *.json file!");
if (filePath is not null && filePath.ExtensionLowered is ".json") if (filePath.ExtensionLowered is ".json")
throw new ArgumentException("Can not be a *.json file!"); throw new ArgumentException("Can not be a *.json file!");
result = new([], filePath, fileSizeChanged, isArchive, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, lastWriteTimeChanged, null, property, relativePath, null, sourceDirectoryFileHolder);
return result;
} }
public Item(FilePath filePath, FileHolder sourceDirectoryFileHolder, string relativePath, bool isValidImageFormatExtension) : public static Item Get(FilePath filePath, FileHolder sourceDirectoryFileHolder, string relativePath, bool isValidImageFormatExtension) =>
this(filePath, sourceDirectoryFileHolder, relativePath, null, false, isValidImageFormatExtension, null, null, null, null) Get(filePath, sourceDirectoryFileHolder, relativePath, null, null, false, isValidImageFormatExtension, null, null, null, null);
{ }
public override string ToString() public override string ToString()
{ {

View File

@ -36,9 +36,8 @@ public class Mapping : Properties.IMapping
_SortingContainer = sortingContainer; _SortingContainer = sortingContainer;
} }
public Mapping(FilePath filePath, MappingFromFilterPost mappingFromFilterPost, MappingFromFilterPre mappingFromFilterPre, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection) : public static Mapping Get(FilePath filePath, MappingFromFilterPost mappingFromFilterPost, MappingFromFilterPre mappingFromFilterPre, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection) =>
this(null, filePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, null, mappingFromPhotoPrismCollection, null, null) new(null, filePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, null, mappingFromPhotoPrismCollection, null, null);
{ }
public override string ToString() public override string ToString()
{ {

View File

@ -7,6 +7,7 @@ public record MappingFromItem(DateTime[] ContainerDateTimes,
DateTime? DateTimeDigitized, DateTime? DateTimeDigitized,
DateTime? DateTimeOriginal, DateTime? DateTimeOriginal,
int Id, int Id,
bool? IsArchive,
FilePath FilePath, FilePath FilePath,
bool? IsWrongYear, bool? IsWrongYear,
string[] Keywords, string[] Keywords,
@ -35,7 +36,7 @@ public record MappingFromItem(DateTime[] ContainerDateTimes,
List<DateTime> dateTimes = item.Property.GetDateTimes(); List<DateTime> dateTimes = item.Property.GetDateTimes();
DateTime minimumDateTime = Stateless.Methods.IProperty.GetMinimumDateTime(item.Property); DateTime minimumDateTime = Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
(bool? isWrongYear, _) = Stateless.Methods.IProperty.IsWrongYear(item.FilePath, item.Property.DateTimeOriginal, dateTimes); (bool? isWrongYear, _) = Stateless.Methods.IProperty.IsWrongYear(item.FilePath, item.Property.DateTimeOriginal, dateTimes);
result = new(containerDateTimes, item.Property.DateTimeDigitized, item.Property.DateTimeOriginal, item.Property.Id.Value, item.FilePath, isWrongYear, item.Property.Keywords ?? [], minimumDateTime, item.Property.Model, item.RelativePath, resizedFileHolder); result = new(containerDateTimes, item.Property.DateTimeDigitized, item.Property.DateTimeOriginal, item.Property.Id.Value, item.IsArchive, item.FilePath, isWrongYear, item.Property.Keywords ?? [], minimumDateTime, item.Property.Model, item.RelativePath, resizedFileHolder);
return result; return result;
} }

View File

@ -3,23 +3,19 @@ using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class PersonBirthday : Properties.IPersonBirthday public record PersonBirthday(DateTime Value)
{ {
protected readonly DateTime _Value; // {{1}}SingletonValue
public DateTime Value => _Value; // {{1}}SingletonValue
[JsonConstructor]
public PersonBirthday
(
DateTime value
) => _Value = value; // {{1}}SingletonValue
public override string ToString() public override string ToString()
{ {
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); string result = JsonSerializer.Serialize(this, PersonBirthdaySourceGenerationContext.Default.PersonBirthday);
return result; return result;
} // ... }
}
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(PersonBirthday))]
public partial class PersonBirthdaySourceGenerationContext : JsonSerializerContext
{
} }

View File

@ -4,53 +4,57 @@ using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class PersonContainer : Properties.IPersonContainer public record PersonContainer(int? ApproximateYears,
PersonBirthday[]? Birthdays,
ReadOnlyCollection<FilePath> DisplayDirectoryAllFilePaths,
string DisplayDirectoryName,
long? Key,
PersonDirectory? PersonDirectory)
{ {
public int? ApproximateYears { init; get; }
public PersonBirthday[]? Birthdays { init; get; }
public ReadOnlyCollection<FilePath> DisplayDirectoryAllFilePaths { init; get; }
public string DisplayDirectoryName { init; get; }
public long? Key { init; get; }
public bool? KeyIsMaxBirthday { init; get; }
public PersonDirectory? PersonDirectory { init; get; }
[JsonConstructor]
public PersonContainer(int? approximateYears, PersonBirthday[]? birthdays, ReadOnlyCollection<FilePath> displayDirectoryAllFiles, string displayDirectoryName, long? key, PersonDirectory? personDirectory)
{
ApproximateYears = approximateYears;
Birthdays = birthdays;
DisplayDirectoryAllFilePaths = displayDirectoryAllFiles;
DisplayDirectoryName = displayDirectoryName;
Key = key;
PersonDirectory = personDirectory;
KeyIsMaxBirthday = birthdays is null || key is null ? null : key.Value == birthdays.First().Value.Ticks;
}
public PersonContainer(char[] personCharacters, PersonBirthday birthday, string displayDirectoryName, PersonDirectory personDirectory) :
this(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), [birthday], new([]), displayDirectoryName, birthday.Value.Ticks, personDirectory)
{ }
public PersonContainer(int? approximateYears, PersonBirthday birthdays, string displayDirectoryName, long key) :
this(approximateYears, [birthdays], new([]), displayDirectoryName, key, null)
{ }
public PersonContainer(int? approximateYears, PersonBirthday birthdays, PersonDirectory? personDirectory, string displayDirectoryName, long key) :
this(approximateYears, [birthdays], new([]), displayDirectoryName, key, personDirectory)
{ }
public PersonContainer(int? approximateYears, ReadOnlyCollection<FilePath> displayDirectoryAllFiles, string displayDirectoryName, PersonDirectory? personDirectory) :
this(approximateYears, null, displayDirectoryAllFiles, displayDirectoryName, null, personDirectory)
{ }
public PersonContainer(int? approximateYears, PersonBirthday[]? birthdays, ReadOnlyCollection<FilePath> displayDirectoryAllFiles, string displayDirectoryName, long? key) :
this(approximateYears, birthdays, displayDirectoryAllFiles, displayDirectoryName, key, null)
{ }
public override string ToString() public override string ToString()
{ {
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); string result = JsonSerializer.Serialize(this, PersonContainerSourceGenerationContext.Default.PersonContainer);
return result; return result;
} }
public static PersonContainer Get(int? approximateYears, PersonBirthday[]? birthdays, ReadOnlyCollection<FilePath> displayDirectoryAllFilePaths, string displayDirectoryName, long? key, PersonDirectory? personDirectory) =>
new(approximateYears, birthdays, displayDirectoryAllFilePaths, displayDirectoryName, key, personDirectory);
public static PersonContainer Get(char[] personCharacters, PersonBirthday birthday, string displayDirectoryName, PersonDirectory personDirectory) =>
new(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), [birthday], new([]), displayDirectoryName, birthday.Value.Ticks, personDirectory);
public static PersonContainer Get(int? approximateYears, PersonBirthday birthdays, string displayDirectoryName, long key) =>
new(approximateYears, [birthdays], new([]), displayDirectoryName, key, null);
public static PersonContainer Get(int? approximateYears, PersonBirthday birthdays, PersonDirectory? personDirectory, string displayDirectoryName, long key) =>
new(approximateYears, [birthdays], new([]), displayDirectoryName, key, personDirectory);
public static PersonContainer Get(int? approximateYears, ReadOnlyCollection<FilePath> displayDirectoryAllFilePaths, string displayDirectoryName, PersonDirectory? personDirectory) =>
new(approximateYears, null, displayDirectoryAllFilePaths, displayDirectoryName, null, personDirectory);
public static PersonContainer Get(int? approximateYears, PersonBirthday[]? birthdays, ReadOnlyCollection<FilePath> displayDirectoryAllFilePaths, string displayDirectoryName, long? key) =>
new(approximateYears, birthdays, displayDirectoryAllFilePaths, displayDirectoryName, key, null);
public static bool? IsKeyIsMaxBirthday(PersonContainer personContainer) =>
personContainer.Birthdays is null || personContainer.Key is null ? null : personContainer.Key.Value == personContainer.Birthdays.First().Value.Ticks;
public static ReadOnlyDictionary<long, PersonContainer> Extract(ReadOnlyCollection<PersonContainer> personContainers)
{
Dictionary<long, PersonContainer> results = [];
foreach (PersonContainer personContainer in personContainers)
{
if (personContainer.Key is null || results.ContainsKey(personContainer.Key.Value))
continue;
results.Add(personContainer.Key.Value, personContainer);
}
return results.AsReadOnly();
}
}
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(PersonContainer))]
public partial class PersonContainerSourceGenerationContext : JsonSerializerContext
{
} }

View File

@ -1,4 +1,5 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
@ -7,8 +8,14 @@ public record PersonDirectory(char Char, string Group, char Status, char Sex, ch
public override string ToString() public override string ToString()
{ {
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); string result = JsonSerializer.Serialize(this, PersonDirectorySourceGenerationContext.Default.PersonDirectory);
return result; return result;
} }
}
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(PersonDirectory))]
public partial class PersonDirectorySourceGenerationContext : JsonSerializerContext
{
} }

View File

@ -6,6 +6,7 @@ public interface IItem
public bool? FileSizeChanged { get; } public bool? FileSizeChanged { get; }
public List<Face> Faces { get; } public List<Face> Faces { get; }
public FilePath FilePath { get; } public FilePath FilePath { get; }
public bool? IsArchive { get; }
public bool? IsNotUniqueAndNeedsReview { get; } public bool? IsNotUniqueAndNeedsReview { get; }
public bool IsUniqueFileName { get; } public bool IsUniqueFileName { get; }
public bool IsValidImageFormatExtension { get; } public bool IsValidImageFormatExtension { get; }

View File

@ -26,7 +26,7 @@ internal abstract class Container
continue; continue;
results.Add(item); results.Add(item);
} }
return container.Items.Count == results.Count ? container.Items : new(results); 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) private static List<Models.FilePair> GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
@ -71,7 +71,23 @@ internal abstract class Container
return result; return result;
} }
private static void ParallelFor(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string extension, int rootDirectoryLength, Models.FilePair filePair, List<FilePair> results) 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(); dlibDotNet?.Tick();
bool abandoned = false; bool abandoned = false;
@ -82,6 +98,7 @@ internal abstract class Container
bool? fileSizeChanged = property is not null ? property.FileSize != filePath.Length : null; bool? fileSizeChanged = property is not null ? property.FileSize != filePath.Length : null;
bool isValidImageFormatExtension = propertyConfiguration.ValidImageFormatExtensions.Contains(filePath.ExtensionLowered); 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? 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 is not null)
{ {
if (shouldIgnore.Value) if (shouldIgnore.Value)
@ -107,20 +124,24 @@ internal abstract class Container
else else
{ {
string fileName = Path.GetFileName(filePair.Path); string fileName = Path.GetFileName(filePair.Path);
(string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
sourceDirectoryFileHolder = IFileHolder.Get(Path.Combine(aPropertySingletonDirectory, directoryName, $"{fileName}{extension}")); 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) 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.SetCreationTime(sourceDirectoryFileHolder.FullName, new(filePath.LastWriteTicks));
File.SetLastWriteTime(sourceDirectoryFileHolder.FullName, sourceDirectoryFileHolder.LastWriteTime.Value); File.SetLastWriteTime(sourceDirectoryFileHolder.FullName, sourceDirectoryFileHolder.LastWriteTime.Value);
} }
Models.Item item = new(filePath, sourceDirectoryFileHolder, relativePath, filePair.IsNotUniqueAndNeedsReview, filePair.IsUnique, isValidImageFormatExtension, property, abandoned, fileSizeChanged, lastWriteTimeChanged); Models.Item item = Models.Item.Get(filePath, sourceDirectoryFileHolder, relativePath, isArchive, filePair.IsNotUniqueAndNeedsReview, filePair.IsUnique, isValidImageFormatExtension, property, abandoned, fileSizeChanged, lastWriteTimeChanged);
lock (results) lock (results)
results.Add(new(filePair.IsUnique, filePair.Collection, filePath, item)); results.Add(new(filePair.IsUnique, filePair.Collection, filePath, item));
} }
private static List<FilePair> GetFilePairs(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter) 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 = []; List<FilePair> results = [];
const string extension = ".json"; const string extension = ".json";
@ -128,11 +149,11 @@ internal abstract class Container
int filesCollectionDirectoryLength = filesCollectionDirectory.Length; int filesCollectionDirectoryLength = filesCollectionDirectory.Length;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
List<Models.FilePair> filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filePathsCollection); List<Models.FilePair> filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filePathsCollection);
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, extension, filesCollectionDirectoryLength, filePairs[i], results)); _ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, extension, filesCollectionDirectoryLength, splatNineIdentifiers, filePairs[i], results));
return results; return results;
} }
private static (int, Models.Container[]) GetContainers(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter) 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 = []; List<Models.Container> results = [];
string directory; string directory;
@ -156,7 +177,7 @@ internal abstract class Container
throw new Exception(); throw new Exception();
} }
} }
List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filePathsCollection, directorySearchFilter); List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
foreach (FilePair filePair in filePairs) foreach (FilePair filePair in filePairs)
{ {
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items)) if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
@ -177,15 +198,15 @@ internal abstract class Container
return (filePairs.Count, results.ToArray()); return (filePairs.Count, results.ToArray());
} }
internal static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) 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; Models.Container[] results;
const string directorySearchFilter = "*"; const string directorySearchFilter = "*";
(_, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filePathsCollection, directorySearchFilter); (_, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
return new(results); return results.AsReadOnly();
} }
internal static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) internal static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory)
{ {
int count; int count;
Models.Container[] results; Models.Container[] results;
@ -195,7 +216,7 @@ internal abstract class Container
const string directorySearchFilter = "*"; const string directorySearchFilter = "*";
ReadOnlyCollection<string[]> filesCollection = IDirectory.GetFilesCollection(propertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage); ReadOnlyCollection<string[]> filesCollection = IDirectory.GetFilesCollection(propertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection); ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, propertyConfiguration.RootDirectory, filePathsCollection, directorySearchFilter); (count, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, propertyConfiguration.RootDirectory, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
return (count, results); return (count, results);
} }
@ -275,7 +296,7 @@ internal abstract class Container
results.Add(item); results.Add(item);
} }
} }
return new(results); return results.AsReadOnly();
} }
} }

View File

@ -18,12 +18,17 @@ public interface IContainer
(int, Models.Container[]) TestStatic_GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) => (int, Models.Container[]) TestStatic_GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
GetContainers(propertyConfiguration, aPropertySingletonDirectory); GetContainers(propertyConfiguration, aPropertySingletonDirectory);
static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) => static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory); GetContainers(propertyConfiguration, null, aPropertySingletonDirectory);
ReadOnlyCollection<Models.Container> TestStatic_GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) => (int, Models.Container[]) TestStatic_GetContainers(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filePathsCollection); GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) => static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
Container.GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filePathsCollection); 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) => List<int> TestStatic_GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers); GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);

View File

@ -20,24 +20,24 @@ public interface IDirectory
static ReadOnlyCollection<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) => static ReadOnlyCollection<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) =>
XDirectory.GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage); XDirectory.GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
ReadOnlyCollection<ReadOnlyCollection<FilePath>> TestStatic_GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) => ReadOnlyCollection<ReadOnlyCollection<FilePath>> TestStatic_GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string fileSearchFilter, string directory, bool useCeilingAverage) =>
GetFilePathCollections(propertyConfiguration, directory, directorySearchFilter, fileSearchFilter, useCeilingAverage); GetFilePathCollections(propertyConfiguration, directorySearchFilter, fileSearchFilter, directory, useCeilingAverage);
static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) => static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string fileSearchFilter, string directory, bool useCeilingAverage) =>
XDirectory.GetFilePathCollections(propertyConfiguration, directory, directorySearchFilter, fileSearchFilter, useCeilingAverage); XDirectory.GetFilePathCollections(propertyConfiguration, directorySearchFilter, fileSearchFilter, directory, useCeilingAverage);
void TestStatic_MoveFiles(List<string> files, string find, string replace) => void TestStatic_MoveFiles(List<string> files, string find, string replace) =>
MoveFiles(files, find, replace); MoveFiles(files, find, replace);
static void MoveFiles(List<string> files, string find, string replace) => static void MoveFiles(List<string> files, string find, string replace) =>
XDirectory.MoveFiles(files, find, replace); XDirectory.MoveFiles(files, find, replace);
(string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyCollection<string>> fileGroups, Action? tick) => (string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
GetToDoCollection(propertyConfiguration, filePathsCollection, fileGroups, tick); GetToDoCollection(propertyConfiguration, filePathsCollection, fileGroups, tick);
static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyCollection<string>> fileGroups, Action? tick) => static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates: false, ifCanUseId: true, filePathsCollection, fileGroups, tick); XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates: false, ifCanUseId: true, filePathsCollection, fileGroups, tick);
(string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyCollection<string>> fileGroups, Action? tick) => (string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, fileGroups, tick); GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, fileGroups, tick);
static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyCollection<string>> fileGroups, Action? tick) => static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, fileGroups, tick); XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, fileGroups, tick);
List<string> TestStatic_CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) => List<string> TestStatic_CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) =>

View File

@ -62,14 +62,14 @@ public interface IPath
static string GetDirectory(string sourceDirectory, int level, string directoryName) => static string GetDirectory(string sourceDirectory, int level, string directoryName) =>
XPath.GetDirectory(sourceDirectory, level, directoryName); XPath.GetDirectory(sourceDirectory, level, directoryName);
(string, int) TestStatic_GetDirectoryNameAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath) => CombinedEnumAndIndex TestStatic_GetCombinedEnumAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
GetDirectoryNameAndIndex(propertyConfiguration, filePath); GetCombinedEnumAndIndex(propertyConfiguration, filePath);
static (string, int) GetDirectoryNameAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath) => static CombinedEnumAndIndex GetCombinedEnumAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
XPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); XPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
ReadOnlyDictionary<string, ReadOnlyCollection<string>> TestStatic_GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups) => ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> TestStatic_GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups) =>
GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, jsonGroups); GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, jsonGroups);
static ReadOnlyDictionary<string, 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);
} }

View File

@ -3,7 +3,7 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class MetadataFileCollection internal abstract class MetadataFileCollection
{ {
internal static Dictionary<string, List<KeyValuePair<string, string>>> GetDefaultValue() => new(); // {{1}}SingletonValue internal static Dictionary<string, List<KeyValuePair<string, string>>> GetDefaultValue() => []; // {{1}}SingletonValue
// ... // ...

View File

@ -95,11 +95,9 @@ internal abstract class PersonBirthday
foreach (string personKeyDirectory in personKeyDirectories) foreach (string personKeyDirectory in personKeyDirectories)
{ {
personKeyFormatted = Path.GetFileName(personKeyDirectory); personKeyFormatted = Path.GetFileName(personKeyDirectory);
if (!DateTime.TryParseExact(personKeyFormatted, "MM.dd.yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthday)) if (DateTime.TryParseExact(personKeyFormatted, "MM.dd.yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthday))
personBirthday = IPersonBirthday.GetPersonBirthday(personBirthdayFormat, personKeyFormatted);
else
// (personBirthday, personKeyFormatted) = Person.Get(personBirthdayFormat, personDisplayDirectory, personKeyDirectory, birthday);
continue; continue;
personBirthday = IPersonBirthday.GetPersonBirthday(personBirthdayFormat, personKeyFormatted);
if (personBirthday is null) if (personBirthday is null)
continue; continue;
if (!IPersonBirthday.IsCounterPersonBirthday(personBirthday) && ((!personKeyDirectory.Contains('#') && (personDisplayDirectoryName.Contains('~') || personDisplayDirectoryName.Contains('#'))) || (personKeyDirectory.Contains('#') && !personDisplayDirectoryName.Contains('#')))) if (!IPersonBirthday.IsCounterPersonBirthday(personBirthday) && ((!personKeyDirectory.Contains('#') && (personDisplayDirectoryName.Contains('~') || personDisplayDirectoryName.Contains('#'))) || (personKeyDirectory.Contains('#') && !personDisplayDirectoryName.Contains('#'))))

View File

@ -215,7 +215,7 @@ internal abstract class PersonContainer
else else
{ {
personDisplayDirectoryAllFilePaths = GetFilePaths(facesFileNameExtension, propertyConfiguration, personDisplayDirectory); personDisplayDirectoryAllFilePaths = GetFilePaths(facesFileNameExtension, propertyConfiguration, personDisplayDirectory);
personContainer = new(approximateYears, new(personDisplayDirectoryAllFilePaths), personDisplayDirectoryName, personDirectory); personContainer = Models.PersonContainer.Get(approximateYears, new(personDisplayDirectoryAllFilePaths), personDisplayDirectoryName, personDirectory);
results.Add(personContainer); results.Add(personContainer);
} }
} }

View File

@ -75,13 +75,15 @@ internal abstract class Property
for (int i = 0; i < int.MaxValue; i++) for (int i = 0; i < int.MaxValue; i++)
{ {
check = Path.GetDirectoryName(check); check = Path.GetDirectoryName(check);
if (string.IsNullOrEmpty(check) || check == pathRoot) if (string.IsNullOrEmpty(check))
break; break;
directoryName = Path.GetFileName(check); directoryName = Path.GetFileName(check);
directorySegments = directoryName.Split(' '); directorySegments = directoryName.Split(' ');
(result, results) = IsWrongYear(directorySegments, year); (result, results) = IsWrongYear(directorySegments, year);
if (result is not null) if (result is not null)
break; break;
if (check == pathRoot)
break;
} }
if (result is not null && !result.Value) if (result is not null && !result.Value)
break; break;

View File

@ -51,10 +51,10 @@ internal abstract partial class XDirectory
int ceilingAverage = directory[^1] == '_' || results.Count == 0 ? 0 : GetCeilingAverage(results); int ceilingAverage = directory[^1] == '_' || results.Count == 0 ? 0 : GetCeilingAverage(results);
if (useCeilingAverage) if (useCeilingAverage)
results = GetFilesCollection(results, ceilingAverage); results = GetFilesCollection(results, ceilingAverage);
return new(results); return results.AsReadOnly();
} }
internal static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) internal static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string fileSearchFilter, string directory, bool useCeilingAverage)
{ {
ReadOnlyCollection<ReadOnlyCollection<FilePath>> results; ReadOnlyCollection<ReadOnlyCollection<FilePath>> results;
ReadOnlyCollection<string[]> filesCollection = GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage); ReadOnlyCollection<string[]> filesCollection = GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
@ -319,15 +319,17 @@ internal abstract partial class XDirectory
foreach (string file in files) foreach (string file in files)
{ {
fileHolder = IFileHolder.Get(file); fileHolder = IFileHolder.Get(file);
if (propertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
continue;
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
filePaths.Add(filePath); filePaths.Add(filePath);
} }
results.Add(new(filePaths)); results.Add(new(filePaths));
} }
return new(results); return results.AsReadOnly();
} }
internal static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyCollection<string>> fileGroups, Action? tick) internal static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick)
{ {
List<(FilePath, string)> results = []; List<(FilePath, string)> results = [];
string key; string key;
@ -336,18 +338,18 @@ internal abstract partial class XDirectory
string directory; string directory;
FileInfo fileInfo; FileInfo fileInfo;
FilePath filePath; FilePath filePath;
int directoryIndex;
string paddedIdFile; string paddedIdFile;
bool wrapped = false; bool wrapped = false;
string intelligentId; string intelligentId;
CombinedEnumAndIndex cei;
bool paddedCheck = false; bool paddedCheck = false;
string fileDirectoryName; string fileDirectoryName;
List<int> distinctIds = []; List<int> distinctIds = [];
List<string> distinct = []; List<string> distinct = [];
Models.FileHolder fileHolder; Models.FileHolder fileHolder;
List<string> distinctDirectories = []; List<string> distinctDirectories = [];
ReadOnlyCollection<string>? directories;
FilePath[] sortedRecords = GetSortedRecords(filePathsCollection); FilePath[] sortedRecords = GetSortedRecords(filePathsCollection);
ReadOnlyDictionary<byte, ReadOnlyCollection<string>>? keyValuePairs;
bool isOffsetDeterministicHashCode = IId.IsOffsetDeterministicHashCode(propertyConfiguration); bool isOffsetDeterministicHashCode = IId.IsOffsetDeterministicHashCode(propertyConfiguration);
for (int i = 0; i < sortedRecords.Length; i++) for (int i = 0; i < sortedRecords.Length; i++)
{ {
@ -356,21 +358,21 @@ internal abstract partial class XDirectory
if (filePath.Name.EndsWith("len") || filePath.ExtensionLowered == ".id" || filePath.ExtensionLowered == ".lsv" || filePath.DirectoryFullPath is null) if (filePath.Name.EndsWith("len") || filePath.ExtensionLowered == ".id" || filePath.ExtensionLowered == ".lsv" || filePath.DirectoryFullPath is null)
continue; continue;
key = propertyConfiguration.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered) ? propertyConfiguration.ResultContentCollection : propertyConfiguration.ResultContent; key = propertyConfiguration.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered) ? propertyConfiguration.ResultContentCollection : propertyConfiguration.ResultContent;
if (!fileGroups.TryGetValue(key, out directories)) if (!fileGroups.TryGetValue(key, out keyValuePairs))
continue; continue;
(_, directoryIndex) = IPath.GetDirectoryNameAndIndex(propertyConfiguration, filePath); cei = IPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
fileDirectoryName = Path.GetFileName(filePath.DirectoryFullPath); fileDirectoryName = Path.GetFileName(filePath.DirectoryFullPath);
if (fileDirectoryName.Length < propertyConfiguration.ResultAllInOneSubdirectoryLength + 3 || !filePath.Name.StartsWith(fileDirectoryName)) if (fileDirectoryName.Length < propertyConfiguration.ResultAllInOneSubdirectoryLength + 3 || !filePath.Name.StartsWith(fileDirectoryName))
{ {
if (wrapped) if (wrapped)
continue; continue;
directory = directories[directoryIndex]; directory = keyValuePairs[cei.Enum][cei.Index];
} }
else else
{ {
if (!wrapped) if (!wrapped)
wrapped = true; wrapped = true;
directory = Path.Combine(directories[directoryIndex], fileDirectoryName); directory = Path.Combine(keyValuePairs[cei.Enum][cei.Index], fileDirectoryName);
} }
if (ifCanUseId && filePath.IsIntelligentIdFormat && filePath.Id is not null && filePath.DirectoryFullPath is not null) if (ifCanUseId && filePath.IsIntelligentIdFormat && filePath.Id is not null && filePath.DirectoryFullPath is not null)
{ {

Some files were not shown because too many files have changed in this diff Show More