7 Commits

Author SHA1 Message Date
f914fd3577 Tif support 2024-08-31 07:32:45 -07:00
9ebfdc8af2 Reuse count over t
FilePath over String
Support first run better
Bump
2024-07-20 10:48:26 -07:00
5b9e748ba4 FileAttributes.Hidden
Nuget Bump
2024-07-13 10:05:31 -07:00
9c253786a9 Prep for item.FilePath.HasIgnoreKeyword, item.FilePath.HasDateTimeOriginal 2024-06-17 21:41:15 -07:00
86b13dc00f Fix the errors 2024-05-27 10:05:37 -07:00
665fb8ec06 GetOneOnly 2024-05-27 09:14:59 -07:00
365df1158a Format 2024-05-27 00:04:14 -07:00
48 changed files with 452 additions and 298 deletions

1
.gitignore vendored
View File

@ -470,3 +470,4 @@ globalStorage/
Shared/.kanbn Shared/.kanbn
.Immich/immich-assets.json .Immich/immich-assets.json
Instance/.vscode/.UserSecrets/*

View File

@ -24,6 +24,6 @@
<ProjectReference Include="..\BlurHash.Core\BlurHash.Core.csproj" /> <ProjectReference Include="..\BlurHash.Core\BlurHash.Core.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -33,8 +33,8 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -34,13 +34,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.1.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Map\Map.csproj" /> <ProjectReference Include="..\Map\Map.csproj" />

View File

@ -180,7 +180,8 @@ public class CopyDistinct
progressBar = new(count, message, options); progressBar = new(count, message, options);
string key = string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey) ? _PropertyConfiguration.ResultAllInOne : _AppSettings.ResultDirectoryKey; string key = string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey) ? _PropertyConfiguration.ResultAllInOne : _AppSettings.ResultDirectoryKey;
string[] directories = _FileGroups[key]; string[] directories = _FileGroups[key];
(distinctDirectories, toDoCollection) = IDirectory.GetToDoCollection(_PropertyConfiguration, _AppSettings.CopyDuplicates, _AppSettings.IfCanUseId, filesCollection, directories, () => progressBar.Tick()); ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollection);
(distinctDirectories, toDoCollection) = IDirectory.GetToDoCollection(_PropertyConfiguration, _AppSettings.CopyDuplicates, _AppSettings.IfCanUseId, filePathsCollection, directories, () => progressBar.Tick());
progressBar.Dispose(); progressBar.Dispose();
} }
foreach (string distinctDirectory in distinctDirectories) foreach (string distinctDirectory in distinctDirectories)

View File

@ -34,15 +34,15 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Options" Version="8.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.1.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -35,13 +35,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.1.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -35,13 +35,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.1.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -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.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" /> <ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />

View File

@ -29,7 +29,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.1.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -34,13 +34,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.1.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -33,7 +33,7 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" /> <ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />

View File

@ -229,7 +229,7 @@ public class D_Face : IFaceD
} }
} }
private List<Shared.Models.Face> GetFaces(string outputResolution, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<Location> locations) private List<Shared.Models.Face> GetFaces(string outputResolution, string cResultsFullGroupDirectory, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<Location> locations)
{ {
if (_PropertyConfiguration.NumberOfJitters is null) if (_PropertyConfiguration.NumberOfJitters is null)
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfJitters)); throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfJitters));
@ -238,7 +238,24 @@ public class D_Face : IFaceD
List<Shared.Models.Face> results = []; List<Shared.Models.Face> results = [];
FaceRecognitionDotNet.Image? unknownImage; FaceRecognitionDotNet.Image? unknownImage;
try try
{ unknownImage = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName); } {
if (mappingFromItem.ResizedFileHolder.ExtensionLowered != ".tif")
unknownImage = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName);
else
{
int outputQuality = 100;
string extension = ".png";
string file = Path.Combine(cResultsFullGroupDirectory, $"{mappingFromItem.ResizedFileHolder.Name}{extension}");
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(extension, outputQuality);
#pragma warning disable CA1416
System.Drawing.Image image = System.Drawing.Image.FromFile(mappingFromItem.ResizedFileHolder.FullName);
image.Save(Path.Combine(cResultsFullGroupDirectory, $"{mappingFromItem.ResizedFileHolder.Name}{filenameExtension}"), imageCodecInfo, encoderParameters);
image.Dispose();
#pragma warning restore CA1416
unknownImage = FaceRecognition.LoadImageFile(file);
File.Delete(file);
}
}
catch (Exception) catch (Exception)
{ unknownImage = null; } { unknownImage = null; }
if (unknownImage is not null) if (unknownImage is not null)
@ -276,7 +293,7 @@ public class D_Face : IFaceD
#pragma warning restore CA1416 #pragma warning restore CA1416
public List<Shared.Models.Face> GetFaces(string outputResolution, string dResultsFullGroupDirectory, 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, string dResultsFullGroupDirectory, 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;
if (string.IsNullOrEmpty(dResultsFullGroupDirectory)) if (string.IsNullOrEmpty(dResultsFullGroupDirectory))
@ -325,7 +342,7 @@ public class D_Face : IFaceD
locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(results, mappingFromPhotoPrismCollection, _RectangleIntersectMinimum); locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(results, mappingFromPhotoPrismCollection, _RectangleIntersectMinimum);
if (results is null || locations.Count > 0) if (results is null || locations.Count > 0)
{ {
results = GetFaces(outputResolution, property, mappingFromItem, outputResolutionToResize, locations); results = GetFaces(outputResolution, cResultsFullGroupDirectory, property, mappingFromItem, outputResolutionToResize, locations);
if (results.Count == 0) if (results.Count == 0)
File.Move(mappingFromItem.ResizedFileHolder.FullName, $"{mappingFromItem.ResizedFileHolder.FullName}.err"); File.Move(mappingFromItem.ResizedFileHolder.FullName, $"{mappingFromItem.ResizedFileHolder.FullName}.err");
else else

View File

@ -33,7 +33,7 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" /> <ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />

5
Instance/.vscode/mklink.md vendored Normal file
View File

@ -0,0 +1,5 @@
# mklink
```bash Sat Aug 17 2024 15:24:10 GMT-0700 (Mountain Standard Time)
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Instance\.vscode\.UserSecrets" "C:\Users\mikep\AppData\Roaming\Microsoft\UserSecrets\2999dda1-5329-4d9f-9d68-cccfabe0e47f"
```

View File

@ -252,22 +252,26 @@ 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<string[]> filesCollection) private ReadOnlyCollection<int> GetNotNineCollection(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
List<int> results = []; List<int> results = [];
FilePath filePath; FileInfo fileInfo;
FileHolder fileHolder; FileHolder fileHolder;
foreach (string[] files in filesCollection) FilePath checkFilePath;
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
foreach (string file in files) foreach (FilePath filePath in filePaths)
{ {
if (!file.Contains(" !9")) if (!filePath.FullName.Contains(" !9"))
continue; continue;
fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(file); fileInfo = new(filePath.FullName);
filePath = FilePath.Get(_Configuration.PropertyConfiguration, fileHolder, index: null); fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(fileInfo);
if (filePath.Id is null) 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; continue;
results.Add(filePath.Id.Value); results.Add(checkFilePath.Id.Value);
} }
} }
return new(results); return new(results);
@ -316,10 +320,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
private void Search(long ticks, ReadOnlyCollection<PersonContainer> personContainers, string argZero, string propertyRoot) private void Search(long ticks, ReadOnlyCollection<PersonContainer> personContainers, string argZero, string propertyRoot)
{ {
int t;
string message; string message;
MapLogic? mapLogic; MapLogic? mapLogic;
Container[] containers;
A_Property propertyLogic; A_Property propertyLogic;
string eDistanceContentDirectory; string eDistanceContentDirectory;
string? a2PeopleContentDirectory; string? a2PeopleContentDirectory;
@ -333,11 +335,12 @@ 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; ReadOnlyCollection<int>? notNineCollection = null;
ReadOnlyDictionary<long, List<int>> personKeyToIds; ReadOnlyDictionary<long, List<int>> personKeyToIds;
ReadOnlyCollection<string[]>? filesCollection = null; ReadOnlyCollection<ReadOnlyCollection<FilePath>>? filePathsCollection = null;
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(_Configuration, ticks);
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); (aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(_Configuration.PropertyConfiguration, ticks);
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory, ticks); Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory, ticks);
a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])"); a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])");
@ -355,8 +358,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
configurationOutputResolutionsHas = true; configurationOutputResolutionsHas = true;
if (!runToDoCollectionFirst) if (!runToDoCollectionFirst)
break; break;
(filesCollectionRootDirectory, filesCollection, filesCollectionCountIsOne) = GetFilesCollectionThenCopyOrMove(ticks, fileSearchFilter, directorySearchFilter, options, outputResolution); (filesCollectionRootDirectory, filePathsCollection, filesCollectionCountIsOne) = GetFilesCollectionThenCopyOrMove(ticks, fileSearchFilter, directorySearchFilter, options, outputResolution);
notNineCollection = GetNotNineCollection(filesCollection); 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);
@ -364,8 +367,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory); propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory);
if (filesCollectionCountIsOne) if (filesCollectionCountIsOne)
{ {
if (filesCollection is null) if (filePathsCollection is null)
throw new NullReferenceException(nameof(filesCollection)); throw new NullReferenceException(nameof(filePathsCollection));
string resultsGroupDirectory; string resultsGroupDirectory;
a2PeopleContentDirectory = null; a2PeopleContentDirectory = null;
eDistanceContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", _Configuration.PropertyConfiguration.ResultContent); eDistanceContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", _Configuration.PropertyConfiguration.ResultContent);
@ -376,7 +379,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
resultsGroupDirectory = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true); resultsGroupDirectory = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true);
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(resultsGroupDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(resultsGroupDirectory);
} }
argZero = SaveUrlAndGetNewRootDirectory(filesCollection.First()); argZero = SaveUrlAndGetNewRootDirectory(filePathsCollection.First());
_Configuration.PropertyConfiguration.ChangeRootDirectory(argZero); _Configuration.PropertyConfiguration.ChangeRootDirectory(argZero);
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); (aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false); propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false);
@ -384,34 +387,32 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
if (configurationOutputResolutionsHas) if (configurationOutputResolutionsHas)
{ {
int count;
foreach (string outputResolution in _Configuration.OutputResolutions) foreach (string outputResolution in _Configuration.OutputResolutions)
{ {
if (outputResolution.Any(char.IsNumber)) if (outputResolution.Any(char.IsNumber))
continue; continue;
(cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution); (cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution);
filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent); filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
filesCollection = IDirectory.GetFilesCollection(filesCollectionRootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage: true); filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollectionRootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage: true);
count = filesCollection.Select(l => l.Length).Sum();
break; break;
} }
} }
if (filesCollectionRootDirectory is null || filesCollection is null) if (filesCollectionRootDirectory is null || filePathsCollection is null)
throw new NullReferenceException(nameof(filesCollection)); throw new NullReferenceException(nameof(filePathsCollection));
message = $") Building Container(s) - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton); string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton);
if (!Directory.Exists(aPropertySingletonDirectory)) if (!Directory.Exists(aPropertySingletonDirectory))
_ = Directory.CreateDirectory(aPropertySingletonDirectory); _ = Directory.CreateDirectory(aPropertySingletonDirectory);
_ProgressBar = new(short.MaxValue, message, options); int count = filePathsCollection.Select(l => l.Count).Sum();
(t, containers) = Shared.Models.Stateless.Methods.IContainer.GetContainers(this, _Configuration.PropertyConfiguration, aPropertySingletonDirectory, filesCollectionRootDirectory, filesCollection); SaveDistinctIds(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, filePathsCollection);
message = $") Building Container(s) - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
_ProgressBar = new(count, message, options);
readOnlyContainers = Shared.Models.Stateless.Methods.IContainer.GetContainers(this, _Configuration.PropertyConfiguration, aPropertySingletonDirectory, filesCollectionRootDirectory, filePathsCollection);
_ProgressBar.Dispose(); _ProgressBar.Dispose();
ReadOnlyCollection<Container> readOnlyContainers = new(containers);
SaveDistinctIds(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, readOnlyContainers);
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleContentDirectory, a2PeopleSingletonDirectory, eDistanceContentDirectory); mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleContentDirectory, a2PeopleSingletonDirectory, eDistanceContentDirectory);
DeleteContinueFiles(personContainers); DeleteContinueFiles(personContainers);
if (!runToDoCollectionFirst) if (!runToDoCollectionFirst)
MapFaceFileLogic(ticks, personContainers, mapLogic, a2PeopleContentDirectory, eDistanceContentDirectory, options); MapFaceFileLogic(ticks, personContainers, mapLogic, a2PeopleContentDirectory, eDistanceContentDirectory, options);
FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, fPhotoPrismSingletonDirectory, t, readOnlyContainers, propertyLogic, mapLogic); FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, fPhotoPrismSingletonDirectory, count, readOnlyContainers, propertyLogic, mapLogic);
ReadOnlyCollection<Item> distinctValidImageItems = Shared.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true); ReadOnlyCollection<Item> distinctValidImageItems = Shared.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true);
if (_Configuration.LookForAbandoned) if (_Configuration.LookForAbandoned)
{ {
@ -471,9 +472,11 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
} }
private bool GetRunToDoCollectionFirst(Property.Models.Configuration propertyConfiguration, long ticks) private bool GetRunToDoCollectionFirst(Models.Configuration configuration, long ticks)
{ {
bool result = !IId.IsOffsetDeterministicHashCode(propertyConfiguration); bool result = configuration.SaveSortingWithoutPerson;
if (!result)
result = !IId.IsOffsetDeterministicHashCode(configuration.PropertyConfiguration);
if (!result) if (!result)
{ {
string[] directories; string[] directories;
@ -526,12 +529,12 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
return result; return result;
} }
private string SaveUrlAndGetNewRootDirectory(string[] files) private string SaveUrlAndGetNewRootDirectory(ReadOnlyCollection<FilePath> filePaths)
{ {
string result; string result;
if (files.Length == 0) if (filePaths.Count == 0)
throw new NotSupportedException(); throw new NotSupportedException();
string? sourceDirectory = Path.GetDirectoryName(files.First()); string? sourceDirectory = filePaths[0].DirectoryName;
if (string.IsNullOrEmpty(sourceDirectory)) if (string.IsNullOrEmpty(sourceDirectory))
throw new NotSupportedException(); throw new NotSupportedException();
Uri uri; Uri uri;
@ -572,7 +575,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
return result; return result;
} }
private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string fPhotoPrismSingletonDirectory, int t, ReadOnlyCollection<Container> readOnlyContainers, A_Property propertyLogic, MapLogic mapLogic) private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string fPhotoPrismSingletonDirectory, int count, ReadOnlyCollection<Container> readOnlyContainers, A_Property propertyLogic, MapLogic mapLogic)
{ {
int total; int total;
int notMapped; int notMapped;
@ -616,7 +619,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
sourceDirectoryChanges.Clear(); sourceDirectoryChanges.Clear();
anyNullOrNoIsUniqueFileName = filteredItems.Any(l => !l.IsUniqueFileName); anyNullOrNoIsUniqueFileName = filteredItems.Any(l => !l.IsUniqueFileName);
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
message = $"{i + 1:000} [{filteredItems.Count:000}] / {containersLength:000} - {total} / {t} total - {totalSeconds} total second(s) - {outputResolution} - <{container.SourceDirectory}> - total not mapped {totalNotMapped:000000}"; message = $"{i + 1:000} [{filteredItems.Count:000}] / {containersLength:000} - {total} / {count} total - {totalSeconds} total second(s) - {outputResolution} - <{container.SourceDirectory}> - total not mapped {totalNotMapped:000000}";
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, container.SourceDirectory, anyNullOrNoIsUniqueFileName); propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, container.SourceDirectory, anyNullOrNoIsUniqueFileName);
if (outputResolutionHasNumber) if (outputResolutionHasNumber)
_Resize.SetAngleBracketCollection(cResultsFullGroupDirectory, container.SourceDirectory); _Resize.SetAngleBracketCollection(cResultsFullGroupDirectory, container.SourceDirectory);
@ -653,14 +656,14 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
total += container.Items.Count; total += container.Items.Count;
} }
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
message = $"### [###] / {containersLength:000} - {total} / {t} total - {totalSeconds} total second(s) - {outputResolution} - <> - total not mapped {totalNotMapped:000000}"; message = $"### [###] / {containersLength:000} - {total} / {count} total - {totalSeconds} total second(s) - {outputResolution} - <> - total not mapped {totalNotMapped:000000}";
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
using ProgressBar progressBar = new(1, message, options); using ProgressBar progressBar = new(1, message, options);
progressBar.Tick(); progressBar.Tick();
} }
} }
private static void SaveDistinctIds(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<Container> readOnlyContainers) private static void SaveDistinctIds(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
string paddedId; string paddedId;
List<int> distinct = []; List<int> distinct = [];
@ -668,21 +671,19 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
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 (Container container in readOnlyContainers) foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
if (container.Items.Count == 0) if (filePaths.Count == 0)
continue; continue;
foreach (Item item in container.Items) foreach (FilePath filePath in filePaths)
{ {
if (item.Property?.Id is null) if (filePath.Id is null)
continue; continue;
if (item.Property.Id != item.FilePath.Id) if (distinct.Contains(filePath.Id.Value))
throw new NotSupportedException();
if (distinct.Contains(item.Property.Id.Value))
continue; continue;
distinct.Add(item.Property.Id.Value); distinct.Add(filePath.Id.Value);
paddedId = IId.GetPaddedId(propertyConfiguration, item.Property.Id.Value, item.FilePath.IsIgnore, index: null); paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal, index: null);
identifiers.Add(new(item.Property.Id.Value, paddedId)); identifiers.Add(new(filePath.Id.Value, paddedId));
} }
} }
string json = JsonSerializer.Serialize(identifiers.OrderBy(l => l.PaddedId).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray); string json = JsonSerializer.Serialize(identifiers.OrderBy(l => l.PaddedId).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
@ -855,6 +856,34 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
return new(results); return new(results);
} }
public ReadOnlyDictionary<string, LocationContainer> GetOnlyOne(IDistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> matrix)
{
Dictionary<string, LocationContainer> results = [];
List<string> added = [];
LocationContainer? tryGetValue;
foreach (LocationContainer locationContainer in matrix)
{
if (_Configuration.SaveIndividually)
break;
if (locationContainer.LengthSource is null)
continue;
if (_Configuration.UseExtraPersonKeyCheck)
{
if (results.TryGetValue(locationContainer.LengthSource.Name, out tryGetValue))
{
if (locationContainer.PersonKey is not null && tryGetValue.PersonKey is not null && locationContainer.PersonKey.Value != tryGetValue.PersonKey)
_ = results.Remove(locationContainer.LengthSource.Name);
continue;
}
}
if (added.Contains(locationContainer.LengthSource.Name))
continue;
added.Add(locationContainer.LengthSource.Name);
results.Add(locationContainer.LengthSource.Name, locationContainer);
}
return new(results);
}
private List<SaveContainer> GetSaveContainers(long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory, ProgressBarOptions options, MapLogic mapLogic, string outputResolution) private List<SaveContainer> GetSaveContainers(long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory, ProgressBarOptions options, MapLogic mapLogic, string outputResolution)
{ {
List<SaveContainer> results; List<SaveContainer> results;
@ -865,7 +894,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
if (mapped.Count == 0 && !_Configuration.SaveSortingWithoutPerson) if (mapped.Count == 0 && !_Configuration.SaveSortingWithoutPerson)
throw new NotSupportedException($"Switch {nameof(_Configuration.SaveSortingWithoutPerson)}!"); throw new NotSupportedException($"Switch {nameof(_Configuration.SaveSortingWithoutPerson)}!");
ReadOnlyCollection<FilePath> filePaths = GetFilePath(ticks, dFacesContentDirectory); ReadOnlyCollection<FilePath> filePaths = GetFilePath(ticks, dFacesContentDirectory);
List<LocationContainer> available = Map.Models.Stateless.Methods.IMapLogic.GetAvailable(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Faces, ticks, dFacesContentDirectory, filePaths); List<LocationContainer> available = Map.Models.Stateless.Methods.IMapLogic.GetAvailable(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, _Faces, ticks, filePaths);
if (!string.IsNullOrEmpty(_Configuration.FocusDirectory) && _Configuration.FocusDirectory.Length != 2) if (!string.IsNullOrEmpty(_Configuration.FocusDirectory) && _Configuration.FocusDirectory.Length != 2)
throw new NotSupportedException($"{nameof(_Configuration.FocusDirectory)} currently only works with output directory! Example 00."); throw new NotSupportedException($"{nameof(_Configuration.FocusDirectory)} currently only works with output directory! Example 00.");
ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedWithEncoding = E_Distance.GetMappedWithEncoding(mapped); ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedWithEncoding = E_Distance.GetMappedWithEncoding(mapped);
@ -873,16 +902,29 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
throw new NotSupportedException($"Switch {nameof(_Configuration.SaveSortingWithoutPerson)}!"); throw new NotSupportedException($"Switch {nameof(_Configuration.SaveSortingWithoutPerson)}!");
List<LocationContainer> preFiltered = E_Distance.GetPreFilterLocationContainer(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, _Configuration.FocusDirectory, _Configuration.FocusModel, _Configuration.SkipPersonWithMoreThen, ticks, mapLogic, jLinkResolvedPersonKeys, mapped, available); List<LocationContainer> preFiltered = E_Distance.GetPreFilterLocationContainer(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, _Configuration.FocusDirectory, _Configuration.FocusModel, _Configuration.SkipPersonWithMoreThen, ticks, mapLogic, jLinkResolvedPersonKeys, mapped, available);
if (preFiltered.Count == 0) if (preFiltered.Count == 0)
throw new NotSupportedException("Done?"); results = [];
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.RangeFaceAreaPermyriadTolerance, _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)
throw new NotSupportedException("Done?"); results = [];
else
{
string message = $") Building Matrix - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)"; string message = $") Building Matrix - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
_ProgressBar = new(postFiltered.Count, message, options); _ProgressBar = new(postFiltered.Count, message, options);
ReadOnlyCollection<LocationContainer> matrix = E_Distance.GetMatrixLocationContainers(this, _MapConfiguration, ticks, mapLogic, mappedWithEncoding, preFiltered, distanceLimits, postFiltered); ReadOnlyCollection<LocationContainer> matrix = E_Distance.GetMatrixLocationContainers(this, _MapConfiguration, ticks, mapLogic, mappedWithEncoding, preFiltered, distanceLimits, postFiltered);
_ProgressBar.Dispose(); _ProgressBar.Dispose();
results = mapLogic.GetSaveContainers(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, distanceLimits, matrix); ReadOnlyDictionary<string, LocationContainer> onlyOne = GetOnlyOne(distanceLimits, matrix);
if (onlyOne.Count == 0)
results = [];
else
{
ReadOnlyDictionary<long, PersonContainer> personKeyToPersonContainer = mapLogic.GetPersonKeyToPersonContainer();
results = mapLogic.GetSaveContainers(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, distanceLimits, onlyOne, personKeyToPersonContainer);
}
}
}
return results; return results;
} }
@ -1113,6 +1155,25 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
_ = _BlurHasher.EncodeAndSave(item.FilePath, resizedFileHolder); _ = _BlurHasher.EncodeAndSave(item.FilePath, resizedFileHolder);
} }
} }
bool? shouldIgnore = property is null || property.Keywords is null ? null : _Configuration.PropertyConfiguration.IgnoreRulesKeyWords.Any(l => property.Keywords.Contains(l));
if (shouldIgnore is not null)
{
if (shouldIgnore.Value)
{
FileInfo fileInfo = new(resizedFileHolder.FullName);
if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden))
File.SetAttributes(resizedFileHolder.FullName, FileAttributes.Hidden);
}
if (resizedFileHolder.Exists && item.FilePath.HasIgnoreKeyword is not null && item.FilePath.HasIgnoreKeyword.Value != shouldIgnore.Value)
{
if (!item.FilePath.DirectoryName.Contains("Results") || !item.FilePath.DirectoryName.Contains("Resize"))
throw new NotSupportedException($"Rename File! <{item.FilePath.FileNameFirstSegment}>");
else
{
File.Delete(resizedFileHolder.FullName);
}
}
}
if (property is null || item.Property is null) if (property is null || item.Property is null)
throw new NullReferenceException(nameof(property)); throw new NullReferenceException(nameof(property));
item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder); item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder);
@ -1142,7 +1203,12 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
Dictionary<string, int[]> outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem); Dictionary<string, int[]> outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem);
if (_Configuration.SaveResizedSubfiles) if (_Configuration.SaveResizedSubfiles)
{
if (shouldIgnore is not null && item.FilePath.HasIgnoreKeyword is not null && item.FilePath.HasIgnoreKeyword.Value != shouldIgnore.Value)
faces = [];
else
_Resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize); _Resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize);
}
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution))
faces = []; faces = [];
else if (!mappingFromItem.ResizedFileHolder.Exists && !File.Exists(mappingFromItem.ResizedFileHolder.FullName)) else if (!mappingFromItem.ResizedFileHolder.Exists && !File.Exists(mappingFromItem.ResizedFileHolder.FullName))
@ -1153,7 +1219,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
if (!fileNameToCollection.TryGetValue(mappingFromItem.Id, out mappingFromPhotoPrismCollection)) if (!fileNameToCollection.TryGetValue(mappingFromItem.Id, out mappingFromPhotoPrismCollection))
mappingFromPhotoPrismCollection = null; mappingFromPhotoPrismCollection = null;
bool move = _Configuration.DistanceMoveUnableToMatch || _Configuration.DistanceRenameToMatch && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution); bool move = _Configuration.DistanceMoveUnableToMatch || _Configuration.DistanceRenameToMatch && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution);
faces = _Faces.GetFaces(outputResolution, dResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, mappingFromPhotoPrismCollection); faces = _Faces.GetFaces(outputResolution, cResultsFullGroupDirectory, dResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, mappingFromPhotoPrismCollection);
result = GetNotMappedCountAndUpdateMappingFromPersonThenSetMapping(mapLogic, item, isFocusRelativePath, mappingFromItem, mappingFromPhotoPrismCollection, faces); result = GetNotMappedCountAndUpdateMappingFromPersonThenSetMapping(mapLogic, item, isFocusRelativePath, mappingFromItem, mappingFromPhotoPrismCollection, faces);
List<(Shared.Models.Face, FileHolder?, string, bool Saved)> faceCollection = _Faces.SaveFaces(_FaceParts.FileNameExtension, dResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, mappingFromItem, exifDirectory, faces); List<(Shared.Models.Face, FileHolder?, string, bool Saved)> faceCollection = _Faces.SaveFaces(_FaceParts.FileNameExtension, dResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, mappingFromItem, exifDirectory, faces);
if (_Configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) if (_Configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
@ -1355,41 +1421,41 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
} }
private static void CheckForAllWindowsLinks(ReadOnlyCollection<string[]> filesCollection) private static void CheckForAllWindowsLinks(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
string fileFullPath; string fileFullPath;
WindowsShortcut windowsShortcut; WindowsShortcut windowsShortcut;
foreach (string[] files in filesCollection) foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
if (files.Length == 0) if (filePaths.Count == 0)
continue; continue;
if (files.All(l => l.EndsWith(".lnk"))) if (filePaths.All(l => l.ExtensionLowered == ".lnk"))
{ {
foreach (string file in files) foreach (FilePath filePath in filePaths)
{ {
windowsShortcut = WindowsShortcut.Load(file); windowsShortcut = WindowsShortcut.Load(filePath.FullName);
if (windowsShortcut.Path is null) if (windowsShortcut.Path is null)
{ {
File.Delete(file); File.Delete(filePath.FullName);
continue; continue;
} }
fileFullPath = windowsShortcut.Path; fileFullPath = windowsShortcut.Path;
windowsShortcut.Dispose(); windowsShortcut.Dispose();
File.WriteAllText(Path.ChangeExtension(file, ".url"), fileFullPath); File.WriteAllText(Path.ChangeExtension(filePath.FullName, ".url"), fileFullPath);
File.Delete(file); File.Delete(filePath.FullName);
} }
throw new NotSupportedException("All are Windows *.lnk files!"); throw new NotSupportedException("All are Windows *.lnk files!");
} }
} }
} }
private static bool IsFilesCollectionCountIsOne(ReadOnlyCollection<string[]> filesCollection) private static bool IsFilesCollectionCountIsOne(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
bool result = true; bool result = true;
int count = 0; int count = 0;
foreach (string[] files in filesCollection) foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
if (files.Length == 0) if (filePaths.Count == 0)
continue; continue;
count += 1; count += 1;
if (count > 1) if (count > 1)
@ -1399,22 +1465,22 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
} }
} }
if (result) if (result)
CheckForAllWindowsLinks(filesCollection); CheckForAllWindowsLinks(filePathsCollection);
return result; return result;
} }
private (string, ReadOnlyCollection<string[]>, bool) GetFilesCollectionThenCopyOrMove(long ticks, string fileSearchFilter, string directorySearchFilter, ProgressBarOptions options, string outputResolution) private (string, ReadOnlyCollection<ReadOnlyCollection<FilePath>>, bool) GetFilesCollectionThenCopyOrMove(long ticks, string fileSearchFilter, string directorySearchFilter, ProgressBarOptions options, string outputResolution)
{ {
ProgressBar progressBar; ProgressBar progressBar;
string filesCollectionRootDirectory = _Configuration.PropertyConfiguration.RootDirectory; string filesCollectionRootDirectory = _Configuration.PropertyConfiguration.RootDirectory;
(string cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution); (string cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution);
IReadOnlyDictionary<string, string[]> fileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, [_Configuration.PropertyConfiguration.ResultContent]); IReadOnlyDictionary<string, string[]> fileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, [_Configuration.PropertyConfiguration.ResultContent]);
ReadOnlyCollection<string[]> filesCollection = IDirectory.GetFilesCollection(filesCollectionRootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage: false); ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollectionRootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage: false);
int count = filesCollection.Select(l => l.Length).Sum(); int count = filePathsCollection.Select(l => l.Count).Sum();
bool filesCollectionCountIsOne = IsFilesCollectionCountIsOne(filesCollection); 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)";
progressBar = new(count, message, options); progressBar = new(count, message, options);
(string[] distinctDirectories, List<(FilePath, string)> toDoCollection) = IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, filesCollection, fileGroups[_Configuration.PropertyConfiguration.ResultContent], () => progressBar.Tick()); (string[] distinctDirectories, List<(FilePath, string)> toDoCollection) = IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, filePathsCollection, fileGroups[_Configuration.PropertyConfiguration.ResultContent], () => progressBar.Tick());
progressBar.Dispose(); progressBar.Dispose();
foreach (string distinctDirectory in distinctDirectories) foreach (string distinctDirectory in distinctDirectories)
{ {
@ -1425,7 +1491,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
progressBar = new(count, message, options); progressBar = new(count, message, options);
_ = IDirectory.CopyOrMove(toDoCollection, move: false, moveBack: false, () => progressBar.Tick()); _ = IDirectory.CopyOrMove(toDoCollection, move: false, moveBack: false, () => progressBar.Tick());
progressBar.Dispose(); progressBar.Dispose();
return (filesCollectionRootDirectory, new(filesCollection), filesCollectionCountIsOne); return (filesCollectionRootDirectory, filePathsCollection, filesCollectionCountIsOne);
} }
} }

View File

@ -34,15 +34,15 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
<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.1.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\BlurHash\BlurHash.csproj" /> <ProjectReference Include="..\BlurHash\BlurHash.csproj" />

View File

@ -94,6 +94,7 @@ public class Configuration
public int? SortingMaximumPerKey { get; set; } public int? SortingMaximumPerKey { get; set; }
public int? SortingMinimumToUseSigma { get; set; } public int? SortingMinimumToUseSigma { get; set; }
public bool? TestDistanceResults { get; set; } public bool? TestDistanceResults { get; set; }
public bool? UseExtraPersonKeyCheck { get; set; }
public int? UseFilterTries { get; set; } public int? UseFilterTries { get; set; }
public string[]? ValidKeyWordsToIgnoreInRandom { get; set; } public string[]? ValidKeyWordsToIgnoreInRandom { get; set; }
public string[]? ValidResolutions { get; set; } public string[]? ValidResolutions { get; set; }
@ -213,6 +214,7 @@ public class Configuration
if (configuration?.SortingMaximumPerKey is null) throw new NullReferenceException(nameof(configuration.SortingMaximumPerKey)); if (configuration?.SortingMaximumPerKey is null) throw new NullReferenceException(nameof(configuration.SortingMaximumPerKey));
if (configuration?.SortingMinimumToUseSigma is null) throw new NullReferenceException(nameof(configuration.SortingMinimumToUseSigma)); if (configuration?.SortingMinimumToUseSigma is null) throw new NullReferenceException(nameof(configuration.SortingMinimumToUseSigma));
if (configuration?.TestDistanceResults is null) throw new NullReferenceException(nameof(configuration.TestDistanceResults)); if (configuration?.TestDistanceResults is null) throw new NullReferenceException(nameof(configuration.TestDistanceResults));
if (configuration?.UseExtraPersonKeyCheck is null) throw new NullReferenceException(nameof(configuration.UseExtraPersonKeyCheck));
if (configuration?.UseFilterTries is null) throw new NullReferenceException(nameof(configuration.UseFilterTries)); if (configuration?.UseFilterTries is null) throw new NullReferenceException(nameof(configuration.UseFilterTries));
// if (configuration?.ValidKeyWordsToIgnoreInRandom is null) throw new NullReferenceException(nameof(configuration.ValidKeyWordsToIgnoreInRandom)); // if (configuration?.ValidKeyWordsToIgnoreInRandom is null) throw new NullReferenceException(nameof(configuration.ValidKeyWordsToIgnoreInRandom));
// if (configuration?.ValidResolutions is null) throw new NullReferenceException(nameof(configuration.ValidResolutions)); // if (configuration?.ValidResolutions is null) throw new NullReferenceException(nameof(configuration.ValidResolutions));
@ -304,6 +306,7 @@ public class Configuration
configuration.SortingMaximumPerKey.Value, configuration.SortingMaximumPerKey.Value,
configuration.SortingMinimumToUseSigma.Value, configuration.SortingMinimumToUseSigma.Value,
configuration.TestDistanceResults.Value, configuration.TestDistanceResults.Value,
configuration.UseExtraPersonKeyCheck.Value,
configuration.UseFilterTries.Value, configuration.UseFilterTries.Value,
configuration.ValidKeyWordsToIgnoreInRandom ?? [], configuration.ValidKeyWordsToIgnoreInRandom ?? [],
configuration.ValidResolutions ?? []); configuration.ValidResolutions ?? []);

View File

@ -88,6 +88,7 @@ public record Configuration(Property.Models.Configuration PropertyConfiguration,
int SortingMaximumPerKey, int SortingMaximumPerKey,
int SortingMinimumToUseSigma, int SortingMinimumToUseSigma,
bool TestDistanceResults, bool TestDistanceResults,
bool UseExtraPersonKeyCheck,
int UseFilterTries, int UseFilterTries,
string[] ValidKeyWordsToIgnoreInRandom, string[] ValidKeyWordsToIgnoreInRandom,
string[] ValidResolutions); string[] ValidResolutions);

View File

@ -36,8 +36,8 @@
<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="WindowsShortcutFactory" Version="1.1.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -359,6 +359,12 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
return new(results); return new(results);
} }
public ReadOnlyDictionary<long, PersonContainer> GetPersonKeyToPersonContainer()
{
Dictionary<long, PersonContainer> results = [];
return new(results);
}
public ReadOnlyDictionary<long, List<int>> GetPersonKeyToIds() public ReadOnlyDictionary<long, List<int>> GetPersonKeyToIds()
{ {
Dictionary<long, List<int>> results = []; Dictionary<long, List<int>> results = [];
@ -820,9 +826,11 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
return result; return result;
} }
private string? GetDisplayDirectoryName(string? displayDirectoryName, LocationContainer locationContainer) private string? GetDisplayDirectoryName(string? displayDirectoryName, LocationContainer locationContainer, ReadOnlyDictionary<long, PersonContainer> personKeyToPersonContainer)
{ {
string? result = displayDirectoryName; string? result = displayDirectoryName;
if (personKeyToPersonContainer.Count != 0)
{
ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers = GetWholePercentagesToPersonContainers(locationContainer.Id); ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers = GetWholePercentagesToPersonContainers(locationContainer.Id);
if (wholePercentagesToPersonContainers is not null) if (wholePercentagesToPersonContainers is not null)
{ {
@ -835,10 +843,11 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
result = keyValuePair.Value[0].DisplayDirectoryName; result = keyValuePair.Value[0].DisplayDirectoryName;
} }
} }
}
return result; return result;
} }
public List<SaveContainer> GetSaveContainers(string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, Shared.Models.Methods.IDistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> matrix) public List<SaveContainer> GetSaveContainers(string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, Shared.Models.Methods.IDistanceLimits distanceLimits, ReadOnlyDictionary<string, LocationContainer> onlyOne, ReadOnlyDictionary<long, PersonContainer> personKeyToPersonContainer)
{ {
if (_Configuration is null) if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration)); throw new NullReferenceException(nameof(_Configuration));
@ -851,7 +860,6 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
string? directory; string? directory;
string shortcutFile; string shortcutFile;
string facesDirectory; string facesDirectory;
List<string> added = [];
bool isCounterPersonYear; bool isCounterPersonYear;
string facePartsDirectory; string facePartsDirectory;
FileHolder? faceFileHolder; FileHolder? faceFileHolder;
@ -862,21 +870,21 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
string resizeContentDirectory; string resizeContentDirectory;
FileHolder? facePartsFileHolder; FileHolder? facePartsFileHolder;
FileHolder? hiddenFaceFileHolder; FileHolder? hiddenFaceFileHolder;
bool sortingContainersAny = matrix.Count > 0; LocationContainer locationContainer;
bool sortingContainersAny = onlyOne.Count > 0;
string cContentDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent); string cContentDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
string forceSingleImageHumanized = nameof(Shared.Models.Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title); string forceSingleImageHumanized = nameof(Shared.Models.Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title);
string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent); string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
foreach (LocationContainer locationContainer in matrix) foreach (KeyValuePair<string, LocationContainer> keyValuePair in onlyOne)
{ {
if (_Configuration.SaveIndividually) if (_Configuration.SaveIndividually)
break; break;
locationContainer = keyValuePair.Value;
if (locationContainer.LengthPermyriad is null || locationContainer.LengthSource is null) if (locationContainer.LengthPermyriad is null || locationContainer.LengthSource is null)
continue; continue;
if (added.Contains(locationContainer.LengthSource.Name))
continue;
segmentB = locationContainer.LengthPermyriad.Value.ToString().PadLeft(2, '0')[..2]; segmentB = locationContainer.LengthPermyriad.Value.ToString().PadLeft(2, '0')[..2];
displayDirectoryName = GetDisplayDirectoryName(locationContainer.DisplayDirectoryName, locationContainer, personKeyToPersonContainer);
isCounterPersonYear = locationContainer.PersonKey is not null && IPersonBirthday.IsCounterPersonYear(locationContainer.PersonKey.Value); isCounterPersonYear = locationContainer.PersonKey is not null && IPersonBirthday.IsCounterPersonYear(locationContainer.PersonKey.Value);
displayDirectoryName = isCounterPersonYear ? locationContainer.DisplayDirectoryName : GetDisplayDirectoryName(locationContainer.DisplayDirectoryName, locationContainer);
(by, _, isBySorting) = Stateless.MapLogic.Get(useFiltersCounter, _Configuration.SaveIndividually, sortingContainersAny, forceSingleImageHumanized, locationContainer.LengthPermyriad, locationContainer.PersonKey, displayDirectoryName); (by, _, isBySorting) = Stateless.MapLogic.Get(useFiltersCounter, _Configuration.SaveIndividually, sortingContainersAny, forceSingleImageHumanized, locationContainer.LengthPermyriad, locationContainer.PersonKey, displayDirectoryName);
record = Get(_Configuration, by, locationContainer.PersonKey, displayDirectoryName, segmentB); record = Get(_Configuration, by, locationContainer.PersonKey, displayDirectoryName, segmentB);
if (string.IsNullOrEmpty(record.Directory) || string.IsNullOrEmpty(record.PersonDirectory)) if (string.IsNullOrEmpty(record.Directory) || string.IsNullOrEmpty(record.PersonDirectory))
@ -903,7 +911,6 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
resizedFileHolder = IFileHolder.Get(Path.Combine(resizeContentDirectory, $"{locationContainer.LengthSource.FileNameFirstSegment}{Path.GetExtension(locationContainer.LengthSource.NameWithoutExtension)}")); resizedFileHolder = IFileHolder.Get(Path.Combine(resizeContentDirectory, $"{locationContainer.LengthSource.FileNameFirstSegment}{Path.GetExtension(locationContainer.LengthSource.NameWithoutExtension)}"));
saveContainer = new(checkFile, directory, faceFileHolder, hiddenFaceFileHolder, facePartsFileHolder, resizedFileHolder, shortcutFile); saveContainer = new(checkFile, directory, faceFileHolder, hiddenFaceFileHolder, facePartsFileHolder, resizedFileHolder, shortcutFile);
results.Add(saveContainer); results.Add(saveContainer);
added.Add(locationContainer.LengthSource.Name);
} }
return results; return results;
} }

View File

@ -144,7 +144,7 @@ internal abstract class FaceFileLogic
File.Move(filePath.FullName, checkFile); File.Move(filePath.FullName, checkFile);
} }
private static void AvailableParallelFor(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, IFaceD dFace, List<LocationContainer> locationContainers, FilePath filePath) private static void AvailableParallelFor(Configuration configuration, IFaceD dFace, List<LocationContainer> locationContainers, FilePath filePath)
{ {
string? json; string? json;
const bool fromDistanceContent = false; const bool fromDistanceContent = false;
@ -193,7 +193,7 @@ internal abstract class FaceFileLogic
wholePercentages.Value)); wholePercentages.Value));
} }
internal static List<LocationContainer> GetAvailable(int maxDegreeOfParallelism, Property.Models.Configuration propertyConfiguration, Configuration configuration, IFaceD dFace, long ticks, string dFacesContentDirectory, ReadOnlyCollection<FilePath> filePaths) internal static List<LocationContainer> GetAvailable(int maxDegreeOfParallelism, Configuration configuration, IFaceD dFace, long ticks, ReadOnlyCollection<FilePath> filePaths)
{ {
List<LocationContainer> results = []; List<LocationContainer> results = [];
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
@ -204,7 +204,7 @@ internal abstract class FaceFileLogic
_ = Parallel.For(0, filePaths.Count, parallelOptions, (i, state) => _ = Parallel.For(0, filePaths.Count, parallelOptions, (i, state) =>
{ {
progressBar.Tick(); progressBar.Tick();
AvailableParallelFor(propertyConfiguration, configuration, dFace, results, filePaths[i]); AvailableParallelFor(configuration, dFace, results, filePaths[i]);
}); });
return results; return results;
} }

View File

@ -325,7 +325,7 @@ internal abstract class MapLogic
continue; continue;
} }
if (!personKeyFormattedToPersonContainer.TryGetValue(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, out personContainer)) if (!personKeyFormattedToPersonContainer.TryGetValue(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, out personContainer))
throw new Exception(); continue;
if (!results.TryGetValue(personKeyFormattedIdThenWholePercentages.Id, out idTo)) if (!results.TryGetValue(personKeyFormattedIdThenWholePercentages.Id, out idTo))
{ {
results.Add(personKeyFormattedIdThenWholePercentages.Id, []); results.Add(personKeyFormattedIdThenWholePercentages.Id, []);
@ -735,7 +735,7 @@ internal abstract class MapLogic
personDisplayDirectoryName = personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName; personDisplayDirectoryName = personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName;
matches = configuration.PersonCharacters.Where(l => personDisplayDirectoryName.Contains(l)).ToArray(); matches = configuration.PersonCharacters.Where(l => personDisplayDirectoryName.Contains(l)).ToArray();
if (matches.Length == 0) if (matches.Length == 0)
throw new NotSupportedException(); continue;
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);

View File

@ -67,9 +67,9 @@ public interface IMapLogic
static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetMapped(int maxDegreeOfParallelism, Property.Models.Configuration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) => static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetMapped(int maxDegreeOfParallelism, Property.Models.Configuration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) =>
FaceFileLogic.GetMapped(maxDegreeOfParallelism, propertyConfiguration, configuration, ticks, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory); FaceFileLogic.GetMapped(maxDegreeOfParallelism, propertyConfiguration, configuration, ticks, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
List<LocationContainer> TestStatic_GetAvailable(int maxDegreeOfParallelism, Property.Models.Configuration propertyConfiguration, Configuration configuration, IFaceD dFace, long ticks, string dFacesContentDirectory, ReadOnlyCollection<FilePath> filePaths) => List<LocationContainer> TestStatic_GetAvailable(int maxDegreeOfParallelism, Configuration configuration, IFaceD dFace, long ticks, ReadOnlyCollection<FilePath> filePaths) =>
GetAvailable(maxDegreeOfParallelism, propertyConfiguration, configuration, dFace, ticks, dFacesContentDirectory, filePaths); GetAvailable(maxDegreeOfParallelism, configuration, dFace, ticks, filePaths);
static List<LocationContainer> GetAvailable(int maxDegreeOfParallelism, Property.Models.Configuration propertyConfiguration, Configuration configuration, IFaceD dFace, long ticks, string dFacesContentDirectory, ReadOnlyCollection<FilePath> filePaths) => static List<LocationContainer> GetAvailable(int maxDegreeOfParallelism, Configuration configuration, IFaceD dFace, long ticks, ReadOnlyCollection<FilePath> filePaths) =>
FaceFileLogic.GetAvailable(maxDegreeOfParallelism, propertyConfiguration, configuration, dFace, ticks, dFacesContentDirectory, filePaths); FaceFileLogic.GetAvailable(maxDegreeOfParallelism, configuration, dFace, ticks, filePaths);
} }

View File

@ -38,7 +38,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -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.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -38,7 +38,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -38,7 +38,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />

View File

@ -36,8 +36,8 @@
<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="WindowsShortcutFactory" Version="1.1.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -35,12 +35,12 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Options" Version="8.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,8 +34,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -42,8 +42,8 @@
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -402,7 +402,7 @@ public class Rename
{ {
if (record.Id is null) if (record.Id is null)
continue; continue;
paddedId = IId.GetPaddedId(_PropertyConfiguration, record.Id.Value, ignore: null, record.Index); paddedId = IId.GetPaddedId(_PropertyConfiguration, record.Id.Value, hasIgnoreKeyword: null, hasDateTimeOriginal: null, record.Index);
checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered; checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered;
checkFile = Path.Combine(seasonDirectory, $"{paddedId}{checkFileExtension}"); checkFile = Path.Combine(seasonDirectory, $"{paddedId}{checkFileExtension}");
if (checkFile == fileHolder.FullName) if (checkFile == fileHolder.FullName)

View File

@ -34,7 +34,7 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CliWrap" Version="3.6.4" /> <PackageReference Include="CliWrap" Version="3.6.6" />
<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.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />

View File

@ -34,8 +34,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -20,22 +20,8 @@ public record FileHolder(DateTime? CreationTime,
return result; return result;
} }
public static FileHolder Get(FileInfo fileInfo) private static FileHolder GetExisting(FileInfo fileInfo) =>
{ new(fileInfo.CreationTime,
FileHolder result;
if (!fileInfo.Exists)
result = new(null,
fileInfo.DirectoryName,
fileInfo.Exists,
fileInfo.Extension.ToLower(),
fileInfo.FullName,
null,
null,
fileInfo.Name,
Path.GetFileNameWithoutExtension(fileInfo.FullName));
else
{
result = new(fileInfo.CreationTime,
fileInfo.DirectoryName, fileInfo.DirectoryName,
fileInfo.Exists, fileInfo.Exists,
fileInfo.Extension.ToLower(), fileInfo.Extension.ToLower(),
@ -44,9 +30,20 @@ public record FileHolder(DateTime? CreationTime,
fileInfo.Length, fileInfo.Length,
fileInfo.Name, fileInfo.Name,
Path.GetFileNameWithoutExtension(fileInfo.FullName)); Path.GetFileNameWithoutExtension(fileInfo.FullName));
}
return result; private static FileHolder GetNonExisting(FileInfo fileInfo) =>
} new(null,
fileInfo.DirectoryName,
fileInfo.Exists,
fileInfo.Extension.ToLower(),
fileInfo.FullName,
null,
null,
fileInfo.Name,
Path.GetFileNameWithoutExtension(fileInfo.FullName));
public static FileHolder Get(FileInfo fileInfo) =>
fileInfo.Exists ? GetExisting(fileInfo) : GetNonExisting(fileInfo);
public static FileHolder Get(FilePath filePath) public static FileHolder Get(FilePath filePath)
{ {

View File

@ -10,7 +10,8 @@ public record FilePath(long CreationTicks,
string FileNameFirstSegment, string FileNameFirstSegment,
string FullName, string FullName,
int? Id, int? Id,
bool? IsIgnore, bool? HasIgnoreKeyword,
bool? HasDateTimeOriginal,
bool IsIntelligentIdFormat, bool IsIntelligentIdFormat,
long LastWriteTicks, long LastWriteTicks,
long Length, long Length,
@ -42,7 +43,8 @@ public record FilePath(long CreationTicks,
bool isIntelligentIdFormat = IId.NameWithoutExtensionIsIntelligentIdFormat(propertyConfiguration, fileNameFirstSegment); bool isIntelligentIdFormat = IId.NameWithoutExtensionIsIntelligentIdFormat(propertyConfiguration, fileNameFirstSegment);
bool isPaddedIntelligentIdFormat = IId.NameWithoutExtensionIsPaddedIntelligentIdFormat(propertyConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment); bool isPaddedIntelligentIdFormat = IId.NameWithoutExtensionIsPaddedIntelligentIdFormat(propertyConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment);
bool fileNameFirstSegmentIsIdFormat = !isPaddedIntelligentIdFormat && !isIntelligentIdFormat && IId.NameWithoutExtensionIsIdFormat(propertyConfiguration, fileHolder); bool fileNameFirstSegmentIsIdFormat = !isPaddedIntelligentIdFormat && !isIntelligentIdFormat && IId.NameWithoutExtensionIsIdFormat(propertyConfiguration, fileHolder);
bool? isIgnore = !isIntelligentIdFormat && !isPaddedIntelligentIdFormat ? null : fileNameFirstSegment[^1] is '2' or '8'; bool? hasIgnoreKeyword = !isIntelligentIdFormat && !isPaddedIntelligentIdFormat ? null : fileNameFirstSegment[^1] is '2' or '8';
bool? hasDateTimeOriginal = !isIntelligentIdFormat && !isPaddedIntelligentIdFormat ? null : fileNameFirstSegment[^1] is '1' or '9';
if (!fileNameFirstSegmentIsIdFormat && !isIntelligentIdFormat && !isPaddedIntelligentIdFormat) if (!fileNameFirstSegmentIsIdFormat && !isIntelligentIdFormat && !isPaddedIntelligentIdFormat)
(id, sortOder) = (null, null); (id, sortOder) = (null, null);
else if (isIntelligentIdFormat) else if (isIntelligentIdFormat)
@ -70,7 +72,8 @@ public record FilePath(long CreationTicks,
fileNameFirstSegment, fileNameFirstSegment,
fileHolder.FullName, fileHolder.FullName,
id, id,
isIgnore, hasIgnoreKeyword,
hasDateTimeOriginal,
isIntelligentIdFormat, isIntelligentIdFormat,
fileHolder.LastWriteTime.Value.Ticks, fileHolder.LastWriteTime.Value.Ticks,
fileHolder.Length.Value, fileHolder.Length.Value,

View File

@ -29,22 +29,21 @@ internal abstract class Container
return container.Items.Count == results.Count ? container.Items : new(results); return container.Items.Count == results.Count ? container.Items : new(results);
} }
internal static List<Models.FilePair> GetFilePairs(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, ReadOnlyCollection<string[]> filesCollection) private static List<Models.FilePair> GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
int renamed; int renamed;
const bool useCeilingAverage = true; const bool useCeilingAverage = true;
List<Models.FilePair>? filePairs = null; List<Models.FilePair>? filePairs = null;
ReadOnlyCollection<string[]>? jsonFilesCollection = null; ReadOnlyCollection<string[]>? jsonFilesCollection = null;
IReadOnlyDictionary<string, List<string>>? compareFileNamesToFiles = null; IReadOnlyDictionary<string, List<string>>? compareFileNamesToFiles = null;
IReadOnlyDictionary<string, List<string>> fileNamesToFiles = XDirectory.GetFilesKeyValuePairs(filesCollection); IReadOnlyDictionary<string, List<string>> fileNamesToFiles = XDirectory.GetFilesKeyValuePairs(filePathsCollection);
for (int i = 0; i < short.MaxValue; i++) for (int i = 0; i < short.MaxValue; i++)
{ {
renamed = 0; renamed = 0;
dlibDotNet?.Tick();
jsonFilesCollection = IDirectory.GetFilesCollection(aPropertySingletonDirectory, directorySearchFilter, extension, useCeilingAverage); jsonFilesCollection = IDirectory.GetFilesCollection(aPropertySingletonDirectory, directorySearchFilter, extension, useCeilingAverage);
compareFileNamesToFiles = XDirectory.GetFilesKeyValuePairs(jsonFilesCollection); compareFileNamesToFiles = XDirectory.GetFilesKeyValuePairs(jsonFilesCollection);
renamed += XDirectory.LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension); renamed += XDirectory.LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension);
filePairs = XDirectory.GetFiles(propertyConfiguration, filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles); filePairs = XDirectory.GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, extension, compareFileNamesToFiles);
renamed += XDirectory.MaybeMove(propertyConfiguration, filePairs, aPropertySingletonDirectory, extension); renamed += XDirectory.MaybeMove(propertyConfiguration, filePairs, aPropertySingletonDirectory, extension);
if (renamed == 0) if (renamed == 0)
break; break;
@ -72,8 +71,9 @@ internal abstract class Container
return result; return result;
} }
private static void ParallelFor(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string extension, int rootDirectoryLength, Models.FilePair filePair, List<FilePair> results) private static void ParallelFor(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string extension, int rootDirectoryLength, Models.FilePair filePair, List<FilePair> results)
{ {
dlibDotNet?.Tick();
bool abandoned = false; bool abandoned = false;
Models.FileHolder sourceDirectoryFileHolder; Models.FileHolder sourceDirectoryFileHolder;
Models.Property? property = GetProperty(filePair); Models.Property? property = GetProperty(filePair);
@ -81,18 +81,16 @@ internal abstract class Container
FilePath filePath = FilePath.Get(propertyConfiguration, imageFileHolder, index: null); FilePath filePath = FilePath.Get(propertyConfiguration, imageFileHolder, index: null);
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);
if (property is not null && property.Keywords is not null) bool? shouldIgnore = property is null || property.Keywords is null ? null : propertyConfiguration.IgnoreRulesKeyWords.Any(l => property.Keywords.Contains(l));
if (shouldIgnore is not null)
{ {
if (filePath.IsIgnore is null) if (shouldIgnore.Value)
throw new NullReferenceException();
bool shouldIgnore = propertyConfiguration.IgnoreRulesKeyWords.Any(l => property.Keywords.Contains(l));
if (shouldIgnore)
{ {
FileInfo fileInfo = new(filePath.FullName); FileInfo fileInfo = new(filePath.FullName);
if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden)) if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden))
File.SetAttributes(imageFileHolder.FullName, FileAttributes.Hidden); File.SetAttributes(imageFileHolder.FullName, FileAttributes.Hidden);
} }
if (filePath.IsIgnore.Value != shouldIgnore) if (filePath.HasIgnoreKeyword is not null && filePath.HasIgnoreKeyword.Value != shouldIgnore.Value)
{ {
if (filePath.DirectoryName.Contains("Results") && filePath.DirectoryName.Contains("Resize")) if (filePath.DirectoryName.Contains("Results") && filePath.DirectoryName.Contains("Resize"))
File.Delete(filePath.FullName); File.Delete(filePath.FullName);
@ -122,31 +120,31 @@ internal abstract class Container
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<string[]> filesCollection, string directorySearchFilter) private static List<FilePair> GetFilePairs(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
{ {
List<FilePair> results = []; List<FilePair> results = [];
const string extension = ".json"; const string extension = ".json";
int maxDegreeOfParallelism = Environment.ProcessorCount; int maxDegreeOfParallelism = Environment.ProcessorCount;
int filesCollectionDirectoryLength = filesCollectionDirectory.Length; int filesCollectionDirectoryLength = filesCollectionDirectory.Length;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
List<Models.FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filesCollection); List<Models.FilePair> filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filePathsCollection);
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(propertyConfiguration, aPropertySingletonDirectory, extension, filesCollectionDirectoryLength, filePairs[i], results)); _ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, extension, filesCollectionDirectoryLength, filePairs[i], results));
return results; return results;
} }
private static (int, Models.Container[]) GetContainers(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection, string directorySearchFilter) private static (int, Models.Container[]) GetContainers(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
{ {
List<Models.Container> results = []; List<Models.Container> results = [];
string? directory; string directory;
List<Models.Item>? items; List<Models.Item>? items;
Models.Container container; Models.Container container;
List<string> directories = []; List<string> directories = [];
Dictionary<string, List<Models.Item>> directoryToItems = []; Dictionary<string, List<Models.Item>> directoryToItems = [];
foreach (string[] files in filesCollection) foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
if (files.Length == 0) if (filePaths.Count == 0)
continue; continue;
directory = Path.GetDirectoryName(files.First()); directory = filePaths[0].DirectoryName;
if (directory is null) if (directory is null)
continue; continue;
if (!directories.Contains(directory)) if (!directories.Contains(directory))
@ -158,7 +156,7 @@ internal abstract class Container
throw new Exception(); throw new Exception();
} }
} }
List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection, directorySearchFilter); List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filePathsCollection, directorySearchFilter);
foreach (FilePair filePair in filePairs) foreach (FilePair filePair in filePairs)
{ {
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryName, out items)) if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryName, out items))
@ -179,13 +177,12 @@ internal abstract class Container
return (filePairs.Count, results.ToArray()); return (filePairs.Count, results.ToArray());
} }
internal static (int, Models.Container[]) GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) internal static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
int count;
Models.Container[] results; Models.Container[] results;
const string directorySearchFilter = "*"; const string directorySearchFilter = "*";
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection, directorySearchFilter); (_, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filePathsCollection, directorySearchFilter);
return (count, results); return new(results);
} }
internal static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) internal static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory)
@ -197,7 +194,8 @@ internal abstract class Container
const string fileSearchFilter = "*"; const string fileSearchFilter = "*";
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);
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, propertyConfiguration.RootDirectory, filesCollection, directorySearchFilter); ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, propertyConfiguration.RootDirectory, filePathsCollection, directorySearchFilter);
return (count, results); return (count, results);
} }

View File

@ -20,10 +20,10 @@ public interface IContainer
static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) => static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory); Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory);
(int, Models.Container[]) TestStatic_GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) => ReadOnlyCollection<Models.Container> TestStatic_GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection); GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filePathsCollection);
static (int, Models.Container[]) GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) => static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
Container.GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection); Container.GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, 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,34 @@ 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) =>
GetFilePathCollections(propertyConfiguration, directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) =>
XDirectory.GetFilePathCollections(propertyConfiguration, directory, directorySearchFilter, fileSearchFilter, 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<string[]> filesCollection, string[] directories, Action? tick) => (string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string[] directories, Action? tick) =>
GetToDoCollection(propertyConfiguration, filesCollection, directories, tick); GetToDoCollection(propertyConfiguration, filePathsCollection, directories, tick);
static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection, string[] directories, Action? tick) => static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string[] directories, Action? tick) =>
XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates: false, ifCanUseId: true, filesCollection, directories, tick); XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates: false, ifCanUseId: true, filePathsCollection, directories, tick);
(string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<string[]> filesCollection, string[] directories, Action? tick) => (string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string[] directories, Action? tick) =>
GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filesCollection, directories, tick); GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, directories, tick);
static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<string[]> filesCollection, string[] directories, Action? tick) => static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string[] directories, Action? tick) =>
XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filesCollection, directories, tick); XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, directories, 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) =>
CopyOrMove(toDoCollection, move, moveBack, tick); CopyOrMove(toDoCollection, move, moveBack, tick);
static List<string> CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) => static List<string> CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) =>
XDirectory.CopyOrMove(toDoCollection, move, moveBack, tick); XDirectory.CopyOrMove(toDoCollection, move, moveBack, tick);
ReadOnlyCollection<ReadOnlyCollection<FilePath>> TestStatic_GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) =>
GetFilePathCollections(propertyConfiguration, filesCollection);
static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) =>
XDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
} }

View File

@ -28,6 +28,11 @@ public interface IFileHolder
static Models.FileHolder Get(string fileName) => static Models.FileHolder Get(string fileName) =>
Models.FileHolder.Get(new FileInfo(fileName)); Models.FileHolder.Get(new FileInfo(fileName));
Models.FileHolder TestStatic_Get(FileInfo fileInfo) =>
Get(fileInfo);
static Models.FileHolder Get(FileInfo fileInfo) =>
Models.FileHolder.Get(fileInfo);
Models.FileHolder TestStatic_Get(FilePath filePath) => Models.FileHolder TestStatic_Get(FilePath filePath) =>
Get(filePath); Get(filePath);
static Models.FileHolder Get(FilePath filePath) => static Models.FileHolder Get(FilePath filePath) =>

View File

@ -8,20 +8,20 @@ public interface IId
static bool IsOffsetDeterministicHashCode(Properties.IPropertyConfiguration propertyConfiguration) => static bool IsOffsetDeterministicHashCode(Properties.IPropertyConfiguration propertyConfiguration) =>
propertyConfiguration.Offset == DeterministicHashCode; propertyConfiguration.Offset == DeterministicHashCode;
string TestStatic_GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? ignore) => string TestStatic_GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
GetIntelligentId(propertyConfiguration, id, ignore); GetIntelligentId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal);
static string GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? ignore) => static string GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
Id.GetIntelligentId(propertyConfiguration, id, ignore); Id.GetIntelligentId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal);
int TestStatic_GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) => int TestStatic_GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) =>
GetId(propertyConfiguration, intelligentId); GetId(propertyConfiguration, intelligentId);
static int GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) => static int GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) =>
Id.GetId(propertyConfiguration, intelligentId); Id.GetId(propertyConfiguration, intelligentId);
string TestStatic_GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, bool? ignore, int? index) => string TestStatic_GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
GetPaddedId(propertyConfiguration, id, ignore, index); GetPaddedId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, bool? ignore, int? index) => static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
Id.GetPaddedId(propertyConfiguration, id, ignore, index); Id.GetPaddedId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
string TestStatic_GetIgnoreFullPath(FilePath filePath, Models.FileHolder fileHolder) => string TestStatic_GetIgnoreFullPath(FilePath filePath, Models.FileHolder fileHolder) =>
GetIgnoreFullPath(filePath, fileHolder); GetIgnoreFullPath(filePath, fileHolder);

View File

@ -35,23 +35,25 @@ internal abstract class Id
return result; return result;
} }
internal static string GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? ignore) internal static string GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal)
{ {
string result; string result;
StringBuilder stringBuilder = new(); StringBuilder stringBuilder = new();
if (propertyConfiguration.IntMinValueLength < (propertyConfiguration.ResultAllInOneSubdirectoryLength + 2)) if (propertyConfiguration.IntMinValueLength < (propertyConfiguration.ResultAllInOneSubdirectoryLength + 2))
throw new NotSupportedException(); throw new NotSupportedException();
if (hasDateTimeOriginal is null)
{ }
int key; int key;
string value; string value;
List<char> resultAllInOneSubdirectoryChars = []; List<char> resultAllInOneSubdirectoryChars = [];
if (id > -1) if (id > -1)
{ {
key = ignore is not null && ignore.Value ? 8 : 9; key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? 8 : 9;
value = id.ToString().PadLeft(propertyConfiguration.IntMinValueLength, '0'); value = id.ToString().PadLeft(propertyConfiguration.IntMinValueLength, '0');
} }
else else
{ {
key = ignore is not null && ignore.Value ? 2 : 1; key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? 2 : 1;
value = id.ToString()[1..].PadLeft(propertyConfiguration.IntMinValueLength, '0'); value = id.ToString()[1..].PadLeft(propertyConfiguration.IntMinValueLength, '0');
} }
for (int i = value.Length - propertyConfiguration.ResultAllInOneSubdirectoryLength - 1; i > -1; i--) for (int i = value.Length - propertyConfiguration.ResultAllInOneSubdirectoryLength - 1; i > -1; i--)
@ -62,14 +64,14 @@ internal abstract class Id
return result; return result;
} }
internal static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, bool? ignore, int? index) internal static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index)
{ {
string result; string result;
if (propertyConfiguration.Offset < 0) if (propertyConfiguration.Offset < 0)
result = Guid.NewGuid().ToString(); result = Guid.NewGuid().ToString();
else else
{ {
string intelligentId = GetIntelligentId(propertyConfiguration, id, ignore); string intelligentId = GetIntelligentId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal);
int check = GetId(propertyConfiguration, intelligentId); int check = GetId(propertyConfiguration, intelligentId);
if (check != id) if (check != id)
throw new NotSupportedException(); throw new NotSupportedException();

View File

@ -54,6 +54,14 @@ internal abstract partial class XDirectory
return new(results); return new(results);
} }
internal static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage)
{
ReadOnlyCollection<ReadOnlyCollection<FilePath>> results;
ReadOnlyCollection<string[]> filesCollection = GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
results = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
return results;
}
internal static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<string[]> filesCollection) internal static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<string[]> filesCollection)
{ {
Dictionary<string, List<string>> results = []; Dictionary<string, List<string>> results = [];
@ -76,6 +84,26 @@ internal abstract partial class XDirectory
return results; return results;
} }
internal static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{
Dictionary<string, List<string>> results = [];
List<string>? collection;
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{
foreach (FilePath filePath in filePaths)
{
if (!results.TryGetValue(filePath.Name, out collection))
{
results.Add(filePath.Name, []);
if (!results.TryGetValue(filePath.Name, out collection))
throw new Exception();
}
collection.Add(filePath.FullName);
}
}
return results;
}
internal static int LookForAbandoned(ReadOnlyCollection<string[]> jsonFilesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension) internal static int LookForAbandoned(ReadOnlyCollection<string[]> jsonFilesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension)
{ {
string fileName; string fileName;
@ -147,41 +175,37 @@ internal abstract partial class XDirectory
return result; return result;
} }
internal static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles) internal static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles)
{ {
List<FilePair> results = []; List<FilePair> results = [];
string? match; string? match;
string fileName;
bool uniqueFileName; bool uniqueFileName;
string fileExtension;
List<string>? collection; List<string>? collection;
bool? isNotUniqueAndNeedsReview; bool? isNotUniqueAndNeedsReview;
foreach (string[] files in filesCollection) foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
{ {
foreach (string file in files) foreach (FilePath filePath in filePaths)
{ {
isNotUniqueAndNeedsReview = null; isNotUniqueAndNeedsReview = null;
fileName = Path.GetFileName(file); if (propertyConfiguration.IgnoreExtensions.Contains(filePath.ExtensionLowered))
fileExtension = Path.GetExtension(file);
if (propertyConfiguration.IgnoreExtensions.Contains(fileExtension))
continue; continue;
if (!fileNamesToFiles.TryGetValue(fileName, out collection)) if (!fileNamesToFiles.TryGetValue(filePath.Name, out collection))
throw new Exception(); throw new Exception();
uniqueFileName = collection.Count == 1; uniqueFileName = collection.Count == 1;
if (!uniqueFileName) if (!uniqueFileName)
isNotUniqueAndNeedsReview = GetIsNotUniqueAndNeedsReview(file, collection); isNotUniqueAndNeedsReview = GetIsNotUniqueAndNeedsReview(filePath.FullName, collection);
if (!compareFileNamesToFiles.TryGetValue(string.Concat(fileName, extension), out collection)) if (!compareFileNamesToFiles.TryGetValue(string.Concat(filePath.Name, extension), out collection))
results.Add(new(file, uniqueFileName, isNotUniqueAndNeedsReview, [], null)); results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, [], null));
else else
{ {
if (collection.Count == 0) if (collection.Count == 0)
results.Add(new(file, uniqueFileName, isNotUniqueAndNeedsReview, collection, null)); results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, collection, null));
else if (uniqueFileName && collection.Count == 1) else if (uniqueFileName && collection.Count == 1)
results.Add(new(file, uniqueFileName, isNotUniqueAndNeedsReview, collection, collection.First())); results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, collection, collection.First()));
else else
{ {
match = GetMatch(file, collection); match = GetMatch(filePath.FullName, collection);
results.Add(new(file, uniqueFileName, isNotUniqueAndNeedsReview, collection, match)); results.Add(new(filePath.FullName, uniqueFileName, isNotUniqueAndNeedsReview, collection, match));
} }
} }
} }
@ -272,24 +296,38 @@ internal abstract partial class XDirectory
} }
} }
private static FilePath[] GetSortedRecords(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) private static FilePath[] GetSortedRecords(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
{ {
List<FilePath> results = []; List<FilePath> results = [];
FilePath filePath; foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
Models.FileHolder fileHolder;
foreach (string[] files in filesCollection)
{ {
foreach (string file in files) foreach (FilePath filePath in filePaths)
{
fileHolder = IFileHolder.Get(file);
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
results.Add(filePath); results.Add(filePath);
} }
}
return (from l in results orderby l.CreationTicks, l.FullName.Length descending select l).ToArray(); return (from l in results orderby l.CreationTicks, l.FullName.Length descending select l).ToArray();
} }
internal static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<string[]> filesCollection, string[] directories, Action? tick) internal static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection)
{
List<ReadOnlyCollection<FilePath>> results = [];
FilePath filePath;
List<FilePath> filePaths;
Models.FileHolder fileHolder;
foreach (string[] files in filesCollection)
{
filePaths = [];
foreach (string file in files)
{
fileHolder = IFileHolder.Get(file);
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
filePaths.Add(filePath);
}
results.Add(new(filePaths));
}
return new(results);
}
internal static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string[] directories, Action? tick)
{ {
List<(FilePath, string)> results = []; List<(FilePath, string)> results = [];
string paddedId; string paddedId;
@ -307,7 +345,7 @@ internal abstract partial class XDirectory
List<string> distinct = []; List<string> distinct = [];
Models.FileHolder fileHolder; Models.FileHolder fileHolder;
List<string> distinctDirectories = []; List<string> distinctDirectories = [];
FilePath[] sortedRecords = GetSortedRecords(propertyConfiguration, filesCollection); FilePath[] sortedRecords = GetSortedRecords(filePathsCollection);
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++)
{ {
@ -331,7 +369,7 @@ internal abstract partial class XDirectory
} }
if (ifCanUseId && filePath.IsIntelligentIdFormat && filePath.Id is not null && filePath.DirectoryName is not null) if (ifCanUseId && filePath.IsIntelligentIdFormat && filePath.Id is not null && filePath.DirectoryName is not null)
{ {
paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, filePath.IsIgnore, i); paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal, i);
paddedIdFile = Path.Combine(filePath.DirectoryName, $"{paddedId}{filePath.ExtensionLowered}"); paddedIdFile = Path.Combine(filePath.DirectoryName, $"{paddedId}{filePath.ExtensionLowered}");
if (!File.Exists(paddedIdFile)) if (!File.Exists(paddedIdFile))
{ {
@ -349,14 +387,14 @@ internal abstract partial class XDirectory
{ {
if (filePath.Id is null) if (filePath.Id is null)
throw new NullReferenceException(nameof(filePath.Id)); throw new NullReferenceException(nameof(filePath.Id));
intelligentId = IId.GetIntelligentId(propertyConfiguration, filePath.Id.Value, filePath.IsIgnore); intelligentId = IId.GetIntelligentId(propertyConfiguration, filePath.Id.Value, filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal);
if (!isOffsetDeterministicHashCode) if (!isOffsetDeterministicHashCode)
checkFile = Path.Combine(directory, $"{intelligentId}{filePath.ExtensionLowered}"); checkFile = Path.Combine(directory, $"{intelligentId}{filePath.ExtensionLowered}");
else else
{ {
if (filePath.DirectoryName is null) if (filePath.DirectoryName is null)
continue; continue;
paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, filePath.IsIgnore, i); paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal, i);
paddedIdFile = Path.Combine(filePath.DirectoryName, $"{paddedId}{filePath.ExtensionLowered}"); paddedIdFile = Path.Combine(filePath.DirectoryName, $"{paddedId}{filePath.ExtensionLowered}");
if (File.Exists(paddedIdFile)) if (File.Exists(paddedIdFile))
continue; continue;

View File

@ -32,7 +32,7 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -27,14 +27,14 @@
<DefineConstants>Linux</DefineConstants> <DefineConstants>Linux</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" /> <PackageReference Include="coverlet.collector" Version="6.0.2" />
<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.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" /> <PackageReference Include="MSTest.TestAdapter" Version="3.5.0" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" /> <PackageReference Include="MSTest.TestFramework" Version="3.5.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\BlurHash\BlurHash.csproj" /> <ProjectReference Include="..\BlurHash\BlurHash.csproj" />

View File

@ -27,13 +27,13 @@
<DefineConstants>Linux</DefineConstants> <DefineConstants>Linux</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" /> <PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" /> <PackageReference Include="MSTest.TestAdapter" Version="3.5.0" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" /> <PackageReference Include="MSTest.TestFramework" Version="3.5.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\BlurHash\BlurHash.csproj" /> <ProjectReference Include="..\BlurHash\BlurHash.csproj" />

View File

@ -33,9 +33,9 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="SkiaSharp" Version="2.88.6" /> <PackageReference Include="SkiaSharp" Version="2.88.8" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" /> <PackageReference Include="System.Drawing.Common" Version="8.0.7" />
<PackageReference Include="System.Text.Json" Version="8.0.0" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />