1 Commits

Author SHA1 Message Date
bd03bba63e Not tested 2025-04-06 15:51:08 -07:00
32 changed files with 936 additions and 959 deletions

12
.vscode/tasks.json vendored
View File

@ -136,18 +136,6 @@
],
"problemMatcher": "$msCompile"
},
{
"label": "buildDragDropSetPropertyItem",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Drag-Drop-Set-Property-Item/Drag-Drop-Set-Property-Item.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "File-Folder-Helper AOT s X Day-Helper-2025-03-20",
"type": "shell",

View File

@ -47,6 +47,5 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Metadata\Metadata.csproj" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,5 @@
using System.Collections.ObjectModel;
using System.Text.Json;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless.Methods;
@ -47,11 +48,11 @@ internal abstract class Container
continue;
foreach (Item item in filteredItems)
{
if (item.ExifDirectory?.FilePath.Id is null || item.ResizedFileHolder is null)
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
if (results.Contains(item.ExifDirectory.FilePath.Id.Value))
if (results.Contains(item.Property.Id.Value))
continue;
results.Add(item.ExifDirectory.FilePath.Id.Value);
results.Add(item.Property.Id.Value);
}
}
return results;
@ -141,23 +142,20 @@ internal abstract class Container
return results;
}
private static void ParallelFor(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, int rootDirectoryLength, ReadOnlyDictionary<int, ExifDirectory>? exifDirectoriesById, Shared.Models.FilePair filePair, List<FilePair> results)
private static void ParallelFor(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, int rootDirectoryLength, ReadOnlyDictionary<int, ExifDirectory>? __, Shared.Models.FilePair filePair, List<FilePair> results)
{
dlibDotNet?.Tick();
bool abandoned = false;
FileHolder sourceDirectoryFileHolder;
if (exifDirectoriesById is null || filePair.FilePath.Id is null || !exifDirectoriesById.TryGetValue(filePair.FilePath.Id.Value, out ExifDirectory? exifDirectory))
exifDirectory = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(filePair.FilePath);
ReadOnlyCollection<string> keywords = IMetaBase.GetKeywords(exifDirectory?.ExifBaseDirectories);
bool? shouldIgnore = propertyConfiguration.IgnoreRulesKeyWords.Any(keywords.Contains);
bool? fileSizeChanged = exifDirectory is not null ? exifDirectory.FilePath.Length != filePair.FilePath.Length : null;
Property? property = GetProperty(filePair);
bool? fileSizeChanged = property is not null ? property.FileSize != filePair.FilePath.Length : null;
bool isValidImageFormatExtension = propertyConfiguration.ValidImageFormatExtensions.Contains(filePair.FilePath.ExtensionLowered);
bool? shouldIgnore = property is null || property.Keywords is null ? null : propertyConfiguration.IgnoreRulesKeyWords.Any(l => property.Keywords.Contains(l));
bool? isArchive = filePair.FilePath.Id is null || splatNineIdentifiers is null ? null : splatNineIdentifiers.TryGetValue(filePair.FilePath.Id.Value, out Identifier? identifier);
if (exifDirectory is not null && filePair.FilePath.Id is not null && filePair.FilePath.HasIgnoreKeyword is not null && filePair.FilePath.HasDateTimeOriginal is not null)
if (property is not null && filePair.FilePath.Id is not null && filePair.FilePath.HasIgnoreKeyword is not null && filePair.FilePath.HasDateTimeOriginal is not null)
{
char? change;
ReadOnlyCollection<FilePath>? filePaths = null;
DateTime? dateTime = IDate.GetDateTimeOriginal(exifDirectory);
char hasIgnoreKeyword = IId.GetHasIgnoreKeyword(filePair.FilePath).ToString()[0];
char hasDateTimeOriginal = IId.GetHasDateTimeOriginal(propertyConfiguration, filePair.FilePath).ToString()[0];
char missingDateTimeOriginal = IId.GetMissingDateTimeOriginal(propertyConfiguration, filePair.FilePath).ToString()[0];
@ -172,7 +170,7 @@ internal abstract class Container
throw new NotSupportedException($"Rename File! <{filePair.FilePath.FileNameFirstSegment}>");
}
}
else if ((shouldIgnore is null || !shouldIgnore.Value) && dateTime is null)
else if ((shouldIgnore is null || !shouldIgnore.Value) && property.DateTimeOriginal is null)
{
if (filePair.FilePath.FileNameFirstSegment[^1] == missingDateTimeOriginal)
change = null;
@ -195,7 +193,7 @@ internal abstract class Container
RenameFile(filePair, filePair.FilePath, change.Value, filePaths);
}
string relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(filePair.FilePath.FullName, rootDirectoryLength, forceExtensionToLower: true);
bool? lastWriteTimeChanged = exifDirectory is not null ? propertyConfiguration.PropertiesChangedForProperty || exifDirectory.FilePath.LastWriteTicks != filePair.FilePath.LastWriteTicks : null;
bool? lastWriteTimeChanged = property is not null ? propertyConfiguration.PropertiesChangedForProperty || property.LastWriteTime.Ticks != filePair.FilePath.LastWriteTicks : null;
if (filePair.Match is not null)
sourceDirectoryFileHolder = IFileHolder.Get(filePair.Match);
else if (!filePair.IsUnique)
@ -215,11 +213,27 @@ internal abstract class Container
File.SetCreationTime(sourceDirectoryFileHolder.FullName, new(filePair.FilePath.LastWriteTicks));
File.SetLastWriteTime(sourceDirectoryFileHolder.FullName, sourceDirectoryFileHolder.LastWriteTime.Value);
}
Item item = Item.Get(filePair.FilePath, sourceDirectoryFileHolder, relativePath, isArchive, filePair.IsNotUniqueAndNeedsReview, filePair.IsUnique, isValidImageFormatExtension, exifDirectory, abandoned, fileSizeChanged, lastWriteTimeChanged);
Item item = Item.Get(filePair.FilePath, sourceDirectoryFileHolder, relativePath, isArchive, filePair.IsNotUniqueAndNeedsReview, filePair.IsUnique, isValidImageFormatExtension, property, abandoned, fileSizeChanged, lastWriteTimeChanged);
lock (results)
results.Add(new(filePair.IsUnique, filePair.Collection, filePair.FilePath, item));
}
private static Property? GetProperty(Shared.Models.FilePair filePair)
{
Property? result;
if (filePair.Match is null)
result = null;
else
{
string json = File.ReadAllText(filePair.Match.FullName);
if (string.IsNullOrEmpty(json))
result = null;
else
result = JsonSerializer.Deserialize(json, PropertyGenerationContext.Default.Property);
}
return result;
}
private static void RenameFile(Shared.Models.FilePair filePair, FilePath filePath, char change, ReadOnlyCollection<FilePath> filePaths)
{
string checkFile;
@ -271,7 +285,7 @@ internal abstract class Container
continue;
foreach (Item item in filteredItems)
{
if (item.ExifDirectory?.FilePath.Id is null || item.ResizedFileHolder is null)
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
if (results.Contains(item.FilePath.FileNameFirstSegment))
continue;
@ -300,13 +314,13 @@ internal abstract class Container
}
foreach (Item item in filteredItems)
{
if (item.ExifDirectory?.FilePath.Id is null || item.ResizedFileHolder is null)
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
if (distinctItems)
{
if (distinct.Contains(item.ExifDirectory.FilePath.Id.Value))
if (distinct.Contains(item.Property.Id.Value))
continue;
distinct.Add(item.ExifDirectory.FilePath.Id.Value);
distinct.Add(item.Property.Id.Value);
}
results.Add(item);
}

View File

@ -117,7 +117,7 @@ public class CopyDistinct
string key = string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey) ? _PropertyConfiguration.ResultAllInOne : _AppSettings.ResultDirectoryKey;
if (key != _PropertyConfiguration.ResultContent)
throw new NotImplementedException("Changed but didn't update!");
ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollection, useIgnoreExtensions: true);
ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollection);
(distinctDirectories, toDoCollection) = IDirectory.GetToDoCollection(_PropertyConfiguration, _AppSettings.CopyDuplicates, _AppSettings.IfCanUseId, filePathsCollection, _FileGroups, () => progressBar.Tick());
progressBar.Dispose();
}

View File

@ -1,4 +1,4 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Phares.Shared;
using System.Globalization;
@ -96,6 +96,203 @@ public class DateGroup
throw new Exception("Change configuration!");
}
private static bool WriteAllText(string path, string contents, bool compareBeforeWrite)
{
bool result;
string text;
if (!compareBeforeWrite)
result = true;
else
{
if (!File.Exists(path))
text = string.Empty;
else
text = File.ReadAllText(path);
result = text != contents;
}
if (result)
{
if (path.Contains("()"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("[]") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
File.WriteAllText(path, contents);
else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
File.WriteAllText(path, contents);
else
File.WriteAllText(path, contents);
}
return result;
}
private List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> GetMoveFileCollection(string destinationDirectory, string topDirectory, Item[] filteredItems)
{
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> results = [];
char flag;
string day;
int season;
string year;
string month;
string? check;
string fileName;
string? pathRoot;
DateTime dateTime;
string seasonName;
string weekOfYear;
bool? isWrongYear;
string seasonValue;
string directoryName;
string topDirectoryName;
List<DateTime> dateTimes;
string[]? matches = null;
string[] directorySegments;
List<string> destinationCollection;
List<string> directoryNames = [];
List<string> topDirectorySegments = [];
StringBuilder destinationDirectoryName = new();
Calendar calendar = new CultureInfo("en-US").Calendar;
for (int z = 1; z < 3; z++)
{
if (z == 1)
{
check = Path.Combine(destinationDirectory, ".");
pathRoot = Path.GetPathRoot(destinationDirectory);
}
else if (z == 2)
{
check = Path.Combine(topDirectory, ".");
pathRoot = Path.GetPathRoot(topDirectory);
}
else
throw new Exception();
if (string.IsNullOrEmpty(pathRoot))
continue;
for (int i = 0; i < int.MaxValue; i++)
{
check = Path.GetDirectoryName(check);
if (string.IsNullOrEmpty(check) || check == pathRoot)
break;
directoryName = Path.GetFileName(check);
directorySegments = directoryName.Split(' ');
topDirectorySegments.AddRange(directorySegments);
(_, matches) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(directorySegments, string.Empty);
if (matches.Length != 0)
break;
}
if (matches is not null && matches.Length != 0)
break;
}
foreach (Item item in filteredItems)
{
directoryNames.Clear();
destinationCollection = [];
_ = destinationDirectoryName.Clear();
if (item.Property is not null)
dateTimes = item.Property.GetDateTimes();
else
dateTimes = [new(item.FilePath.LastWriteTicks)];
if (item.Property is not null && item.Property.DateTimeOriginal is not null)
dateTime = item.Property.DateTimeOriginal.Value;
else if (item.Property is null)
dateTime = new(item.FilePath.LastWriteTicks);
else
dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
day = dateTime.ToString("MM-dd");
month = dateTime.ToString("MMMM");
if (item.Property?.Id is null)
{
flag = '#';
isWrongYear = null;
}
else
{
(isWrongYear, _) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(item.FilePath, item.Property.DateTimeOriginal, dateTimes);
if (isWrongYear is null)
flag = '#';
else if (isWrongYear.Value)
flag = '~';
else
{
if (item.Property.DateTimeOriginal is not null && dateTime.DayOfYear != item.Property.DateTimeOriginal.Value.DayOfYear && Math.Abs(new TimeSpan(dateTime.Ticks - item.Property.DateTimeOriginal.Value.Ticks).TotalHours) > 8)
flag = '^';
else
flag = '=';
}
}
(season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
if ((from l in topDirectorySegments where l == "Christmas" select true).Any())
seasonValue = string.Empty;
else
seasonValue = $".{season}";
if (isWrongYear is null || !isWrongYear.Value)
year = $"{flag}{dateTime:yyyy}{seasonValue}";
else if (matches is null || matches.Length < 3)
year = "----";
else
{
if (matches[0][0] != '~')
year = $"{flag}{matches[0].Split('.')[0]}{seasonValue}";
else
year = $"{flag}{matches[0][1..].Split('.')[0]}{seasonValue}";
}
topDirectoryName = Path.GetFileName(topDirectory);
weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
if (_Configuration.ByHash)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.BySeason && topDirectoryName.Length == 1 && topDirectoryName[0] == '_')
directoryNames.Add($"{year} {seasonName}");
else
{
if (!_Configuration.KeepFullPath)
{
if (topDirectoryName.Length > 1)
_ = destinationDirectoryName.Append(topDirectoryName);
if (_Configuration.BySeason)
directoryNames.AddRange([$"{destinationDirectoryName} {year} {seasonName}"]);
else if (_Configuration.ByDay)
directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year}-{day}"]);
else if (_Configuration.ByWeek)
directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year} {month}"]);
else
throw new Exception();
}
else
{
foreach (string sourceDirectoryNameSegment in topDirectorySegments)
{
if (matches is not null && matches.Contains(sourceDirectoryNameSegment))
_ = destinationDirectoryName.Append(year);
else
_ = destinationDirectoryName.Append(sourceDirectoryNameSegment);
}
if (_Configuration.BySeason)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.ByDay)
directoryNames.Add($"{weekOfYear}) {year} {day}");
else if (_Configuration.ByWeek)
directoryNames.Add($"{weekOfYear}) {month} {year}");
else
throw new Exception();
}
}
if (!_Configuration.ByHash || item.Property?.Id is null)
fileName = item.FilePath.Name;
else
fileName = $"{item.Property.Id.Value}{item.FilePath.ExtensionLowered}";
destinationCollection.Add(destinationDirectory);
destinationCollection.AddRange(directoryNames);
destinationCollection.Add(fileName);
if (item.Property is null)
results.Add(new(item, item.FilePath.LastWriteTicks, dateTime.Ticks, destinationCollection.ToArray()));
else
results.Add(new(item, item.Property.LastWriteTime.Ticks, dateTime.Ticks, destinationCollection.ToArray()));
}
return results;
}
private A_Property GetPropertyLogic(bool reverse, string outputExtension, string aResultsFullGroupDirectory)
{
A_Property result;
@ -105,64 +302,54 @@ public class DateGroup
return result;
}
private static void CreateDateShortcut(Property.Models.Configuration configuration, Container.Models.Container[] containers)
private static Item[] GetFilterItems(Container.Models.Container container)
{
string path;
string fileName;
string directory;
DateTime dateTime;
int selectedTotal;
const int minimum = 3;
List<DateTime> dateTimes;
List<Item> selectedItems;
const int maximumHours = 24;
string? relativePathDirectory;
WindowsShortcut windowsShortcut;
TimeSpan threeStandardDeviationHigh;
string aPropertyContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "()");
List<Item> results = [];
foreach (Item item in container.Items)
{
if (item.FilePath is not null)
results.Add(item);
}
return results.ToArray();
}
private (Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] GetFileMoveCollectionAll(Property.Models.Configuration configuration, string destinationRoot, Container.Models.Container[] containers)
{
(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] results;
Item[] filteredItems;
string? topDirectory;
string? checkDirectory;
string destinationDirectory;
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollection = [];
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollectionDirectory;
foreach (Container.Models.Container container in containers)
{
if (container.Items.Count == 0)
continue;
selectedTotal = 0;
threeStandardDeviationHigh = Property.Models.Stateless.IProperty.GetThreeStandardDeviationHigh(minimum, container);
if (threeStandardDeviationHigh.TotalHours > maximumHours)
threeStandardDeviationHigh = new(maximumHours, 0, 0);
for (int i = 0; i < container.Items.Count; i++)
if (!_Configuration.KeepFullPath)
destinationDirectory = destinationRoot;
else
destinationDirectory = string.Concat(destinationRoot, container.SourceDirectory[configuration.RootDirectory.Length..]);
checkDirectory = Path.GetFullPath(container.SourceDirectory);
for (int z = 0; z < int.MaxValue; z++)
{
(i, dateTimes, selectedItems) = Property.Models.Stateless.IProperty.Get(container, threeStandardDeviationHigh, i);
selectedTotal += selectedItems.Count;
foreach (Item item in selectedItems)
{
if (item.ExifDirectory is null)
continue;
relativePathDirectory = Path.GetDirectoryName(item.RelativePath);
if (string.IsNullOrEmpty(relativePathDirectory))
continue;
if (item.ExifDirectory is null)
dateTime = new(item.FilePath.LastWriteTicks);
else if (item.ExifDirectory is not null && item.ExifDirectory.DateTimeOriginal is not null)
dateTime = item.ExifDirectory.DateTimeOriginal.Value;
else
dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.ExifDirectory);
path = Path.GetFullPath($"{configuration.RootDirectory}{item.RelativePath[..^5]}");
directory = Path.Combine($"{aPropertyContentDirectory}{relativePathDirectory}", $"{dateTimes.Min():yyyy-MM-dd_HH-mm-ss}---{dateTimes.Max():yyyy-MM-dd_HH-mm-ss}");
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
fileName = Path.Combine(directory, $"{Path.GetFileName(item.RelativePath[..^5])}.lnk");
if (File.Exists(fileName))
continue;
windowsShortcut = new() { Path = path };
windowsShortcut.Save(fileName);
windowsShortcut.Dispose();
if (!File.Exists(fileName))
continue;
File.SetLastWriteTime(fileName, dateTime);
}
if (checkDirectory == configuration.RootDirectory)
break;
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory))
break;
}
if (selectedTotal < container.Items.Count && selectedTotal < (from l in container.Items where l.Property is not null select true).Count())
if (string.IsNullOrEmpty(checkDirectory))
continue;
topDirectory = checkDirectory;
filteredItems = GetFilterItems(container);
if (filteredItems.Length == 0)
continue;
fileMoveCollectionDirectory = GetMoveFileCollection(destinationDirectory, topDirectory, filteredItems);
fileMoveCollection.AddRange(fileMoveCollectionDirectory);
}
results = (from l in fileMoveCollection orderby l.MinimumDateTimeTicks descending, l.LastWriteTimeTicks descending select l).ToArray();
return results;
}
private void MoveFiles(Property.Models.Configuration configuration, string destinationRoot, Container.Models.Container[] containers)
@ -266,251 +453,64 @@ public class DateGroup
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(configuration.RootDirectory);
}
private (Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] GetFileMoveCollectionAll(Property.Models.Configuration configuration, string destinationRoot, Container.Models.Container[] containers)
private static void CreateDateShortcut(Property.Models.Configuration configuration, Container.Models.Container[] containers)
{
(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] results;
Item[] filteredItems;
string? topDirectory;
string? checkDirectory;
string destinationDirectory;
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollection = [];
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollectionDirectory;
string path;
string fileName;
string directory;
DateTime dateTime;
int selectedTotal;
const int minimum = 3;
List<DateTime> dateTimes;
List<Item> selectedItems;
const int maximumHours = 24;
string? relativePathDirectory;
WindowsShortcut windowsShortcut;
TimeSpan threeStandardDeviationHigh;
string aPropertyContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "()");
foreach (Container.Models.Container container in containers)
{
if (container.Items.Count == 0)
continue;
if (!_Configuration.KeepFullPath)
destinationDirectory = destinationRoot;
else
destinationDirectory = string.Concat(destinationRoot, container.SourceDirectory[configuration.RootDirectory.Length..]);
checkDirectory = Path.GetFullPath(container.SourceDirectory);
for (int z = 0; z < int.MaxValue; z++)
selectedTotal = 0;
threeStandardDeviationHigh = Property.Models.Stateless.IProperty.GetThreeStandardDeviationHigh(minimum, container);
if (threeStandardDeviationHigh.TotalHours > maximumHours)
threeStandardDeviationHigh = new(maximumHours, 0, 0);
for (int i = 0; i < container.Items.Count; i++)
{
if (checkDirectory == configuration.RootDirectory)
break;
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory))
break;
}
if (string.IsNullOrEmpty(checkDirectory))
continue;
topDirectory = checkDirectory;
filteredItems = GetFilterItems(container);
if (filteredItems.Length == 0)
continue;
fileMoveCollectionDirectory = GetMoveFileCollection(destinationDirectory, topDirectory, filteredItems);
fileMoveCollection.AddRange(fileMoveCollectionDirectory);
}
results = (from l in fileMoveCollection orderby l.MinimumDateTimeTicks descending, l.LastWriteTimeTicks descending select l).ToArray();
return results;
}
private static Item[] GetFilterItems(Container.Models.Container container)
{
List<Item> results = [];
foreach (Item item in container.Items)
{
if (item.FilePath is not null)
results.Add(item);
}
return results.ToArray();
}
private List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> GetMoveFileCollection(string destinationDirectory, string topDirectory, Item[] filteredItems)
{
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> results = [];
char flag;
string day;
int season;
string year;
string month;
string? check;
string fileName;
string? pathRoot;
DateTime dateTime;
string seasonName;
string weekOfYear;
bool? isWrongYear;
string seasonValue;
string directoryName;
string topDirectoryName;
List<DateTime> dateTimes;
string[]? matches = null;
string[] directorySegments;
List<string> destinationCollection;
List<string> directoryNames = [];
List<string> topDirectorySegments = [];
StringBuilder destinationDirectoryName = new();
Calendar calendar = new CultureInfo("en-US").Calendar;
for (int z = 1; z < 3; z++)
{
if (z == 1)
{
check = Path.Combine(destinationDirectory, ".");
pathRoot = Path.GetPathRoot(destinationDirectory);
}
else if (z == 2)
{
check = Path.Combine(topDirectory, ".");
pathRoot = Path.GetPathRoot(topDirectory);
}
else
throw new Exception();
if (string.IsNullOrEmpty(pathRoot))
continue;
for (int i = 0; i < int.MaxValue; i++)
{
check = Path.GetDirectoryName(check);
if (string.IsNullOrEmpty(check) || check == pathRoot)
break;
directoryName = Path.GetFileName(check);
directorySegments = directoryName.Split(' ');
topDirectorySegments.AddRange(directorySegments);
(_, matches) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(directorySegments, string.Empty);
if (matches.Length != 0)
break;
}
if (matches is not null && matches.Length != 0)
break;
}
foreach (Item item in filteredItems)
{
directoryNames.Clear();
destinationCollection = [];
_ = destinationDirectoryName.Clear();
if (item.ExifDirectory is not null)
dateTimes = item.ExifDirectory.GetDateTimes();
else
dateTimes = [new(item.FilePath.LastWriteTicks)];
if (item.ExifDirectory is not null && item.ExifDirectory.DateTimeOriginal is not null)
dateTime = item.ExifDirectory.DateTimeOriginal.Value;
else if (item.ExifDirectory is null)
dateTime = new(item.FilePath.LastWriteTicks);
else
dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.ExifDirectory);
day = dateTime.ToString("MM-dd");
month = dateTime.ToString("MMMM");
if (item.ExifDirectory?.FilePath.Id is null)
{
flag = '#';
isWrongYear = null;
}
else
{
(isWrongYear, _) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(item.FilePath, item.ExifDirectory.DateTimeOriginal, dateTimes);
if (isWrongYear is null)
flag = '#';
else if (isWrongYear.Value)
flag = '~';
else
(i, dateTimes, selectedItems) = Property.Models.Stateless.IProperty.Get(container, threeStandardDeviationHigh, i);
selectedTotal += selectedItems.Count;
foreach (Item item in selectedItems)
{
if (item.ExifDirectory.DateTimeOriginal is not null && dateTime.DayOfYear != item.ExifDirectory.DateTimeOriginal.Value.DayOfYear && Math.Abs(new TimeSpan(dateTime.Ticks - item.ExifDirectory.DateTimeOriginal.Value.Ticks).TotalHours) > 8)
flag = '^';
if (item.Property is null)
continue;
relativePathDirectory = Path.GetDirectoryName(item.RelativePath);
if (string.IsNullOrEmpty(relativePathDirectory))
continue;
if (item.Property is null)
dateTime = new(item.FilePath.LastWriteTicks);
else if (item.Property is not null && item.Property.DateTimeOriginal is not null)
dateTime = item.Property.DateTimeOriginal.Value;
else
flag = '=';
dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
path = Path.GetFullPath($"{configuration.RootDirectory}{item.RelativePath[..^5]}");
directory = Path.Combine($"{aPropertyContentDirectory}{relativePathDirectory}", $"{dateTimes.Min():yyyy-MM-dd_HH-mm-ss}---{dateTimes.Max():yyyy-MM-dd_HH-mm-ss}");
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
fileName = Path.Combine(directory, $"{Path.GetFileName(item.RelativePath[..^5])}.lnk");
if (File.Exists(fileName))
continue;
windowsShortcut = new() { Path = path };
windowsShortcut.Save(fileName);
windowsShortcut.Dispose();
if (!File.Exists(fileName))
continue;
File.SetLastWriteTime(fileName, dateTime);
}
}
(season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
if ((from l in topDirectorySegments where l == "Christmas" select true).Any())
seasonValue = string.Empty;
else
seasonValue = $".{season}";
if (isWrongYear is null || !isWrongYear.Value)
year = $"{flag}{dateTime:yyyy}{seasonValue}";
else if (matches is null || matches.Length < 3)
year = "----";
else
{
if (matches[0][0] != '~')
year = $"{flag}{matches[0].Split('.')[0]}{seasonValue}";
else
year = $"{flag}{matches[0][1..].Split('.')[0]}{seasonValue}";
}
topDirectoryName = Path.GetFileName(topDirectory);
weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
if (_Configuration.ByHash)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.BySeason && topDirectoryName.Length == 1 && topDirectoryName[0] == '_')
directoryNames.Add($"{year} {seasonName}");
else
{
if (!_Configuration.KeepFullPath)
{
if (topDirectoryName.Length > 1)
_ = destinationDirectoryName.Append(topDirectoryName);
if (_Configuration.BySeason)
directoryNames.AddRange([$"{destinationDirectoryName} {year} {seasonName}"]);
else if (_Configuration.ByDay)
directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year}-{day}"]);
else if (_Configuration.ByWeek)
directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year} {month}"]);
else
throw new Exception();
}
else
{
foreach (string sourceDirectoryNameSegment in topDirectorySegments)
{
if (matches is not null && matches.Contains(sourceDirectoryNameSegment))
_ = destinationDirectoryName.Append(year);
else
_ = destinationDirectoryName.Append(sourceDirectoryNameSegment);
}
if (_Configuration.BySeason)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.ByDay)
directoryNames.Add($"{weekOfYear}) {year} {day}");
else if (_Configuration.ByWeek)
directoryNames.Add($"{weekOfYear}) {month} {year}");
else
throw new Exception();
}
}
if (!_Configuration.ByHash || item.ExifDirectory?.FilePath.Id is null)
fileName = item.FilePath.Name;
else
fileName = $"{item.ExifDirectory.FilePath.Id.Value}{item.FilePath.ExtensionLowered}";
destinationCollection.Add(destinationDirectory);
destinationCollection.AddRange(directoryNames);
destinationCollection.Add(fileName);
if (item.ExifDirectory is null)
results.Add(new(item, item.FilePath.LastWriteTicks, dateTime.Ticks, destinationCollection.ToArray()));
else
results.Add(new(item, item.ExifDirectory.LastWriteTime.Ticks, dateTime.Ticks, destinationCollection.ToArray()));
if (selectedTotal < container.Items.Count && selectedTotal < (from l in container.Items where l.Property is not null select true).Count())
continue;
}
return results;
}
private static bool WriteAllText(string path, string contents, bool compareBeforeWrite)
{
bool result;
string text;
if (!compareBeforeWrite)
result = true;
else
{
if (!File.Exists(path))
text = string.Empty;
else
text = File.ReadAllText(path);
result = text != contents;
}
if (result)
{
if (path.Contains("()"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("[]") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
File.WriteAllText(path, contents);
else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
File.WriteAllText(path, contents);
else
File.WriteAllText(path, contents);
}
return result;
}
}

View File

@ -64,6 +64,63 @@ public partial class DragDropSearch : Form
Controls.Add(_TextBox);
}
private void Form1_Load(object? sender, EventArgs e)
{
try
{
AllowDrop = true;
DragDrop += new DragEventHandler(Form1_DragDrop);
DragEnter += new DragEventHandler(Form1_DragEnter);
_TextBox.LostFocus += new EventHandler(TextBox_LostFocus);
}
catch (Exception)
{
throw;
}
}
private void TextBox_LostFocus(object? sender, EventArgs e)
{
try
{
if (_TextBox.Text == "ps")
throw new NotImplementedException();
}
catch (Exception)
{
throw;
}
}
private void Form1_DragEnter(object? sender, DragEventArgs e)
{
try
{
if (e.Data is not null && e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
catch (Exception)
{
throw;
}
}
private void LoadData()
{
Container.Models.Container[] containers;
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "{}");
(_, containers) = View_by_Distance.Container.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory);
List<Item> collection = Program.GetItemCollection(_Configuration, containers);
foreach (Item item in collection)
{
if (item.Property?.Id is null)
continue;
if (_IdToItem.ContainsKey(item.Property.Id.Value))
continue;
_IdToItem.Add(item.Property.Id.Value, item);
}
}
public static string? GetFaceEncoding(string file)
{
string? result;
@ -90,37 +147,6 @@ public partial class DragDropSearch : Form
return result;
}
private void LoadData()
{
Container.Models.Container[] containers;
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "{}");
(_, containers) = View_by_Distance.Container.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory);
List<Item> collection = Program.GetItemCollection(_Configuration, containers);
foreach (Item item in collection)
{
if (item.ExifDirectory?.FilePath.Id is null)
continue;
if (_IdToItem.ContainsKey(item.ExifDirectory.FilePath.Id.Value))
continue;
_IdToItem.Add(item.ExifDirectory.FilePath.Id.Value, item);
}
}
private void Form1_Load(object? sender, EventArgs e)
{
try
{
AllowDrop = true;
DragDrop += new DragEventHandler(Form1_DragDrop);
DragEnter += new DragEventHandler(Form1_DragEnter);
_TextBox.LostFocus += new EventHandler(TextBox_LostFocus);
}
catch (Exception)
{
throw;
}
}
private void GetDirectoriesOrDoDragDrop(string[] paths)
{
string name;
@ -142,19 +168,6 @@ public partial class DragDropSearch : Form
}
}
private void TextBox_LostFocus(object? sender, EventArgs e)
{
try
{
if (_TextBox.Text == "ps")
throw new NotImplementedException();
}
catch (Exception)
{
throw;
}
}
private void Form1_DragDrop(object? sender, DragEventArgs e)
{
try
@ -170,17 +183,4 @@ public partial class DragDropSearch : Form
}
}
private void Form1_DragEnter(object? sender, DragEventArgs e)
{
try
{
if (e.Data is not null && e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
catch (Exception)
{
throw;
}
}
}

View File

@ -1,4 +1,4 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Phares.Shared;
using ShellProgressBar;
@ -61,144 +61,6 @@ public class DuplicateSearch
File.WriteAllText(Path.Combine(alongSideDirectory, $"{directoryName}-{ticks}.json"), json);
}
private static Container.Models.Container[] GetContainers(long ticks, Configuration configuration)
{
int f;
Container.Models.Container[] containers;
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
string message = $") Building Container(s) - {totalSeconds} total second(s)";
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
using (ProgressBar progressBar = new(1, message, options))
{
progressBar.Tick();
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
(f, containers) = Container.Models.Stateless.Methods.IContainer.GetContainers(configuration, aPropertySingletonDirectory);
}
return containers;
}
private static List<int> GetPreloadIds(string destinationRoot)
{
List<int> results = [];
string[] lines;
string preloadDirectory = Path.Combine(destinationRoot, "Preload");
if (!Directory.Exists(preloadDirectory))
_ = Directory.CreateDirectory(preloadDirectory);
string[] files = Directory.GetFiles(preloadDirectory, "*.lsv", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
lines = File.ReadAllLines(file);
foreach (string line in lines)
{
if (string.IsNullOrEmpty(line) || !int.TryParse(line, out int id) || id == 0)
continue;
results.Add(id);
}
}
return results;
}
private static Dictionary<int, List<MappingFromItem?>> GetIdToCollection(string argZero, Configuration configuration, bool argZeroIsConfigurationRootDirectory, Container.Models.Container[] containers, string destinationRoot, List<int> preloadIds)
{
Dictionary<int, List<MappingFromItem?>> results = [];
string directory;
const int zero = 0;
FileHolder resizedFileHolder;
DateTime[] containerDateTimes;
MappingFromItem? mappingFromItem;
List<MappingFromItem?>? collection;
ReadOnlyCollection<Item> validImageItems;
const string duplicates = "-Duplicate(s)";
if (containers.Length != 0)
{
foreach (int id in preloadIds)
results.Add(id, [null]);
}
foreach (Container.Models.Container container in containers)
{
if (container.Items.Count == 0)
continue;
if (!argZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
continue;
validImageItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(configuration, container);
if (validImageItems.Count == 0)
continue;
containerDateTimes = Container.Models.Stateless.Methods.IContainer.GetContainerDateTimes(validImageItems);
foreach (Item item in validImageItems)
{
if (item.ExifDirectory?.FilePath.Id is null)
{
if (int.TryParse(item.FilePath.NameWithoutExtension, out int id))
continue;
continue;
}
if (!results.TryGetValue(item.ExifDirectory.FilePath.Id.Value, out collection))
results.Add(item.ExifDirectory.FilePath.Id.Value, []);
if (collection is null && !results.TryGetValue(item.ExifDirectory.FilePath.Id.Value, out collection))
continue;
if (collection.Count == 0)
directory = $"0{duplicates}";
else
directory = $"{collection.Count + 1}{duplicates}";
if (collection.Count == 1)
{
mappingFromItem = collection[zero];
if (mappingFromItem is not null)
{
resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}"));
collection[0] = new(mappingFromItem.ContainerDateTimes, item.Property.DateTimeDigitized, item.Property.DateTimeOriginal, mappingFromItem.Id, mappingFromItem.IsArchive, mappingFromItem.FilePath, mappingFromItem.IsWrongYear, item.Property.Keywords ?? [], mappingFromItem.MinimumDateTime, item.Property.Model, mappingFromItem.RelativePath, resizedFileHolder);
}
}
resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath));
mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
collection.Add(mappingFromItem);
}
}
return results;
}
private static void QuestionMove(long ticks, ILogger<Program>? logger, string destinationRoot, Dictionary<int, List<MappingFromItem?>> idToCollection, int duplicates)
{
int[] ids = (from l in idToCollection orderby l.Key where l.Value.Any(m => m is not null) select l.Key).ToArray();
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(destinationRoot, $"{ticks}-id(s).lsv"), string.Join(Environment.NewLine, ids), updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
string json = JsonSerializer.Serialize(idToCollection, new JsonSerializerOptions { WriteIndented = true });
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(destinationRoot, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
logger?.LogInformation($"Found {duplicates} duplicate file(s)");
for (int y = 0; y < int.MaxValue; y++)
{
logger?.LogInformation("Press \"Y\" key to continue or close console to leave them moved");
if (System.Console.ReadKey().Key != ConsoleKey.Y)
continue;
logger?.LogInformation(". . .");
List<(FilePath FilePath, string Destination)> collection = GetCollectionAndCreateDirectories(idToCollection);
Move(logger, ticks, destinationRoot, collection);
}
}
private static List<(FilePath FilePath, string Destination)> GetCollectionAndCreateDirectories(Dictionary<int, List<MappingFromItem?>> idToCollection)
{
List<(FilePath FilePath, string Destination)> results = [];
List<string> collection = [];
foreach (KeyValuePair<int, List<MappingFromItem?>> keyValuePair in idToCollection)
{
foreach (MappingFromItem? mappingFromItem in keyValuePair.Value)
{
if (mappingFromItem?.ResizedFileHolder.DirectoryFullPath is null)
continue;
if (mappingFromItem.ResizedFileHolder.Exists)
continue;
collection.Add(mappingFromItem.ResizedFileHolder.DirectoryFullPath);
results.Add(new(mappingFromItem.FilePath, mappingFromItem.ResizedFileHolder.FullName));
}
}
foreach (string directory in collection.Distinct())
{
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
}
return results;
}
private static void Move(ILogger<Program>? logger, long ticks, string destinationRoot, List<(FilePath FilePath, string Destination)> collection)
{
StringBuilder stringBuilder = new();
@ -245,4 +107,142 @@ public class DuplicateSearch
logger?.LogInformation(". . .");
}
private static void QuestionMove(long ticks, ILogger<Program>? logger, string destinationRoot, Dictionary<int, List<MappingFromItem?>> idToCollection, int duplicates)
{
int[] ids = (from l in idToCollection orderby l.Key where l.Value.Any(m => m is not null) select l.Key).ToArray();
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(destinationRoot, $"{ticks}-id(s).lsv"), string.Join(Environment.NewLine, ids), updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
string json = JsonSerializer.Serialize(idToCollection, new JsonSerializerOptions { WriteIndented = true });
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(destinationRoot, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
logger?.LogInformation($"Found {duplicates} duplicate file(s)");
for (int y = 0; y < int.MaxValue; y++)
{
logger?.LogInformation("Press \"Y\" key to continue or close console to leave them moved");
if (System.Console.ReadKey().Key != ConsoleKey.Y)
continue;
logger?.LogInformation(". . .");
List<(FilePath FilePath, string Destination)> collection = GetCollectionAndCreateDirectories(idToCollection);
Move(logger, ticks, destinationRoot, collection);
}
}
private static Container.Models.Container[] GetContainers(long ticks, Configuration configuration)
{
int f;
Container.Models.Container[] containers;
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
string message = $") Building Container(s) - {totalSeconds} total second(s)";
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
using (ProgressBar progressBar = new(1, message, options))
{
progressBar.Tick();
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
(f, containers) = Container.Models.Stateless.Methods.IContainer.GetContainers(configuration, aPropertySingletonDirectory);
}
return containers;
}
private static Dictionary<int, List<MappingFromItem?>> GetIdToCollection(string argZero, Configuration configuration, bool argZeroIsConfigurationRootDirectory, Container.Models.Container[] containers, string destinationRoot, List<int> preloadIds)
{
Dictionary<int, List<MappingFromItem?>> results = [];
string directory;
const int zero = 0;
FileHolder resizedFileHolder;
DateTime[] containerDateTimes;
MappingFromItem? mappingFromItem;
List<MappingFromItem?>? collection;
ReadOnlyCollection<Item> validImageItems;
const string duplicates = "-Duplicate(s)";
if (containers.Length != 0)
{
foreach (int id in preloadIds)
results.Add(id, [null]);
}
foreach (Container.Models.Container container in containers)
{
if (container.Items.Count == 0)
continue;
if (!argZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
continue;
validImageItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(configuration, container);
if (validImageItems.Count == 0)
continue;
containerDateTimes = Container.Models.Stateless.Methods.IContainer.GetContainerDateTimes(validImageItems);
foreach (Item item in validImageItems)
{
if (item.Property?.Id is null)
{
if (int.TryParse(item.FilePath.NameWithoutExtension, out int id))
continue;
continue;
}
if (!results.TryGetValue(item.Property.Id.Value, out collection))
results.Add(item.Property.Id.Value, []);
if (collection is null && !results.TryGetValue(item.Property.Id.Value, out collection))
continue;
if (collection.Count == 0)
directory = $"0{duplicates}";
else
directory = $"{collection.Count + 1}{duplicates}";
if (collection.Count == 1)
{
mappingFromItem = collection[zero];
if (mappingFromItem is not null)
{
resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}"));
collection[0] = new(mappingFromItem.ContainerDateTimes, item.Property.DateTimeDigitized, item.Property.DateTimeOriginal, mappingFromItem.Id, mappingFromItem.IsArchive, mappingFromItem.FilePath, mappingFromItem.IsWrongYear, item.Property.Keywords ?? [], mappingFromItem.MinimumDateTime, item.Property.Model, mappingFromItem.RelativePath, resizedFileHolder);
}
}
resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath));
mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
collection.Add(mappingFromItem);
}
}
return results;
}
private static List<(FilePath FilePath, string Destination)> GetCollectionAndCreateDirectories(Dictionary<int, List<MappingFromItem?>> idToCollection)
{
List<(FilePath FilePath, string Destination)> results = [];
List<string> collection = [];
foreach (KeyValuePair<int, List<MappingFromItem?>> keyValuePair in idToCollection)
{
foreach (MappingFromItem? mappingFromItem in keyValuePair.Value)
{
if (mappingFromItem?.ResizedFileHolder.DirectoryFullPath is null)
continue;
if (mappingFromItem.ResizedFileHolder.Exists)
continue;
collection.Add(mappingFromItem.ResizedFileHolder.DirectoryFullPath);
results.Add(new(mappingFromItem.FilePath, mappingFromItem.ResizedFileHolder.FullName));
}
}
foreach (string directory in collection.Distinct())
{
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
}
return results;
}
private static List<int> GetPreloadIds(string destinationRoot)
{
List<int> results = [];
string[] lines;
string preloadDirectory = Path.Combine(destinationRoot, "Preload");
if (!Directory.Exists(preloadDirectory))
_ = Directory.CreateDirectory(preloadDirectory);
string[] files = Directory.GetFiles(preloadDirectory, "*.lsv", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
lines = File.ReadAllLines(file);
foreach (string line in lines)
{
if (string.IsNullOrEmpty(line) || !int.TryParse(line, out int id) || id == 0)
continue;
results.Add(id);
}
}
return results;
}
}

View File

@ -264,7 +264,7 @@ public class D_Face : IFaceD
}
}
public List<Shared.Models.Face> GetFaces(string outputResolution, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, ExifDirectory exifDirectory, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
public List<Shared.Models.Face> GetFaces(string outputResolution, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
{
List<Shared.Models.Face>? results;
string? json;
@ -314,7 +314,7 @@ public class D_Face : IFaceD
locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(results, mappingFromPhotoPrismCollection, _RectangleIntersectMinimum);
if (results is null || locations.Count > 0)
{
results = GetFaces(outputResolution, cResultsFullGroupDirectory, exifDirectory, mappingFromItem, outputResolutionToResize, locations);
results = GetFaces(outputResolution, cResultsFullGroupDirectory, property, mappingFromItem, outputResolutionToResize, locations);
if (results.Count == 0)
File.Move(mappingFromItem.ResizedFileHolder.FullName, $"{mappingFromItem.ResizedFileHolder.FullName}.err");
else
@ -338,7 +338,7 @@ public class D_Face : IFaceD
return results;
}
private List<Shared.Models.Face> GetFaces(string outputResolution, string cResultsFullGroupDirectory, ExifDirectory exifDirectory, 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)
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfJitters));
@ -374,7 +374,7 @@ public class D_Face : IFaceD
FaceRecognition faceRecognition = new(_PropertyConfiguration.NumberOfJitters.Value, _PropertyConfiguration.NumberOfTimesToUpsample.Value, _Model, _ModelParameter, _PredictorModel);
collection = faceRecognition.GetCollection(unknownImage, locations, includeFaceEncoding: true, includeFaceParts: true);
if (collection.Count == 0)
results.Add(new(exifDirectory, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null));
results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null));
else
{
double[] rawEncoding;
@ -382,7 +382,7 @@ public class D_Face : IFaceD
Shared.Models.FaceEncoding convertedFaceEncoding;
foreach ((Location location, FaceRecognitionDotNet.FaceEncoding? faceEncoding, Dictionary<FacePart, FacePoint[]>? faceParts) in collection)
{
face = new(exifDirectory, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location);
face = new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location);
if (faceEncoding is not null)
{
rawEncoding = faceEncoding.GetRawEncoding();

View File

@ -25,12 +25,10 @@ namespace View_by_Distance.Instance;
public partial class DlibDotNet : IDlibDotNet, IDisposable
{
public record Record(ReadOnlyDictionary<int, ExifDirectory> ExifDirectoriesById,
string FilesCollectionRootDirectory,
public record Record(string FilesCollectionRootDirectory,
bool FilesCollectionCountIsOne,
ReadOnlyCollection<ReadOnlyCollection<FilePath>> FilePathsCollection,
ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? IdToFilePaths,
ReadOnlyDictionary<int, Identifier>? SplatNineIdentifiers);
ReadOnlyDictionary<int, ExifDirectory> ExifDirectoriesById);
private readonly D_Face _Faces;
private ProgressBar? _ProgressBar;
@ -64,11 +62,11 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
{
string message;
_Logger = logger;
_Exceptions = [];
_Console = console;
_AppSettings = appSettings;
_IsEnvironment = isEnvironment;
long ticks = DateTime.Now.Ticks;
_Exceptions = [];
_JLinkResolvedDirectories = [];
if (ticks.ToString().Last() == '0')
ticks += 1;
@ -173,7 +171,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
_Logger?.LogInformation("First run completed. Run again if wanted");
}
private int FullParallelForWork(B_Metadata metadata,
private int FullParallelForWork(A_Property propertyLogic,
B_Metadata metadata,
MapLogic mapLogic,
string outputResolution,
bool outputResolutionHasNumber,
@ -181,47 +180,60 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
string d2ResultsFullGroupDirectory,
List<Tuple<string, DateTime>> sourceDirectoryChanges,
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection,
Record record,
ReadOnlyDictionary<int, ExifDirectory> exifDirectoriesById,
Container.Models.Container container,
Item item,
DateTime[] containerDateTimes,
bool? isFocusRelativePath)
{
int result = 0;
bool? shouldIgnore;
List<Shared.Models.Face> faces;
long ticks = DateTime.Now.Ticks;
DateTime dateTime = DateTime.Now;
Shared.Models.Property? property;
List<string> parseExceptions = [];
string[] changesFrom = [nameof(A_Property)];
List<Tuple<string, DateTime>> subFileTuples = [];
FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber);
if (item.ExifDirectory is null || item.ExifDirectory.FilePath.Id is null || !item.SourceDirectoryFileHolder.Exists || item.SourceDirectoryFileHolder.CreationTime is null || item.SourceDirectoryFileHolder.LastWriteTime is null || item.Any())
throw new Exception();
if (_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime && item.SourceDirectoryFileHolder.LastWriteTime.Value != item.SourceDirectoryFileHolder.CreationTime.Value)
if (item.Property is null || item.Property.Id is null || !item.SourceDirectoryFileHolder.Exists || item.SourceDirectoryFileHolder.CreationTime is null || item.SourceDirectoryFileHolder.LastWriteTime is null || item.Any())
{
File.SetLastWriteTime(item.SourceDirectoryFileHolder.FullName, item.SourceDirectoryFileHolder.CreationTime.Value);
subFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), item.SourceDirectoryFileHolder.CreationTime.Value));
}
else if (item.SourceDirectoryFileHolder.LastWriteTime is not null)
subFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), item.SourceDirectoryFileHolder.LastWriteTime.Value));
else
subFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), new FileInfo(item.SourceDirectoryFileHolder.FullName).LastWriteTime));
if (resizedFileHolder.Exists && item.ExifDirectory.Width is not null && item.ExifDirectory.Width.Value > 4 && _Configuration.SaveBlurHashForOutputResolutions.Contains(outputResolution))
{
string? file = _BlurHasher.GetFile(item.FilePath);
if (file is not null && !File.Exists(file))
_ = _BlurHasher.EncodeAndSave(item.FilePath, resizedFileHolder);
}
if (item.FilePath.Id is null || !record.ExifDirectoriesById.TryGetValue(item.FilePath.Id.Value, out ExifDirectory? exifDirectory))
{
shouldIgnore = null;
exifDirectory = null;
LogItemPropertyIsNull(item);
int? propertyHashCode = item.Property?.GetHashCode();
property = propertyLogic.GetProperty(metadata, item, subFileTuples, parseExceptions);
item.Update(property);
if (propertyHashCode is null)
{
lock (sourceDirectoryChanges)
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
}
else if (propertyHashCode.Value != property.GetHashCode())
{
lock (sourceDirectoryChanges)
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
}
}
else
{
ReadOnlyCollection<string> keywords = IMetaBase.GetKeywords(exifDirectory.ExifBaseDirectories);
shouldIgnore = _Configuration.PropertyConfiguration.IgnoreRulesKeyWords.Any(keywords.Contains);
property = item.Property;
if (_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime && item.SourceDirectoryFileHolder.LastWriteTime.Value != item.SourceDirectoryFileHolder.CreationTime.Value)
{
File.SetLastWriteTime(item.SourceDirectoryFileHolder.FullName, item.SourceDirectoryFileHolder.CreationTime.Value);
subFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), item.SourceDirectoryFileHolder.CreationTime.Value));
}
else if (item.SourceDirectoryFileHolder.LastWriteTime is not null)
subFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), item.SourceDirectoryFileHolder.LastWriteTime.Value));
else
subFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), new FileInfo(item.SourceDirectoryFileHolder.FullName).LastWriteTime));
if (resizedFileHolder.Exists && item.Property.Width is not null && item.Property.Width.Value > 4 && _Configuration.SaveBlurHashForOutputResolutions.Contains(outputResolution))
{
string? file = _BlurHasher.GetFile(item.FilePath);
if (file is not null && !File.Exists(file))
_ = _BlurHasher.EncodeAndSave(item.FilePath, resizedFileHolder);
}
}
bool? shouldIgnore = property is null || property.Keywords is null ? null : _Configuration.PropertyConfiguration.IgnoreRulesKeyWords.Any(l => property.Keywords.Contains(l));
if (shouldIgnore is not null)
{
if (shouldIgnore.Value)
{
FileInfo fileInfo = new(resizedFileHolder.FullName);
@ -236,9 +248,12 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
throw new NotSupportedException($"Rename File! <{item.FilePath.FileNameFirstSegment}>");
}
}
if (property is null || item.Property is null)
throw new NullReferenceException(nameof(property));
item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder);
MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
exifDirectory ??= metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
if (item.FilePath.Id is null || !exifDirectoriesById.TryGetValue(item.FilePath.Id.Value, out ExifDirectory? exifDirectory))
exifDirectory = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
if (_AppSettings.Places.Count > 0)
{
float latitude;
@ -261,13 +276,13 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
distance += 1;
}
}
Dictionary<string, int[]> outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.ExifDirectory, mappingFromItem);
Dictionary<string, int[]> outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem);
if (_Configuration.SaveResizedSubfiles)
{
if (shouldIgnore is not null && item.FilePath.HasIgnoreKeyword is not null && item.FilePath.HasIgnoreKeyword.Value != shouldIgnore.Value)
faces = [];
else
_Resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.ExifDirectory, mappingFromItem, outputResolutionToResize);
_Resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize);
}
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution))
faces = [];
@ -279,7 +294,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
if (!fileNameToCollection.TryGetValue(mappingFromItem.Id, out mappingFromPhotoPrismCollection))
mappingFromPhotoPrismCollection = null;
bool move = _Configuration.DistanceMoveUnableToMatch || _Configuration.DistanceRenameToMatch && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution);
faces = _Faces.GetFaces(outputResolution, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.ExifDirectory, mappingFromItem, outputResolutionToResize, mappingFromPhotoPrismCollection);
faces = _Faces.GetFaces(outputResolution, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, mappingFromPhotoPrismCollection);
result = GetNotMappedCountAndUpdateMappingFromPersonThenSetMapping(mapLogic, item, isFocusRelativePath, mappingFromItem, mappingFromPhotoPrismCollection, faces);
List<(Shared.Models.Face, FileHolder?, string, bool Saved)> faceCollection = _Faces.SaveFaces(item.FilePath, subFileTuples, parseExceptions, mappingFromItem, exifDirectory, faces);
if (move && faceCollection.All(l => !l.Saved))
@ -312,6 +327,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
}
private (int, bool) FullParallelWork(int maxDegreeOfParallelism,
A_Property propertyLogic,
B_Metadata metadata,
MapLogic mapLogic,
string outputResolution,
@ -320,7 +336,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
string d2ResultsFullGroupDirectory,
List<Tuple<string, DateTime>> sourceDirectoryChanges,
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection,
Record record,
ReadOnlyDictionary<int, ExifDirectory> exifDirectoriesById,
Container.Models.Container container,
ReadOnlyCollection<Item> filteredItems,
string message)
@ -337,7 +353,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
{
try
{
result += FullParallelForWork(metadata,
result += FullParallelForWork(propertyLogic,
metadata,
mapLogic,
outputResolution,
outputResolutionHasNumber,
@ -345,7 +362,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
d2ResultsFullGroupDirectory,
sourceDirectoryChanges,
fileNameToCollection,
record,
exifDirectoriesById,
container,
filteredItems[i],
containerDateTimes,
@ -366,11 +383,13 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
private void FullDoWork(string argZero,
string propertyRoot,
long ticks,
string aResultsFullGroupDirectory,
string fPhotoPrismSingletonDirectory,
int count,
B_Metadata metadata,
Record record,
ReadOnlyDictionary<int, ExifDirectory> exifDirectoriesById,
ReadOnlyCollection<Container.Models.Container> readOnlyContainers,
A_Property propertyLogic,
MapLogic mapLogic)
{
int total;
@ -415,9 +434,11 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
anyNullOrNoIsUniqueFileName = filteredItems.Any(l => !l.IsUniqueFileName);
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
message = $"{totalSeconds} total second(s) - {outputResolution} - {i + 1:000} / {readOnlyContainers.Count:000} - {total} / {count} total - <{container.SourceDirectory}> [{filteredItems.Count:000}] - total not mapped {totalNotMapped:000000}";
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, container.SourceDirectory, anyNullOrNoIsUniqueFileName);
if (outputResolutionHasNumber)
_Resize.SetAngleBracketCollection(cResultsFullGroupDirectory, container.SourceDirectory);
(notMapped, exceptions) = FullParallelWork(maxDegreeOfParallelism,
propertyLogic,
metadata,
mapLogic,
outputResolution,
@ -426,7 +447,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
d2ResultsFullGroupDirectory,
sourceDirectoryChanges,
fileNameToCollection,
record,
exifDirectoriesById,
container,
filteredItems,
message);
@ -688,11 +709,11 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
foreach (Item item in distinctFilteredItems)
{
found = false;
if (item.ExifDirectory?.FilePath.Id is null)
if (item.Property?.Id is null)
continue;
foreach (Mapping mapping in distinctFilteredMappingCollection)
{
if (mapping.MappingFromItem.Id != item.ExifDirectory.FilePath.Id.Value)
if (mapping.MappingFromItem.Id != item.Property.Id.Value)
continue;
found = true;
break;
@ -707,15 +728,13 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
string fileName;
string directory;
bool? isWrongYear;
DateTime? dateTime;
string? exifDirectoryModel;
List<DateTime> dateTimes;
List<string> distinct = [];
WindowsShortcut windowsShortcut;
ReadOnlyCollection<DateTime> dateTimes;
List<(string, string, string)> collection = [];
foreach (Item item in distinctValidImageItems)
{
if (item.ExifDirectory?.FilePath.Id is null)
if (item.Property?.Id is null)
continue;
if (item.IsNotUniqueAndNeedsReview is null || !item.IsNotUniqueAndNeedsReview.Value)
continue;
@ -728,19 +747,15 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
}
foreach (Item item in distinctValidImageItems)
{
if (item.ExifDirectory?.FilePath.Id is null)
if (item.Property?.Id is null || item.Property.DateTimeOriginal is null)
continue;
dateTime = IDate.GetDateTimeOriginal(item.ExifDirectory);
if (dateTime is null)
continue;
dateTimes = IDate.GetDateTimes(item.ExifDirectory);
(isWrongYear, _) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(item.FilePath, dateTime, dateTimes.ToList());
dateTimes = item.Property.GetDateTimes();
(isWrongYear, _) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(item.FilePath, item.Property.DateTimeOriginal, dateTimes);
if (isWrongYear is null || !isWrongYear.Value)
continue;
// Remove-Item -LiteralPath "\\?\D:\Tmp\a\EX-Z70 "
exifDirectoryModel = IMetaBase.GetModel(item.ExifDirectory?.ExifBaseDirectories);
model = string.IsNullOrEmpty(exifDirectoryModel) ? "Unknown" : CameraRegex().Replace(exifDirectoryModel.Trim(), "_");
directory = Path.Combine($"{eDistanceContentDirectory[..^1]}{nameof(Item)})", dateTime.Value.Year.ToString(), model);
model = string.IsNullOrEmpty(item.Property.Model) ? "Unknown" : CameraRegex().Replace(item.Property.Model.Trim(), "_");
directory = Path.Combine($"{eDistanceContentDirectory[..^1]}{nameof(Item)})", item.Property.DateTimeOriginal.Value.Year.ToString(), model);
fileName = item.IsNotUniqueAndNeedsReview is not null && item.IsNotUniqueAndNeedsReview.Value ? Path.Combine(directory, $"{item.FilePath.Name} {item.FilePath.Length}.lnk") : Path.Combine(directory, $"{item.FilePath.Name}.lnk");
collection.Add((item.FilePath.FullName, directory, fileName));
if (distinct.Contains(directory))
@ -909,19 +924,15 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
return results;
}
private bool? GetIsFocusModel(ExifDirectory? exifDirectory)
private bool? GetIsFocusModel(Shared.Models.Property? property)
{
bool? result;
if (string.IsNullOrEmpty(_Configuration.FocusModel))
result = null;
else if (property is null || string.IsNullOrEmpty(property.Model))
result = null;
else
{
string? model = IMetaBase.GetModel(exifDirectory?.ExifBaseDirectories);
if (exifDirectory is null || string.IsNullOrEmpty(model))
result = null;
else
result = model.Contains(_Configuration.FocusModel);
}
result = property.Model.Contains(_Configuration.FocusModel);
return result;
}
@ -1088,6 +1099,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
bool configurationOutputResolutionsHas = false;
ReadOnlyDictionary<long, List<int>> personKeyToIds;
(int season, string seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers = null;
ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs = null;
string[] checkDirectories =
[
Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, "Ancestry"),
@ -1114,6 +1127,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
if (!runToDoCollectionFirst)
break;
record = GetFilesCollectionThenCopyOrMove(dlibDotNet, ticks, fileSearchFilter, directorySearchFilter, bResultsFullGroupDirectory, outputResolution);
keyValuePairs = FilePath.GetKeyValuePairs(record.FilePathsCollection);
splatNineIdentifiers = GetSplatNineIdentifiersAndHideSplatNine(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, keyValuePairs);
break;
}
fPhotoPrismContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), _Configuration.PropertyConfiguration.ResultContent);
@ -1152,9 +1167,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
record = new(FilesCollectionRootDirectory: filesCollectionRootDirectory,
FilesCollectionCountIsOne: false,
FilePathsCollection: filePathsCollection,
ExifDirectoriesById: new(exifDirectoriesById),
IdToFilePaths: null,
SplatNineIdentifiers: null);
ExifDirectoriesById: new(exifDirectoriesById));
break;
}
}
@ -1176,8 +1189,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
_Faces.HiddenFileNameExtension,
eDistanceContentDirectory,
record.FilesCollectionRootDirectory,
record.IdToFilePaths,
record.SplatNineIdentifiers,
keyValuePairs,
splatNineIdentifiers,
record.FilePathsCollection,
record.ExifDirectoriesById);
_ProgressBar.Dispose();
@ -1188,11 +1201,13 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
FullDoWork(argZero,
propertyRoot,
ticks,
aResultsFullGroupDirectory,
fPhotoPrismSingletonDirectory,
count,
metadata,
record,
record.ExifDirectoriesById,
readOnlyContainers,
propertyLogic,
mapLogic);
ReadOnlyCollection<Item> distinctValidImageItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true);
if (_Configuration.LookForAbandoned)
@ -1234,8 +1249,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
&& _Exceptions.Count == 0)
MapLogic(ticks, readOnlyContainers, fPhotoPrismContentDirectory, mapLogic, outputResolution, new(personKeyToIds), distinctValidImageFaces, distinctValidImageMappingCollection);
if (runToDoCollectionFirst && _Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Count > 0 && record?.SplatNineIdentifiers is not null && distinctValidImageMappingCollection.Count > 0)
_Random.Random(_Configuration.PropertyConfiguration, _Configuration.ImmichAssetsFile, _Configuration.ImmichOwnerId, _Configuration.ImmichRoot, _Configuration.RadomUseBirthdayMinimum, _Configuration.ValidKeyWordsToIgnoreInRandom, personKeyToIds, record.SplatNineIdentifiers, distinctValidImageMappingCollection);
if (runToDoCollectionFirst && _Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Count > 0 && splatNineIdentifiers is not null && distinctValidImageMappingCollection.Count > 0)
_Random.Random(_Configuration.PropertyConfiguration, _Configuration.ImmichAssetsFile, _Configuration.ImmichOwnerId, _Configuration.ImmichRoot, _Configuration.RadomUseBirthdayMinimum, _Configuration.ValidKeyWordsToIgnoreInRandom, personKeyToIds, splatNineIdentifiers, distinctValidImageMappingCollection);
if (_IsEnvironment.Development)
continue;
if (!_IsEnvironment.Development)
@ -1294,14 +1309,10 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
progressBar = new(count, message, _ProgressBarOptions);
_ = IDirectory.CopyOrMove(toDoCollection, move: false, moveBack: false, () => progressBar.Tick());
progressBar.Dispose();
ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>> idToFilePaths = FilePath.GetKeyValuePairs(filePathsCollection);
ReadOnlyDictionary<int, Identifier> splatNineIdentifiers = GetSplatNineIdentifiersAndHideSplatNine(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, idToFilePaths);
result = new(ExifDirectoriesById: new(exifDirectoriesById),
FilesCollectionRootDirectory: filesCollectionRootDirectory,
result = new(FilesCollectionRootDirectory: filesCollectionRootDirectory,
FilesCollectionCountIsOne: filesCollectionCountIsOne,
FilePathsCollection: filePathsCollection,
IdToFilePaths: idToFilePaths,
SplatNineIdentifiers: splatNineIdentifiers);
ExifDirectoriesById: new(exifDirectoriesById));
return result;
}
@ -1403,14 +1414,14 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
foreach (Item item in filteredItems)
{
if (item.ExifDirectory?.FilePath.Id is null || item.ResizedFileHolder is null)
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
mappingFromItem = IMappingFromItem.GetMappingFromItem(containerDateTimes, item, item.ResizedFileHolder);
if (distinctItems)
{
if (distinct.Contains(item.ExifDirectory.FilePath.Id.Value))
if (distinct.Contains(item.Property.Id.Value))
continue;
distinct.Add(item.ExifDirectory.FilePath.Id.Value);
distinct.Add(item.Property.Id.Value);
}
count++;
anyValidFaces = false;
@ -1442,7 +1453,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
bool? eyeReview = null;
int confidencePercent = 0;
int faceAreaPermyriad = 0;
bool? isFocusModel = GetIsFocusModel(item.ExifDirectory);
bool? isFocusModel = GetIsFocusModel(item.Property);
long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray();
int wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(Shared.Models.Stateless.ILocation.Digits);
string deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.FilePath, Shared.Models.Stateless.ILocation.Digits);
@ -1598,12 +1609,12 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
MappingFromLocation? mappingFromLocation;
MappingFromFilterPre mappingFromFilterPre;
MappingFromFilterPost mappingFromFilterPost;
bool? isFocusModel = GetIsFocusModel(item.ExifDirectory);
ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(item.ExifDirectory?.FilePath.Id);
bool? isFocusModel = GetIsFocusModel(item.Property);
ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(item.Property?.Id);
long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray();
foreach (Shared.Models.Face face in faces)
{
if (item.ExifDirectory?.FilePath.Id is null || face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
if (item.Property?.Id is null || face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
{
canReMap = null;
isFocusPerson = null;
@ -1626,7 +1637,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.FilePath, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle);
inSkipCollection = mapLogic.InSkipCollection(item.ExifDirectory.FilePath.Id.Value, mappingFromLocation);
inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation);
mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath);
canReMap = Map.Models.Stateless.Methods.IMapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);
isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);

View File

@ -55,6 +55,7 @@
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\PhotoPrism\PhotoPrism.csproj" />
<ProjectReference Include="..\Property-Compare\Property-Compare.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Resize\Resize.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup>

View File

@ -320,12 +320,12 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
public ReadOnlyCollection<LocationContainer> GetLocationContainers(Item item)
{
LocationContainer[] results;
if (item.ExifDirectory?.FilePath.Id is null)
if (item.Property?.Id is null)
results = [];
else
{
List<LocationContainer>? locationContainers;
if (_IdToLocationContainers.TryGetValue(item.ExifDirectory.FilePath.Id.Value, out locationContainers))
if (_IdToLocationContainers.TryGetValue(item.Property.Id.Value, out locationContainers))
results = locationContainers.ToArray();
else
results = [];

View File

@ -110,7 +110,7 @@ internal abstract class MapLogic
List<Face> results = [];
foreach (Item item in items)
{
if (item.ExifDirectory?.FilePath.Id is null || item.ResizedFileHolder is null)
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
foreach (Face face in item.Faces)
{

View File

@ -35,7 +35,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
private readonly ReadOnlyDictionary<byte, ReadOnlyCollection<string>>[] _ResultSingletonFileGroups;
public B_Metadata(IDlibDotNet? dlibDotNet, IPropertyConfiguration propertyConfiguration, bool forceMetadataLastWriteTimeToCreationTime, bool propertiesChangedForMetadata, long ticks, string bResultsFullGroupDirectory)
public B_Metadata(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, bool forceMetadataLastWriteTimeToCreationTime, bool propertiesChangedForMetadata, long ticks, string bResultsFullGroupDirectory)
{
_PropertyConfiguration = propertyConfiguration;
_PropertiesChangedForMetadata = propertiesChangedForMetadata;
@ -68,7 +68,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
ReadOnlyDictionary<int, List<FilePath>> fileNamesToFiles = FilePath.GetFilesKeyValuePairs(filePathsCollection);
ReadOnlyCollection<FilePair> filePairs = IFilePair.GetFilePairs(propertyConfiguration, directorySearchFilter, extension, jsonGroupSingletonDirectory, filePathsCollection, fileNamesToFiles);
string message = $") Preloading ExifDirectory Dictionary - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
dlibDotNet?.ConstructProgressBar(filePairs.Count, message);
dlibDotNet.ConstructProgressBar(filePairs.Count, message);
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(dlibDotNet, filePairs[i], results));
jsonGroupDirectory = Path.Combine(bResultsFullGroupDirectory, propertyConfiguration.ResultCollection);
foreach (ExifDirectory exifDirectory in results)
@ -86,7 +86,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
Collection = filePathsSingletonCollection[0];
}
private void ParallelFor(IDlibDotNet? dlibDotNet, FilePair filePair, List<ExifDirectory> results)
private void ParallelFor(IDlibDotNet dlibDotNet, FilePair filePair, List<ExifDirectory> results)
{
dlibDotNet?.Tick();
if (filePair.FilePath.Id is null)

View File

@ -66,7 +66,6 @@ public class A_Property
converted: false));
}
[Obsolete("Use ExifDirectory")]
public void SavePropertyParallelWork(long ticks, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, int t, Container.Models.Container[] containers)
{
int total = 0;
@ -112,7 +111,6 @@ public class A_Property
SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName);
}
[Obsolete("Use ExifDirectory")]
private void SavePropertyParallelWork(int maxDegreeOfParallelism, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, Container.Models.Container container, ReadOnlyCollection<Item> items, string message)
{
List<Tuple<string, DateTime>> sourceDirectoryFileTuples = [];
@ -142,7 +140,6 @@ public class A_Property
});
}
[Obsolete("Use ExifDirectory")]
private void SavePropertyParallelForWork(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, string sourceDirectory, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item item)
{
Shared.Models.Property property;
@ -151,17 +148,16 @@ public class A_Property
string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{item.FilePath.NameWithoutExtension}{item.FilePath.ExtensionLowered}");
if (item.IsValidImageFormatExtension && item.FilePath.FullName.Length == filteredSourceDirectoryFileExtensionLowered.Length && item.FilePath.FullName != filteredSourceDirectoryFileExtensionLowered)
File.Move(item.FilePath.FullName, filteredSourceDirectoryFileExtensionLowered);
if (item.FileSizeChanged is null || item.FileSizeChanged.Value || item.LastWriteTimeChanged is null || item.LastWriteTimeChanged.Value || item.ExifDirectory is null)
if (item.FileSizeChanged is null || item.FileSizeChanged.Value || item.LastWriteTimeChanged is null || item.LastWriteTimeChanged.Value || item.Property is null)
{
property = GetImageProperty(metadata, item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension);
lock (sourceDirectoryChanges)
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
lock (item)
item.Update(null);
item.Update(property);
}
}
[Obsolete("Use ExifDirectory")]
private Shared.Models.Property GetImageProperty(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension)
{
Shared.Models.Property? result;
@ -206,8 +202,8 @@ public class A_Property
json = File.ReadAllText(fileInfo.FullName);
try
{
if (item.ExifDirectory is not null)
result = null;
if (item.Property is not null)
result = item.Property;
else
result = JsonSerializer.Deserialize(json, PropertyGenerationContext.Default.Property);
if (result is not null && json.Contains("WrongYear"))
@ -305,7 +301,6 @@ public class A_Property
}
}
[Obsolete("Use ExifDirectory")]
public Shared.Models.Property GetProperty(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions)
{
Shared.Models.Property result;

View File

@ -21,9 +21,9 @@ internal partial class Property
List<long> ticksCollection = [];
foreach (Item item in container.Items)
{
if (item.ExifDirectory is null)
if (item.Property is null)
continue;
minimumDateTime = Shared.Models.Stateless.Methods.IDate.GetMinimum(item.ExifDirectory);
minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
if (minimumDateTime is null)
continue;
ticksCollection.Add(minimumDateTime.Value.Ticks);
@ -195,17 +195,17 @@ internal partial class Property
{
ticks = null;
item = container.Items[j];
if (item.ExifDirectory is null)
if (item.Property is null)
continue;
minimumDateTime = Shared.Models.Stateless.Methods.IDate.GetMinimum(item.ExifDirectory);
minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
if (minimumDateTime is null)
continue;
for (int k = j + 1; k < container.Items.Count; k++)
{
nextItem = container.Items[k];
if (nextItem.ExifDirectory is null)
if (nextItem.Property is null)
continue;
nextMinimumDateTime = Shared.Models.Stateless.Methods.IDate.GetMinimum(nextItem.ExifDirectory);
nextMinimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(nextItem.Property);
if (nextMinimumDateTime is null)
continue;
ticks = nextMinimumDateTime.Value.Ticks;

View File

@ -191,7 +191,7 @@ public class C_Resize
public FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, Item item, bool outputResolutionHasNumber) =>
GetResizedFileHolder(cResultsFullGroupDirectory, item.FilePath, outputResolutionHasNumber, item.FilePath.Name);
public Dictionary<string, int[]> GetResizeKeyValuePairs(Configuration configuration, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, ExifDirectory exifDirectory, MappingFromItem mappingFromItem)
public Dictionary<string, int[]> GetResizeKeyValuePairs(Configuration configuration, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem)
{
Dictionary<string, int[]>? results;
string json;
@ -238,7 +238,7 @@ public class C_Resize
}
if (results is null)
{
results = GetImageResizes(exifDirectory);
results = GetImageResizes(property);
json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions);
bool updateDateWhenMatches = dateTimes.Count != 0 && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime;
DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
@ -276,7 +276,7 @@ public class C_Resize
}
}
private Dictionary<string, int[]> GetImageResizes(ExifDirectory exifDirectory)
private Dictionary<string, int[]> GetImageResizes(Shared.Models.Property property)
{
Dictionary<string, int[]> results = [];
int[] desired;
@ -284,13 +284,13 @@ public class C_Resize
int checkHeight;
int desiredWidth;
int desiredHeight;
int? orientation = Shared.Models.Stateless.Methods.IMetaBase.GetOrientation(exifDirectory.ExifBaseDirectories);
if (exifDirectory is null || orientation is null || exifDirectory.Width is null || exifDirectory.Height is null)
int orientation = property.Orientation is null || string.IsNullOrEmpty(property.Orientation) || !int.TryParse(property.Orientation, out int propertyOrientation) ? 0 : propertyOrientation;
if (property is null || property.Width is null || property.Height is null)
throw new NotSupportedException();
checkWidth = exifDirectory.Width.Value;
checkHeight = exifDirectory.Height.Value;
checkWidth = property.Width.Value;
checkHeight = property.Height.Value;
if (!_ValidResolutions.Contains(_Original))
results.Add(_Original, [checkWidth, checkHeight, orientation.Value]);
results.Add(_Original, [checkWidth, checkHeight, orientation]);
foreach (string validResolution in _ValidResolutions)
{
if (validResolution == _Original)
@ -305,22 +305,22 @@ public class C_Resize
desiredHeight = desired[1];
}
if (checkWidth <= desiredWidth && checkHeight <= desiredHeight)
results.Add(validResolution, [checkWidth, checkHeight, orientation.Value]);
results.Add(validResolution, [checkWidth, checkHeight, orientation]);
else
{
if (desiredWidth != desiredHeight)
{
if (checkWidth * desiredHeight > desiredWidth * checkHeight)
results.Add(validResolution, [desiredWidth, Convert.ToInt32(desiredWidth * checkHeight / (double)checkWidth), orientation.Value]);
results.Add(validResolution, [desiredWidth, Convert.ToInt32(desiredWidth * checkHeight / (double)checkWidth), orientation]);
else
results.Add(validResolution, [Convert.ToInt32(desiredHeight * checkWidth / (double)checkHeight), desiredHeight, orientation.Value]);
results.Add(validResolution, [Convert.ToInt32(desiredHeight * checkWidth / (double)checkHeight), desiredHeight, orientation]);
}
else
{
if (checkWidth * desiredHeight <= desiredWidth * checkHeight)
results.Add(validResolution, [desiredWidth, desiredHeight, orientation.Value, desiredWidth, Convert.ToInt32(desiredWidth * checkHeight / (double)checkWidth)]);
results.Add(validResolution, [desiredWidth, desiredHeight, orientation, desiredWidth, Convert.ToInt32(desiredWidth * checkHeight / (double)checkWidth)]);
else
results.Add(validResolution, [desiredWidth, desiredHeight, orientation.Value, Convert.ToInt32(desiredHeight * checkWidth / (double)checkHeight), desiredHeight]);
results.Add(validResolution, [desiredWidth, desiredHeight, orientation, Convert.ToInt32(desiredHeight * checkWidth / (double)checkHeight), desiredHeight]);
}
}
}
@ -336,7 +336,7 @@ public class C_Resize
return results.ToArray();
}
public void SaveResizedSubfile(Configuration configuration, string outputResolution, string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, Item item, ExifDirectory exifDirectory, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize)
public void SaveResizedSubfile(Configuration configuration, string outputResolution, string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, Item item, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize)
{
if (mappingFromItem.ResizedFileHolder is null)
throw new NullReferenceException(nameof(mappingFromItem.ResizedFileHolder));
@ -378,19 +378,18 @@ public class C_Resize
check = true;
if (check)
{
SaveResizedSubfile(exifDirectory, mappingFromItem, resize);
SaveResizedSubfile(property, mappingFromItem, resize);
item.SetResizedFileHolder(_FileNameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(mappingFromItem.ResizedFileHolder));
subFileTuples.Add(new Tuple<string, DateTime>(nameof(C_Resize), DateTime.Now));
}
}
}
private void SaveResizedSubfile(ExifDirectory exifDirectory, MappingFromItem mappingFromItem, int[] resize)
private void SaveResizedSubfile(Shared.Models.Property property, MappingFromItem mappingFromItem, int[] resize)
{
string dateTimeFormat = IProperty.DateTimeFormat;
DateTime? dateTime = Shared.Models.Stateless.Methods.IDate.GetDateTimeOriginal(exifDirectory);
dateTime ??= Shared.Models.Stateless.Methods.IDate.GetMinimum(exifDirectory);
string dateTimeValue = dateTime.Value.ToString(dateTimeFormat);
DateTime dateTime = property.DateTimeOriginal is not null ? property.DateTimeOriginal.Value : Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
string dateTimeValue = dateTime.ToString(dateTimeFormat);
byte[] bytes = _ASCIIEncoding.GetBytes(dateTimeValue);
if (_ASCIIEncoding.GetString(bytes, 0, bytes.Length) != dateTimeValue)
throw new Exception();

View File

@ -1,4 +1,3 @@
using System.Collections.ObjectModel;
using System.Text.Json;
using System.Text.Json.Serialization;
@ -34,12 +33,13 @@ public class Face : Properties.IFace
_OutputResolution = outputResolution;
}
public Face(ExifDirectory exifDirectory, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, Location? location) :
public Face(Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, Location? location) :
this(DateTime.MinValue, null, null, null, location, null, null)
{
DateTime?[] dateTimes;
_OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth);
ReadOnlyCollection<DateTime> dateTimes = Stateless.Methods.IDate.GetDateTimes(exifDirectory);
_DateTime = dateTimes.Min();
dateTimes = [property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeFromName, property.DateTimeOriginal, property.GPSDateStamp];
_DateTime = (from l in dateTimes where l.HasValue select l.Value).Min();
}
public override string ToString()
@ -48,16 +48,12 @@ public class Face : Properties.IFace
return result;
}
public void SetFaceEncoding(FaceEncoding faceEncoding) =>
_FaceEncoding = faceEncoding;
public void SetFaceEncoding(FaceEncoding faceEncoding) => _FaceEncoding = faceEncoding;
public void SetFaceParts(Dictionary<Stateless.FacePart, FacePoint[]> faceParts) =>
_FaceParts = faceParts;
public void SetFaceParts(Dictionary<Stateless.FacePart, FacePoint[]> faceParts) => _FaceParts = faceParts;
public void SetMapping(Mapping mapping) =>
_Mapping = mapping;
public void SetMapping(Mapping mapping) => _Mapping = mapping;
public void SetFaceDistance(FaceDistance? faceDistance) =>
_FaceDistance = faceDistance;
public void SetFaceDistance(FaceDistance? faceDistance) => _FaceDistance = faceDistance;
}

View File

@ -6,7 +6,6 @@ namespace View_by_Distance.Shared.Models;
public class Item : Properties.IItem
{
protected ExifDirectory? _ExifDirectory;
protected List<Face> _Faces;
protected readonly bool? _FileSizeChanged;
protected readonly FilePath _FilePath;
@ -16,10 +15,10 @@ public class Item : Properties.IItem
protected bool _IsValidImageFormatExtension;
protected bool? _LastWriteTimeChanged;
protected bool? _Moved;
protected Property? _Property;
protected readonly string _RelativePath;
protected FileHolder? _ResizedFileHolder;
protected readonly FileHolder _SourceDirectoryFileHolder;
public ExifDirectory? ExifDirectory => _ExifDirectory;
public List<Face> Faces => _Faces;
public bool? FileSizeChanged => _FileSizeChanged;
public FilePath FilePath => _FilePath;
@ -29,12 +28,13 @@ public class Item : Properties.IItem
public bool IsValidImageFormatExtension => _IsValidImageFormatExtension;
public bool? LastWriteTimeChanged => _LastWriteTimeChanged;
public bool? Moved => _Moved;
public Property? Property => _Property;
public string RelativePath => _RelativePath;
public FileHolder? ResizedFileHolder => _ResizedFileHolder;
public FileHolder SourceDirectoryFileHolder => _SourceDirectoryFileHolder;
[JsonConstructor]
public Item(List<Face> faces, FilePath filePath, bool? fileSizeChanged, bool? isArchive, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, bool? lastWriteTimeChanged, bool? moved, ExifDirectory? exifDirectory, string relativePath, FileHolder? resizedFileHolder, FileHolder sourceDirectoryFileHolder)
public Item(List<Face> faces, FilePath filePath, bool? fileSizeChanged, bool? isArchive, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, bool? lastWriteTimeChanged, bool? moved, Property? property, string relativePath, FileHolder? resizedFileHolder, FileHolder sourceDirectoryFileHolder)
{
_Faces = faces;
_FilePath = filePath;
@ -45,28 +45,25 @@ public class Item : Properties.IItem
_IsValidImageFormatExtension = isValidImageFormatExtension;
_LastWriteTimeChanged = lastWriteTimeChanged;
_Moved = moved;
_ExifDirectory = exifDirectory;
_Property = property;
_RelativePath = relativePath;
_ResizedFileHolder = resizedFileHolder;
_SourceDirectoryFileHolder = sourceDirectoryFileHolder;
}
public static Item Get(FilePath filePath, FileHolder sourceDirectoryFileHolder, string relativePath, bool isValidImageFormatExtension) =>
Get(filePath, sourceDirectoryFileHolder, relativePath, null, null, false, isValidImageFormatExtension, null, null, null, null);
public static Item Get(FilePath filePath, FileHolder sourceDirectoryFileHolder, string relativePath, bool? isArchive, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, ExifDirectory? exifDirectory, bool? abandoned, bool? fileSizeChanged, bool? lastWriteTimeChanged)
public static Item Get(FilePath filePath, FileHolder sourceDirectoryFileHolder, string relativePath, bool? isArchive, bool? isNotUniqueAndNeedsReview, bool isUniqueFileName, bool isValidImageFormatExtension, Property? property, bool? abandoned, bool? fileSizeChanged, bool? lastWriteTimeChanged)
{
Item result;
if (relativePath.EndsWith(".json"))
throw new ArgumentException("Can not be a *.json file!");
if (filePath.ExtensionLowered is ".json")
throw new ArgumentException("Can not be a *.json file!");
result = new([], filePath, fileSizeChanged, isArchive, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, lastWriteTimeChanged, null, exifDirectory, relativePath, null, sourceDirectoryFileHolder);
result = new([], filePath, fileSizeChanged, isArchive, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, lastWriteTimeChanged, null, property, relativePath, null, sourceDirectoryFileHolder);
return result;
}
public bool Any() =>
!_SourceDirectoryFileHolder.Exists || (_FileSizeChanged.HasValue && _FileSizeChanged.Value) || (_LastWriteTimeChanged.HasValue && _LastWriteTimeChanged.Value) || (_Moved.HasValue && _Moved.Value);
public static Item Get(FilePath filePath, FileHolder sourceDirectoryFileHolder, string relativePath, bool isValidImageFormatExtension) =>
Get(filePath, sourceDirectoryFileHolder, relativePath, null, null, false, isValidImageFormatExtension, null, null, null, null);
public override string ToString()
{
@ -74,9 +71,6 @@ public class Item : Properties.IItem
return result;
}
public void Update(ExifDirectory exifDirectory) =>
_ExifDirectory = exifDirectory;
public void SetMoved(bool moved) => _Moved = moved;
public void SetResizedFileHolder(string filenameExtension, FileHolder fileHolder)
@ -89,4 +83,8 @@ public class Item : Properties.IItem
_ResizedFileHolder = fileHolder;
}
public bool Any() => !_SourceDirectoryFileHolder.Exists || (_FileSizeChanged.HasValue && _FileSizeChanged.Value) || (_LastWriteTimeChanged.HasValue && _LastWriteTimeChanged.Value) || (_Moved.HasValue && _Moved.Value);
public void Update(Property property) => _Property = property;
}

View File

@ -1,16 +1,16 @@
using System.Collections.ObjectModel;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public record MappingFromItem(DateTime[] ContainerDateTimes,
DateTime? DateTimeDigitized,
DateTime? DateTimeOriginal,
int Id,
bool? IsArchive,
FilePath FilePath,
bool? IsWrongYear,
ReadOnlyCollection<string> Keywords,
string[] Keywords,
DateTime MinimumDateTime,
string? Model,
string RelativePath,
@ -29,18 +29,14 @@ public record MappingFromItem(DateTime[] ContainerDateTimes,
internal static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Item item, FileHolder? resizedFileHolder)
{
MappingFromItem result;
if (item.ExifDirectory?.FilePath.Id is null)
if (item.Property?.Id is null)
throw new NotSupportedException();
if (resizedFileHolder is null)
throw new NotSupportedException();
ExifDirectory exifDirectory = item.ExifDirectory;
DateTime minimumDateTime = Stateless.Methods.IDate.GetMinimum(exifDirectory);
DateTime? dateTime = Stateless.Methods.IDate.GetDateTimeOriginal(exifDirectory);
string? model = Stateless.Methods.MetaBase.GetModel(exifDirectory.ExifBaseDirectories);
ReadOnlyCollection<DateTime> dateTimes = Stateless.Methods.IDate.GetDateTimes(exifDirectory);
(bool? isWrongYear, _) = Stateless.Methods.IProperty.IsWrongYear(item.FilePath, dateTime, dateTimes.ToList());
ReadOnlyCollection<string> keywords = Stateless.Methods.MetaBase.GetKeywords(exifDirectory.ExifBaseDirectories);
result = new(containerDateTimes, dateTime, exifDirectory.FilePath.Id.Value, item.IsArchive, item.FilePath, isWrongYear, keywords, minimumDateTime, model, item.RelativePath, resizedFileHolder);
List<DateTime> dateTimes = item.Property.GetDateTimes();
DateTime minimumDateTime = Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
(bool? isWrongYear, _) = Stateless.Methods.IProperty.IsWrongYear(item.FilePath, item.Property.DateTimeOriginal, dateTimes);
result = new(containerDateTimes, item.Property.DateTimeDigitized, item.Property.DateTimeOriginal, item.Property.Id.Value, item.IsArchive, item.FilePath, isWrongYear, item.Property.Keywords ?? [], minimumDateTime, item.Property.Model, item.RelativePath, resizedFileHolder);
return result;
}

View File

@ -0,0 +1,8 @@
namespace View_by_Distance.Shared.Models.Methods;
public interface IMetadataFile : Stateless.Methods.IMetadataFile
{
// ...
}

View File

@ -3,7 +3,6 @@ namespace View_by_Distance.Shared.Models.Properties;
public interface IItem
{
public ExifDirectory? ExifDirectory { get; }
public bool? FileSizeChanged { get; }
public List<Face> Faces { get; }
public FilePath FilePath { get; }
@ -12,6 +11,7 @@ public interface IItem
public bool IsUniqueFileName { get; }
public bool IsValidImageFormatExtension { get; }
public bool? Moved { get; }
public Property? Property { get; }
public string RelativePath { get; }
public FileHolder? ResizedFileHolder { get; }
public FileHolder SourceDirectoryFileHolder { get; }

View File

@ -1,5 +1,3 @@
using System.Collections.ObjectModel;
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IDate
@ -14,9 +12,6 @@ public interface IDate
public static DateTime? GetDateTimeOriginal(ExifDirectory exifDirectory) =>
XDate.GetDateTimeOriginal(exifDirectory);
public static ReadOnlyCollection<DateTime> GetDateTimes(ExifDirectory exifDirectory) =>
XDate.GetDateTimes(exifDirectory);
public static (bool?, string[]) IsWrongYear(DirectoryInfo directoryInfo, FilePath filePath, ExifDirectory exifDirectory) =>
XDate.IsWrongYear(directoryInfo, filePath, exifDirectory);
@ -29,9 +24,6 @@ public interface IDate
internal DateTime? TestStatic_GetDateTimeOriginal(ExifDirectory exifDirectory) =>
GetDateTimeOriginal(exifDirectory);
internal ReadOnlyCollection<DateTime> TestStatic_GetDateTimes(ExifDirectory exifDirectory) =>
XDate.GetDateTimes(exifDirectory);
internal (bool?, string[]) TestStatic_IsWrongYear(DirectoryInfo directoryInfo, FilePath filePath, ExifDirectory exifDirectory) =>
IsWrongYear(directoryInfo, filePath, exifDirectory);

View File

@ -1,18 +1,16 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IMappingFromItem
{
{ // ...
public static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, Models.FileHolder? resizedFileHolder)
MappingFromItem TestStatic_GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, Models.FileHolder? resizedFileHolder)
=> GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, Models.FileHolder? resizedFileHolder)
=> MappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
public static MappingFromItem GetMappingFromItem(Models.Item item)
MappingFromItem TestStatic_GetMappingFromItem(Models.Item item)
=> GetMappingFromItem(item);
static MappingFromItem GetMappingFromItem(Models.Item item)
=> GetMappingFromItem(containerDateTimes: [], item, item.ResizedFileHolder);
internal MappingFromItem TestStatic_GetMappingFromItem(Models.Item item)
=> GetMappingFromItem(item);
internal MappingFromItem TestStatic_GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, Models.FileHolder? resizedFileHolder)
=> GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
}

View File

@ -1,32 +0,0 @@
using System.Collections.ObjectModel;
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IMetaBase
{
public static string? GetMaker(ExifDirectoryBase[]? exifBaseDirectories) =>
MetaBase.GetMaker(exifBaseDirectories);
public static string? GetModel(ExifDirectoryBase[]? exifBaseDirectories) =>
MetaBase.GetModel(exifBaseDirectories);
public static int? GetOrientation(ExifDirectoryBase[]? exifBaseDirectories) =>
MetaBase.GetOrientation(exifBaseDirectories);
public static ReadOnlyCollection<string> GetKeywords(ExifDirectoryBase[]? exifBaseDirectories) =>
MetaBase.GetKeywords(exifBaseDirectories);
internal static string? TestStatic_GetMaker(ExifDirectoryBase[]? exifBaseDirectories) =>
GetMaker(exifBaseDirectories);
internal static string? TestStatic_GetModel(ExifDirectoryBase[]? exifBaseDirectories) =>
GetModel(exifBaseDirectories);
internal static int? TestStatic_GetOrientation(ExifDirectoryBase[]? exifBaseDirectories) =>
GetOrientation(exifBaseDirectories);
internal static ReadOnlyCollection<string> TestStatic_GetKeywords(ExifDirectoryBase[]? exifBaseDirectories) =>
GetKeywords(exifBaseDirectories);
}

View File

@ -0,0 +1,8 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IMetadataFile
{
// ...
}

View File

@ -47,22 +47,6 @@ internal static class MetaBase
return result;
}
internal static int? GetOrientation(ExifDirectoryBase[]? exifBaseDirectories)
{
int? result = null;
// public const int TagOrientation = 274;
if (exifBaseDirectories is not null)
{
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
{
result = exifDirectoryBase?.OrientationValue;
if (result is not null)
break;
}
}
return result;
}
internal static ReadOnlyCollection<string> GetKeywords(ExifDirectoryBase[]? exifBaseDirectories)
{
List<string> results = [];

View File

@ -7,7 +7,15 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class XDate
{
internal static ReadOnlyCollection<DateTime> GetDateTimes(ExifDirectory exifDirectory)
internal static DateTime GetMinimum(ExifDirectory exifDirectory)
{
DateTime result;
ReadOnlyCollection<DateTime> results = GetDateTimes(exifDirectory);
result = results.Count == 0 ? DateTime.MinValue : results.Min();
return result;
}
private static ReadOnlyCollection<DateTime> GetDateTimes(ExifDirectory exifDirectory)
{
List<DateTime> results = [];
foreach (ExifDirectoryBase exifDirectoryBase in exifDirectory.ExifBaseDirectories)
@ -114,14 +122,6 @@ internal abstract class XDate
return result;
}
internal static DateTime GetMinimum(ExifDirectory exifDirectory)
{
DateTime result;
ReadOnlyCollection<DateTime> results = GetDateTimes(exifDirectory);
result = results.Count == 0 ? DateTime.MinValue : results.Min();
return result;
}
internal static (int Season, string seasonName) GetSeason(int dayOfYear)
{
(int Season, string seasonName) result = dayOfYear switch

View File

@ -39,6 +39,7 @@
<ItemGroup>
<ProjectReference Include="..\BlurHash\BlurHash.csproj" />
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Resize\Resize.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup>

View File

@ -56,6 +56,13 @@ public class UnitTestResize
_PropertyConfiguration = propertyConfiguration;
}
private static void NonThrowTryCatch()
{
try
{ throw new Exception(); }
catch (Exception) { }
}
[TestMethod]
public void TestMethodNull()
{
@ -68,80 +75,13 @@ public class UnitTestResize
NonThrowTryCatch();
}
private static void NonThrowTryCatch()
private A_Property GetPropertyLogic(bool reverse, string aResultsFullGroupDirectory)
{
try
{ throw new Exception(); }
catch (Exception) { }
}
[TestMethod]
public void TestMethodResize()
{
if (_PropertyConfiguration.NumberOfJitters is null)
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfJitters));
if (_PropertyConfiguration.NumberOfTimesToUpsample is null)
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfTimesToUpsample));
// string sourceFileName = "100000507001158650387.jpg";
// string sourceDirectoryName = "Facebook/2023.2 Summer Facebook";
string sourceFileName = "105131603001106320328.jpg";
string sourceDirectoryName = "Mike iCloud Have Date Taken 2022 !9";
Item item;
bool reverse = false;
bool isArchive = false;
FileHolder resizedFileHolder;
long ticks = DateTime.Now.Ticks;
List<string> parseExceptions = [];
const bool isValidImageFormatExtension = true;
List<Tuple<string, DateTime>> subFileTuples = [];
int length = _PropertyConfiguration.RootDirectory.Length;
string[] changesFrom = [nameof(A_Property)];
string outputResolution = _Configuration.OutputResolutions[0];
bool outputResolutionHasNumber = outputResolution.Any(char.IsNumber);
(string cResultsFullGroupDirectory, _, _) = GetResultsFullGroupDirectories(outputResolution);
(string aResultsFullGroupDirectory, string bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
Shared.Models.Methods.IBlurHasher blurHasher = new BlurHash.Models.C2_BlurHasher(_PropertyConfiguration);
A_Property propertyLogic = GetPropertyLogic(reverse, aResultsFullGroupDirectory);
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, "{}");
if (!Directory.Exists(aPropertySingletonDirectory))
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(_Configuration.OutputExtension, _Configuration.OutputQuality);
B_Metadata metadata = new(null, _PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, ticks, bResultsFullGroupDirectory);
_ = metadata.ToString();
C_Resize resize = new(_PropertyConfiguration, _Configuration.ForceResizeLastWriteTimeToCreationTime, _Configuration.OverrideForResizeImages, _Configuration.PropertiesChangedForResize, _Configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension);
_ = resize.ToString();
bool isUniqueFileName = false;
bool? isNotUniqueAndNeedsReview = null;
FileHolder sourceDirectoryFileHolder = IFileHolder.Get(".json");
string sourceDirectory = Path.GetFullPath(Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName));
FileHolder fileHolder = IFileHolder.Get(Path.Combine(sourceDirectory, sourceFileName));
FilePath filePath = FilePath.Get(_PropertyConfiguration, fileHolder, index: null);
Assert.IsNotNull(filePath.Id);
string relativePath = IPath.GetRelativePath(fileHolder.FullName, length);
ExifDirectory? exifDirectory = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(filePath);
string propertyLogicSourceDirectory = Path.GetFullPath(Path.Combine(aPropertySingletonDirectory, sourceDirectoryName));
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, propertyLogicSourceDirectory);
if (outputResolutionHasNumber)
resize.SetAngleBracketCollection(cResultsFullGroupDirectory, sourceDirectory);
resize.Update(cResultsFullGroupDirectory);
blurHasher.Update(cResultsFullGroupDirectory);
item = Item.Get(filePath, sourceDirectoryFileHolder, relativePath, isArchive, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, exifDirectory, false, false, false);
if (item.ExifDirectory is null)
throw new NullReferenceException(nameof(item.ExifDirectory));
resizedFileHolder = resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber, filePath.Id.Value);
item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder);
MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item);
Dictionary<string, int[]> outputResolutionToResize = resize.GetResizeKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.ExifDirectory, mappingFromItem);
Assert.IsNotNull(mappingFromItem.ResizedFileHolder);
resize.SaveResizedSubfile(_PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.ExifDirectory, mappingFromItem, outputResolutionToResize);
string blurHash = blurHasher.Encode(resizedFileHolder);
Assert.IsNotNull(blurHash);
exifDirectory = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
string json = JsonSerializer.Serialize(exifDirectory, ExifDirectoryBaseSourceGenerationContext.Default.ExifDirectoryBase);
File.WriteAllText("../../../.json", json);
MetadataExtractor.GeoLocation? geoLocation = Metadata.Models.Stateless.Methods.IMetadata.GeoLocation(exifDirectory);
double? distance = geoLocation is null ? null : Metadata.Models.Stateless.Methods.IMetadata.GetDistance(1, 1, geoLocation.Latitude, geoLocation.Longitude);
NonThrowTryCatch();
A_Property result;
if (_Configuration?.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_PropertyConfiguration));
result = new(_AppSettings.MaxDegreeOfParallelism, _PropertyConfiguration, _Configuration.OutputExtension, reverse, aResultsFullGroupDirectory);
return result;
}
private (string, string) GetResultsFullGroupDirectories()
@ -177,13 +117,77 @@ public class UnitTestResize
return new(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory);
}
private A_Property GetPropertyLogic(bool reverse, string aResultsFullGroupDirectory)
[TestMethod]
public void TestMethodResize()
{
A_Property result;
if (_Configuration?.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_PropertyConfiguration));
result = new(_AppSettings.MaxDegreeOfParallelism, _PropertyConfiguration, _Configuration.OutputExtension, reverse, aResultsFullGroupDirectory);
return result;
if (_PropertyConfiguration.NumberOfJitters is null)
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfJitters));
if (_PropertyConfiguration.NumberOfTimesToUpsample is null)
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfTimesToUpsample));
// string sourceFileName = "100000507001158650387.jpg";
// string sourceDirectoryName = "Facebook/2023.2 Summer Facebook";
string sourceFileName = "105131603001106320328.jpg";
string sourceDirectoryName = "Mike iCloud Have Date Taken 2022 !9";
Item item;
bool reverse = false;
bool isArchive = false;
FileHolder resizedFileHolder;
List<string> parseExceptions = [];
Shared.Models.Property? property = null;
const bool isValidImageFormatExtension = true;
List<Tuple<string, DateTime>> subFileTuples = [];
int length = _PropertyConfiguration.RootDirectory.Length;
string[] changesFrom = [nameof(A_Property)];
string outputResolution = _Configuration.OutputResolutions[0];
bool outputResolutionHasNumber = outputResolution.Any(char.IsNumber);
(string cResultsFullGroupDirectory, _, _) = GetResultsFullGroupDirectories(outputResolution);
(string aResultsFullGroupDirectory, string bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
Shared.Models.Methods.IBlurHasher blurHasher = new BlurHash.Models.C2_BlurHasher(_PropertyConfiguration);
A_Property propertyLogic = GetPropertyLogic(reverse, aResultsFullGroupDirectory);
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, "{}");
if (!Directory.Exists(aPropertySingletonDirectory))
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(_Configuration.OutputExtension, _Configuration.OutputQuality);
B_Metadata metadata = new(_PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory);
_ = metadata.ToString();
C_Resize resize = new(_PropertyConfiguration, _Configuration.ForceResizeLastWriteTimeToCreationTime, _Configuration.OverrideForResizeImages, _Configuration.PropertiesChangedForResize, _Configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension);
_ = resize.ToString();
bool isUniqueFileName = false;
bool? isNotUniqueAndNeedsReview = null;
FileHolder sourceDirectoryFileHolder = IFileHolder.Get(".json");
string sourceDirectory = Path.GetFullPath(Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName));
FileHolder fileHolder = IFileHolder.Get(Path.Combine(sourceDirectory, sourceFileName));
FilePath filePath = FilePath.Get(_PropertyConfiguration, fileHolder, index: null);
Assert.IsNotNull(filePath.Id);
string relativePath = IPath.GetRelativePath(fileHolder.FullName, length);
string propertyLogicSourceDirectory = Path.GetFullPath(Path.Combine(aPropertySingletonDirectory, sourceDirectoryName));
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, propertyLogicSourceDirectory);
if (outputResolutionHasNumber)
resize.SetAngleBracketCollection(cResultsFullGroupDirectory, sourceDirectory);
resize.Update(cResultsFullGroupDirectory);
blurHasher.Update(cResultsFullGroupDirectory);
item = Item.Get(filePath, sourceDirectoryFileHolder, relativePath, isArchive, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, property, false, false, false);
if (item.Property is null)
{
property = propertyLogic.GetProperty(metadata, item, subFileTuples, parseExceptions);
item.Update(property);
}
if (property is null || item.Property is null)
throw new NullReferenceException(nameof(property));
resizedFileHolder = resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber, filePath.Id.Value);
item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder);
MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item);
Dictionary<string, int[]> outputResolutionToResize = resize.GetResizeKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem);
Assert.IsNotNull(mappingFromItem.ResizedFileHolder);
resize.SaveResizedSubfile(_PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize);
string blurHash = blurHasher.Encode(resizedFileHolder);
Assert.IsNotNull(blurHash);
ExifDirectory exifDirectory = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
string json = JsonSerializer.Serialize(exifDirectory, ExifDirectoryBaseSourceGenerationContext.Default.ExifDirectoryBase);
File.WriteAllText("../../../.json", json);
MetadataExtractor.GeoLocation? geoLocation = Metadata.Models.Stateless.Methods.IMetadata.GeoLocation(exifDirectory);
double? distance = geoLocation is null ? null : Metadata.Models.Stateless.Methods.IMetadata.GetDistance(1, 1, geoLocation.Latitude, geoLocation.Longitude);
NonThrowTryCatch();
}
}

View File

@ -39,6 +39,7 @@
<ProjectReference Include="..\BlurHash\BlurHash.csproj" />
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Resize\Resize.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup>

View File

@ -58,113 +58,33 @@ public class UnitTestFace
_PropertyConfiguration = propertyConfiguration;
}
[TestMethod]
public void TestMethodFace()
private static void NonThrowTryCatch()
{
if (_PropertyConfiguration.NumberOfJitters is null)
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfJitters));
if (_PropertyConfiguration.NumberOfTimesToUpsample is null)
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfTimesToUpsample));
string sourceFileName = "100000507001158650387.jpg";
string sourceDirectoryName = "Facebook/2023.2 Summer Facebook";
Item item;
bool reverse = false;
bool isArchive = false;
FileHolder resizedFileHolder;
long ticks = DateTime.Now.Ticks;
List<string> parseExceptions = [];
const bool isValidImageFormatExtension = true;
List<Tuple<string, DateTime>> subFileTuples = [];
int length = _PropertyConfiguration.RootDirectory.Length;
string[] changesFrom = [nameof(A_Property)];
string outputResolution = _Configuration.OutputResolutions[0];
bool outputResolutionHasNumber = outputResolution.Any(char.IsNumber);
(string cResultsFullGroupDirectory, _, _) = GetResultsFullGroupDirectories(outputResolution);
(string aResultsFullGroupDirectory, string bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
Shared.Models.Methods.IBlurHasher blurHasher = new BlurHash.Models.C2_BlurHasher(_PropertyConfiguration);
A_Property propertyLogic = GetPropertyLogic(reverse, aResultsFullGroupDirectory);
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, "{}");
if (!Directory.Exists(aPropertySingletonDirectory))
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(_Configuration.OutputExtension, _Configuration.OutputQuality);
B_Metadata metadata = new(null, _PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, ticks, bResultsFullGroupDirectory);
_ = metadata.ToString();
C_Resize resize = new(_PropertyConfiguration, _Configuration.ForceResizeLastWriteTimeToCreationTime, _Configuration.OverrideForResizeImages, _Configuration.PropertiesChangedForResize, _Configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension);
_ = resize.ToString();
bool isUniqueFileName = false;
bool? isNotUniqueAndNeedsReview = null;
FileHolder sourceDirectoryFileHolder = IFileHolder.Get(".json");
string sourceDirectory = Path.GetFullPath(Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName));
FileHolder fileHolder = IFileHolder.Get(Path.Combine(sourceDirectory, sourceFileName));
FilePath filePath = FilePath.Get(_PropertyConfiguration, fileHolder, index: null);
Assert.IsNotNull(filePath.Id);
string relativePath = IPath.GetRelativePath(fileHolder.FullName, length);
ExifDirectory? exifDirectory = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(filePath);
string propertyLogicSourceDirectory = Path.GetFullPath(Path.Combine(aPropertySingletonDirectory, sourceDirectoryName));
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, propertyLogicSourceDirectory);
if (outputResolutionHasNumber)
resize.SetAngleBracketCollection(cResultsFullGroupDirectory, sourceDirectory);
resize.Update(cResultsFullGroupDirectory);
blurHasher.Update(cResultsFullGroupDirectory);
item = Item.Get(filePath, sourceDirectoryFileHolder, relativePath, isArchive, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, exifDirectory, false, false, false);
if (item.ExifDirectory is null)
throw new NullReferenceException(nameof(item.ExifDirectory));
resizedFileHolder = resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber, filePath.Id.Value);
item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder);
MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item);
Dictionary<string, int[]> outputResolutionToResize = resize.GetResizeKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.ExifDirectory, mappingFromItem);
Assert.IsNotNull(mappingFromItem.ResizedFileHolder);
resize.SaveResizedSubfile(_PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.ExifDirectory, mappingFromItem, outputResolutionToResize);
string blurHash = blurHasher.Encode(resizedFileHolder);
Assert.IsNotNull(blurHash);
exifDirectory = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
string json = JsonSerializer.Serialize(exifDirectory, ExifDirectoryBaseSourceGenerationContext.Default.ExifDirectoryBase);
File.WriteAllText("../../../.json", json);
Image image = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName);
Assert.IsNotNull(image);
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(_Configuration);
FaceRecognition faceRecognition = new(_PropertyConfiguration.NumberOfJitters.Value, _PropertyConfiguration.NumberOfTimesToUpsample.Value, model, modelParameter, predictorModel);
List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
collection = faceRecognition.GetCollection(image, locations: [], includeFaceEncoding: true, includeFaceParts: true);
Assert.IsTrue(collection.Count == 2);
List<FaceDistance> faceDistanceEncodings = (from l in collection where l.FaceEncoding is not null select new FaceDistance(l.FaceEncoding)).ToList();
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(new(faceDistanceEncodings), faceDistanceEncodings[0]);
Assert.IsTrue(faceDistanceLengths.Count == 2);
Assert.IsNotNull(sourceFileName);
try
{ throw new Exception(); }
catch (Exception) { }
}
[TestMethod]
public void TestConfiguration()
{
if (_Configuration.LocationDigits != Shared.Models.Stateless.ILocation.Digits)
throw new Exception("Configuration has to match interface!");
if (_Configuration.LocationFactor != Shared.Models.Stateless.ILocation.Factor)
throw new Exception("Configuration has to match interface!");
NonThrowTryCatch();
}
private (string, string) GetResultsFullGroupDirectories()
[TestMethod]
public void TestMethodNull()
{
string aResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
_PropertyConfiguration,
nameof(A_Property),
string.Empty,
includeResizeGroup: false,
includeModel: false,
includePredictorModel: false);
string bResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
_PropertyConfiguration,
nameof(B_Metadata),
string.Empty,
includeResizeGroup: false,
includeModel: false,
includePredictorModel: false);
return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory);
}
private (string, string, string) GetResultsFullGroupDirectories(string outputResolution)
{
string cResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
_PropertyConfiguration,
nameof(C_Resize),
outputResolution,
includeResizeGroup: true,
includeModel: false,
includePredictorModel: false);
string dResultsFullGroupDirectory = string.Empty;
string d2ResultsFullGroupDirectory = string.Empty;
return new(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory);
Assert.IsFalse(_AppSettings is null);
Assert.IsFalse(_Configuration is null);
Assert.IsFalse(_IsEnvironment is null);
Assert.IsFalse(_WorkingDirectory is null);
Assert.IsFalse(_ConfigurationRoot is null);
Assert.IsFalse(_PropertyConfiguration is null);
NonThrowTryCatch();
}
private A_Property GetPropertyLogic(bool reverse, string aResultsFullGroupDirectory)
@ -217,25 +137,6 @@ public class UnitTestFace
return result;
}
private static void NonThrowTryCatch()
{
try
{ throw new Exception(); }
catch (Exception) { }
}
[TestMethod]
public void TestMethodNull()
{
Assert.IsFalse(_AppSettings is null);
Assert.IsFalse(_Configuration is null);
Assert.IsFalse(_IsEnvironment is null);
Assert.IsFalse(_WorkingDirectory is null);
Assert.IsFalse(_ConfigurationRoot is null);
Assert.IsFalse(_PropertyConfiguration is null);
NonThrowTryCatch();
}
[TestMethod]
public void TestMethodRoundB()
{
@ -258,13 +159,116 @@ public class UnitTestFace
NonThrowTryCatch();
}
[TestMethod]
public void TestConfiguration()
private (string, string) GetResultsFullGroupDirectories()
{
if (_Configuration.LocationDigits != Shared.Models.Stateless.ILocation.Digits)
throw new Exception("Configuration has to match interface!");
if (_Configuration.LocationFactor != Shared.Models.Stateless.ILocation.Factor)
throw new Exception("Configuration has to match interface!");
string aResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
_PropertyConfiguration,
nameof(A_Property),
string.Empty,
includeResizeGroup: false,
includeModel: false,
includePredictorModel: false);
string bResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
_PropertyConfiguration,
nameof(B_Metadata),
string.Empty,
includeResizeGroup: false,
includeModel: false,
includePredictorModel: false);
return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory);
}
private (string, string, string) GetResultsFullGroupDirectories(string outputResolution)
{
string cResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
_PropertyConfiguration,
nameof(C_Resize),
outputResolution,
includeResizeGroup: true,
includeModel: false,
includePredictorModel: false);
string dResultsFullGroupDirectory = string.Empty;
string d2ResultsFullGroupDirectory = string.Empty;
return new(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory);
}
[TestMethod]
public void TestMethodFace()
{
if (_PropertyConfiguration.NumberOfJitters is null)
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfJitters));
if (_PropertyConfiguration.NumberOfTimesToUpsample is null)
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfTimesToUpsample));
string sourceFileName = "100000507001158650387.jpg";
string sourceDirectoryName = "Facebook/2023.2 Summer Facebook";
Item item;
bool reverse = false;
bool isArchive = false;
FileHolder resizedFileHolder;
List<string> parseExceptions = [];
Shared.Models.Property? property = null;
const bool isValidImageFormatExtension = true;
List<Tuple<string, DateTime>> subFileTuples = [];
int length = _PropertyConfiguration.RootDirectory.Length;
string[] changesFrom = [nameof(A_Property)];
string outputResolution = _Configuration.OutputResolutions[0];
bool outputResolutionHasNumber = outputResolution.Any(char.IsNumber);
(string cResultsFullGroupDirectory, _, _) = GetResultsFullGroupDirectories(outputResolution);
(string aResultsFullGroupDirectory, string bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
Shared.Models.Methods.IBlurHasher blurHasher = new BlurHash.Models.C2_BlurHasher(_PropertyConfiguration);
A_Property propertyLogic = GetPropertyLogic(reverse, aResultsFullGroupDirectory);
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, "{}");
if (!Directory.Exists(aPropertySingletonDirectory))
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(_Configuration.OutputExtension, _Configuration.OutputQuality);
B_Metadata metadata = new(_PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory);
_ = metadata.ToString();
C_Resize resize = new(_PropertyConfiguration, _Configuration.ForceResizeLastWriteTimeToCreationTime, _Configuration.OverrideForResizeImages, _Configuration.PropertiesChangedForResize, _Configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension);
_ = resize.ToString();
bool isUniqueFileName = false;
bool? isNotUniqueAndNeedsReview = null;
FileHolder sourceDirectoryFileHolder = IFileHolder.Get(".json");
string sourceDirectory = Path.GetFullPath(Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName));
FileHolder fileHolder = IFileHolder.Get(Path.Combine(sourceDirectory, sourceFileName));
FilePath filePath = FilePath.Get(_PropertyConfiguration, fileHolder, index: null);
Assert.IsNotNull(filePath.Id);
string relativePath = IPath.GetRelativePath(fileHolder.FullName, length);
string propertyLogicSourceDirectory = Path.GetFullPath(Path.Combine(aPropertySingletonDirectory, sourceDirectoryName));
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, propertyLogicSourceDirectory);
if (outputResolutionHasNumber)
resize.SetAngleBracketCollection(cResultsFullGroupDirectory, sourceDirectory);
resize.Update(cResultsFullGroupDirectory);
blurHasher.Update(cResultsFullGroupDirectory);
item = Item.Get(filePath, sourceDirectoryFileHolder, relativePath, isArchive, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, property, false, false, false);
if (item.Property is null)
{
property = propertyLogic.GetProperty(metadata, item, subFileTuples, parseExceptions);
item.Update(property);
}
if (property is null || item.Property is null)
throw new NullReferenceException(nameof(property));
resizedFileHolder = resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber, filePath.Id.Value);
item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder);
MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item);
Dictionary<string, int[]> outputResolutionToResize = resize.GetResizeKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem);
Assert.IsNotNull(mappingFromItem.ResizedFileHolder);
resize.SaveResizedSubfile(_PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize);
string blurHash = blurHasher.Encode(resizedFileHolder);
Assert.IsNotNull(blurHash);
ExifDirectory exifDirectory = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
string json = JsonSerializer.Serialize(exifDirectory, ExifDirectoryBaseSourceGenerationContext.Default.ExifDirectoryBase);
File.WriteAllText("../../../.json", json);
Image image = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName);
Assert.IsNotNull(image);
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(_Configuration);
FaceRecognition faceRecognition = new(_PropertyConfiguration.NumberOfJitters.Value, _PropertyConfiguration.NumberOfTimesToUpsample.Value, model, modelParameter, predictorModel);
List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
collection = faceRecognition.GetCollection(image, locations: [], includeFaceEncoding: true, includeFaceParts: true);
Assert.IsTrue(collection.Count == 2);
List<FaceDistance> faceDistanceEncodings = (from l in collection where l.FaceEncoding is not null select new FaceDistance(l.FaceEncoding)).ToList();
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(new(faceDistanceEncodings), faceDistanceEncodings[0]);
Assert.IsTrue(faceDistanceLengths.Count == 2);
Assert.IsNotNull(sourceFileName);
NonThrowTryCatch();
}

View File

@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlurHash", "BlurHash\BlurHa
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Copy-Distinct", "Copy-Distinct\Copy-Distinct.csproj", "{E08CB662-FF25-48DF-A378-A770E1EFBA56}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Date-Group", "Date-Group\Date-Group.csproj", "{DFEDB5F9-AFFC-40A2-9FEC-9B84C83B63D9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Delete-By-Distinct", "Delete-By-Distinct\Delete-By-Distinct.csproj", "{3F00BDD5-75F8-470C-ACED-1A26FDC8D7B3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Delete-By-Relative", "Delete-By-Relative\Delete-By-Relative.csproj", "{9DFCA595-80AA-4E78-A9AF-5B4AB4D737C4}"
@ -21,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drag-Drop-Search", "Drag-Dr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drag-Drop-Set-Property-Item", "Drag-Drop-Set-Property-Item\Drag-Drop-Set-Property-Item.csproj", "{BFF75D8C-48E6-4B84-B480-3E5A4F9B2DD8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicate-Search", "Duplicate-Search\Duplicate-Search.csproj", "{48E87D9B-B802-467A-BDC7-E86F7FD01D5C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Face", "Face\Face.csproj", "{A12E19E5-59C0-40D4-B807-DF1334D4906D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FaceParts", "FaceParts\FaceParts.csproj", "{919525B1-60BA-40C6-BA66-6F7F4C526E01}"
@ -47,6 +51,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrepareForOld", "PrepareFor
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Property-Compare", "Property-Compare\Property-Compare.csproj", "{692AA058-F142-44B0-88BC-F22AB5BE5EDF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Property", "Property\Property.csproj", "{964B969A-719C-48AF-86C0-F97AF1397347}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rename", "Rename\Rename.csproj", "{83FD089F-8034-4597-B87F-87D343C0486B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Resize", "Resize\Resize.csproj", "{27D0D869-394D-4B07-83DF-2095B16026FC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Set-Created-Date", "Set-Created-Date\Set-Created-Date.csproj", "{B067643E-9F59-46A1-A001-ACF4661F059C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{B4FB6B43-36EC-404D-B934-5C695C6E32CC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsWithFaceRecognitionDotNet", "TestsWithFaceRecognitionDotNet\TestsWithFaceRecognitionDotNet.csproj", "{A67D73C7-A1A1-4443-B681-776339CFA08A}"