NullReferenceException

This commit is contained in:
2022-08-13 11:19:08 -07:00
parent 3aeab88384
commit 0392de1920
33 changed files with 1278 additions and 1030 deletions

View File

@ -0,0 +1,40 @@
using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Property.Models;
public class Closest
{
protected readonly double? _Average;
protected readonly int? _FaceLocationIndex;
protected readonly bool? _IsWrongYear;
protected readonly DateTime _MinimumDateTime;
protected readonly PersonBirthday? _PersonBirthday;
public double? Average => _Average;
public int? FaceLocationIndex => _FaceLocationIndex;
public bool? IsWrongYear => _IsWrongYear;
public DateTime MinimumDateTime => _MinimumDateTime;
public PersonBirthday? PersonBirthday => _PersonBirthday;
[JsonConstructor]
public Closest(double? average, int? faceLocationIndex, bool? isWrongYear, DateTime minimumDateTime, PersonBirthday? personBirthday)
{
_Average = average;
_FaceLocationIndex = faceLocationIndex;
_IsWrongYear = isWrongYear;
_MinimumDateTime = minimumDateTime;
_PersonBirthday = personBirthday;
}
public Closest(int? faceLocationIndex, DateTime minimumDateTime, bool? isWrongYear, PersonBirthday? personBirthday, double? average)
{
_Average = average;
_FaceLocationIndex = faceLocationIndex;
_IsWrongYear = isWrongYear;
_MinimumDateTime = minimumDateTime;
_PersonBirthday = personBirthday;
}
}

View File

@ -65,37 +65,37 @@ public class Configuration
public static void Verify(Configuration? propertyConfiguration)
{
if (propertyConfiguration is null)
throw new ArgumentNullException(nameof(propertyConfiguration));
throw new NullReferenceException(nameof(propertyConfiguration));
if (propertyConfiguration.ForcePropertyLastWriteTimeToCreationTime is null)
throw new ArgumentNullException(nameof(propertyConfiguration.ForcePropertyLastWriteTimeToCreationTime));
throw new NullReferenceException(nameof(propertyConfiguration.ForcePropertyLastWriteTimeToCreationTime));
if (propertyConfiguration.IgnoreExtensions is null || !propertyConfiguration.IgnoreExtensions.Any())
throw new ArgumentNullException(nameof(propertyConfiguration.IgnoreExtensions));
throw new NullReferenceException(nameof(propertyConfiguration.IgnoreExtensions));
if (propertyConfiguration.PopulatePropertyId is null)
throw new ArgumentNullException(nameof(propertyConfiguration.PopulatePropertyId));
throw new NullReferenceException(nameof(propertyConfiguration.PopulatePropertyId));
if (propertyConfiguration.PropertiesChangedForProperty is null)
throw new ArgumentNullException(nameof(propertyConfiguration.PropertiesChangedForProperty));
throw new NullReferenceException(nameof(propertyConfiguration.PropertiesChangedForProperty));
if (propertyConfiguration.PropertyContentCollectionFiles is null)
throw new ArgumentNullException(nameof(propertyConfiguration.PropertyContentCollectionFiles));
throw new NullReferenceException(nameof(propertyConfiguration.PropertyContentCollectionFiles));
if (propertyConfiguration.ValidImageFormatExtensions is null || !propertyConfiguration.ValidImageFormatExtensions.Any())
throw new ArgumentNullException(nameof(propertyConfiguration.ValidImageFormatExtensions));
throw new NullReferenceException(nameof(propertyConfiguration.ValidImageFormatExtensions));
if (propertyConfiguration.ValidMetadataExtensions is null || !propertyConfiguration.ValidMetadataExtensions.Any())
throw new ArgumentNullException(nameof(propertyConfiguration.ValidMetadataExtensions));
throw new NullReferenceException(nameof(propertyConfiguration.ValidMetadataExtensions));
if (propertyConfiguration.VerifyToSeason is null || !propertyConfiguration.VerifyToSeason.Any())
throw new ArgumentNullException(nameof(propertyConfiguration.VerifyToSeason));
throw new NullReferenceException(nameof(propertyConfiguration.VerifyToSeason));
if (propertyConfiguration.WriteBitmapDataBytes is null)
throw new ArgumentNullException(nameof(propertyConfiguration.WriteBitmapDataBytes));
throw new NullReferenceException(nameof(propertyConfiguration.WriteBitmapDataBytes));
if (Path.GetPathRoot(propertyConfiguration.RootDirectory) == propertyConfiguration.RootDirectory)
throw new ArgumentNullException(nameof(propertyConfiguration.RootDirectory));
throw new NullReferenceException(nameof(propertyConfiguration.RootDirectory));
if (propertyConfiguration is null)
throw new ArgumentNullException(nameof(propertyConfiguration));
throw new NullReferenceException(nameof(propertyConfiguration));
if (string.IsNullOrEmpty(propertyConfiguration.DateGroup))
throw new ArgumentNullException(nameof(propertyConfiguration.DateGroup));
throw new NullReferenceException(nameof(propertyConfiguration.DateGroup));
if (string.IsNullOrEmpty(propertyConfiguration.FileNameDirectorySeparator))
throw new ArgumentNullException(nameof(propertyConfiguration.FileNameDirectorySeparator));
throw new NullReferenceException(nameof(propertyConfiguration.FileNameDirectorySeparator));
if (string.IsNullOrEmpty(propertyConfiguration.Pattern))
throw new ArgumentNullException(nameof(propertyConfiguration.Pattern));
throw new NullReferenceException(nameof(propertyConfiguration.Pattern));
if (string.IsNullOrEmpty(propertyConfiguration.RootDirectory) || !Directory.Exists(propertyConfiguration.RootDirectory))
throw new ArgumentNullException(nameof(propertyConfiguration.RootDirectory));
throw new NullReferenceException(nameof(propertyConfiguration.RootDirectory));
}
public void ChangeRootDirectory(string rootDirectory) => _RootDirectory = rootDirectory;

View File

@ -0,0 +1,34 @@
using System.Text.Json.Serialization;
namespace View_by_Distance.Property.Models;
public class Container
{
protected readonly int _G;
protected readonly int _R;
protected readonly List<Item> _Items;
protected readonly string _SourceDirectory;
public int G => _G;
public List<Item> Items => _Items;
public int R => _R;
public string SourceDirectory => _SourceDirectory;
[JsonConstructor]
public Container(int g, int r, List<Item> items, string sourceDirectory)
{
_G = g;
_R = r;
_Items = items;
_SourceDirectory = sourceDirectory;
}
public Container(int g, int r, string sourceDirectory)
{
_G = g;
_R = r;
_Items = new();
_SourceDirectory = sourceDirectory;
}
}

View File

@ -5,7 +5,7 @@ public class FileHolder
protected readonly DateTime _CreationTime;
protected readonly string? _DirectoryName;
protected readonly bool _Exists;
protected readonly string _Extension;
protected readonly string _ExtensionLowered;
protected readonly string _FullName;
protected readonly DateTime _LastWriteTime;
protected readonly long? _Length;
@ -14,19 +14,19 @@ public class FileHolder
public DateTime CreationTime => _CreationTime;
public string? DirectoryName => _DirectoryName;
public bool Exists => _Exists;
public string Extension => _Extension;
public string ExtensionLowered => _ExtensionLowered;
public string FullName => _FullName;
public DateTime LastWriteTime => _LastWriteTime;
public long? Length => _Length;
public string Name => _Name;
public string NameWithoutExtension => _NameWithoutExtension;
public FileHolder(DateTime creationTime, string? directoryName, bool exists, string extension, string fullName, DateTime lastWriteTime, long? length, string name, string nameWithoutExtension)
public FileHolder(DateTime creationTime, string? directoryName, bool exists, string extensionLowered, string fullName, DateTime lastWriteTime, long? length, string name, string nameWithoutExtension)
{
_CreationTime = creationTime;
_DirectoryName = directoryName;
_Exists = exists;
_Extension = extension;
_ExtensionLowered = extensionLowered;
_FullName = fullName;
_LastWriteTime = lastWriteTime;
_Length = length;
@ -41,7 +41,7 @@ public class FileHolder
_CreationTime = fileInfo.CreationTime;
_DirectoryName = fileInfo.DirectoryName;
_Exists = fileInfo.Exists;
_Extension = fileInfo.Extension;
_ExtensionLowered = fileInfo.Extension.ToLower();
_FullName = fileInfo.FullName;
_LastWriteTime = fileInfo.LastWriteTime;
if (fileInfo.Exists)
@ -56,7 +56,7 @@ public class FileHolder
_CreationTime = fileInfo.CreationTime;
_DirectoryName = fileInfo.DirectoryName;
_Exists = fileInfo.Exists;
_Extension = fileInfo.Extension;
_ExtensionLowered = fileInfo.Extension.ToLower();
_FullName = fileInfo.FullName;
_LastWriteTime = fileInfo.LastWriteTime;
if (fileInfo.Exists)

View File

@ -4,86 +4,72 @@ using View_by_Distance.Shared.Models.Properties;
namespace View_by_Distance.Property.Models;
public class PropertyHolder
public class Item
{
protected readonly bool? _Abandoned;
protected readonly bool? _Changed;
protected List<Closest> _Closest;
protected List<IFace> _Faces;
protected readonly FileHolder? _ImageFileHolder;
protected readonly string _ImageFileNameWithoutExtension;
protected readonly int _G;
protected DateTime? _MinimumDateTime;
protected bool? _Moved;
protected List<(bool?, DateTime, PersonBirthday, double?)> _Named;
protected List<Named> _Named;
protected readonly bool? _NoJson;
protected A_Property? _Property;
protected readonly int _R;
protected readonly string _RelativePath;
protected FileHolder? _ResizedFileHolder;
protected readonly string _SourceDirectory;
protected readonly string _SourceDirectoryFile;
protected bool? _ValidImageFormatExtension;
protected bool _ValidImageFormatExtension;
public bool? Abandoned => _Abandoned;
public bool? Changed => _Changed;
public List<Closest> Closest => _Closest;
public List<IFace> Faces => _Faces;
public FileHolder? ImageFileHolder => _ImageFileHolder;
public string ImageFileNameWithoutExtension => _ImageFileNameWithoutExtension;
public int G => _G;
public DateTime? MinimumDateTime => _MinimumDateTime;
public bool? Moved => _Moved;
public bool? NoJson => _NoJson;
public List<(bool? isWrongYear, DateTime minimumDateTime, PersonBirthday personBirthday, double? pixelPercentage)> Named => _Named;
public List<Named> Named => _Named;
public A_Property? Property => _Property;
public int R => _R;
public string RelativePath => _RelativePath;
public FileHolder? ResizedFileHolder => _ResizedFileHolder;
public string SourceDirectory => _SourceDirectory;
public string SourceDirectoryFile => _SourceDirectoryFile;
public bool? ValidImageFormatExtension => _ValidImageFormatExtension;
public PropertyHolder()
{
_G = -1;
_R = -1;
_Faces = new();
_Named = new();
_RelativePath = string.Empty;
_SourceDirectory = string.Empty;
_SourceDirectoryFile = string.Empty;
_ImageFileNameWithoutExtension = string.Empty;
}
public bool ValidImageFormatExtension => _ValidImageFormatExtension;
[JsonConstructor]
public PropertyHolder(int g, string sourceDirectory, string sourceDirectoryFile, string relativePath, int r, FileHolder? imageFileInfo, A_Property? property, bool? abandoned, bool? changed, bool? moved, bool? validImageFormatExtension)
public Item(bool? abandoned, bool? changed, List<Closest> closest, List<IFace> faces, FileHolder? imageFileHolder, bool? moved, List<Named> named, bool? noJson, A_Property? property, string relativePath, FileHolder? resizedFileHolder, string sourceDirectoryFile, bool validImageFormatExtension)
{
_G = g;
_R = r;
_Faces = new();
_Moved = moved;
_Named = new();
_Abandoned = abandoned;
_Changed = changed;
_Closest = closest;
_Faces = faces;
_ImageFileHolder = imageFileHolder;
_Moved = moved;
_Named = named;
_NoJson = noJson;
_Property = property;
_RelativePath = relativePath;
_ResizedFileHolder = resizedFileHolder;
_SourceDirectoryFile = sourceDirectoryFile;
_ValidImageFormatExtension = validImageFormatExtension;
}
public Item(string sourceDirectoryFile, string relativePath, FileHolder? imageFileInfo, bool isValidImageFormatExtension, A_Property? property, bool? abandoned, bool? changed)
{
_Faces = new();
_Named = new();
_Closest = new();
_Changed = changed;
_Abandoned = abandoned;
_NoJson = abandoned is null;
_RelativePath = relativePath;
_ImageFileHolder = imageFileInfo;
_SourceDirectory = sourceDirectory;
_SourceDirectoryFile = sourceDirectoryFile;
_ValidImageFormatExtension = validImageFormatExtension;
_MinimumDateTime = Stateless.A_Property.GetMinimumDateTime(property);
if (imageFileInfo is null)
_ImageFileNameWithoutExtension = string.Empty;
else
_ImageFileNameWithoutExtension = Path.GetFileNameWithoutExtension(imageFileInfo.FullName);
if (imageFileInfo is not null && imageFileInfo.Extension is ".json")
_ValidImageFormatExtension = isValidImageFormatExtension;
if (relativePath.EndsWith(".json"))
throw new ArgumentException("Can not be a *.json file!");
if (imageFileInfo is not null && imageFileInfo.ExtensionLowered is ".json")
throw new ArgumentException("Can not be a *.json file!");
if (!sourceDirectoryFile.EndsWith(".json") && !sourceDirectoryFile.EndsWith(".old"))
throw new ArgumentException("Must be a *.json or *.old file!");
}
internal void SetValidImageFormatExtension(bool isValidImageFormatExtension) => _ValidImageFormatExtension = isValidImageFormatExtension;
internal void SetMoved(bool moved) => _Moved = moved;
public static string GetWrongYearFlag(bool? isWrongYear) => isWrongYear is null ? "#" : isWrongYear.Value ? "~" : "=";
@ -92,42 +78,39 @@ public class PropertyHolder
public bool Any() => (_Abandoned.HasValue && _Abandoned.Value) || (_Changed.HasValue && _Changed.Value) || (_Moved.HasValue && _Moved.Value) || (_NoJson.HasValue && _NoJson.Value);
public void Update(A_Property property)
{
_Property = property;
_MinimumDateTime = Stateless.A_Property.GetMinimumDateTime(property);
}
public void Update(A_Property property) => _Property = property;
public (bool?, string[]) IsWrongYear()
{
(bool?, string[]) result;
if (_Property is null || _ImageFileHolder is null)
throw new ArgumentNullException();
result = _Property.IsWrongYear(_ImageFileHolder.FullName, _MinimumDateTime);
throw new NullReferenceException();
DateTime? minimumDateTime = Stateless.A_Property.GetMinimumDateTime(_Property);
result = _Property.IsWrongYear(_ImageFileHolder.FullName, minimumDateTime);
return result;
}
public static void AddToNamed(PropertyLogic propertyLogic, PropertyHolder[] filteredPropertyHolderCollection)
public static void AddToNamed(PropertyLogic propertyLogic, Item[] filteredItems)
{
Item item;
bool? isWrongYear;
string[] segments;
string[] personKeys;
double? pixelPercentage;
DateTime minimumDateTime;
PropertyHolder propertyHolder;
PersonBirthday? personBirthday;
for (int i = 0; i < filteredPropertyHolderCollection.Length; i++)
for (int i = 0; i < filteredItems.Length; i++)
{
propertyHolder = filteredPropertyHolderCollection[i];
if (propertyHolder.ImageFileHolder is null)
item = filteredItems[i];
if (item.ImageFileHolder is null)
continue;
if (propertyHolder.Property?.Id is null || propertyHolder.MinimumDateTime is null || propertyHolder.ResizedFileHolder is null)
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
if (!propertyLogic.NamedFaceInfoDeterministicHashCodeIndices.ContainsKey(propertyHolder.Property.Id.Value))
if (!propertyLogic.NamedFaceInfoDeterministicHashCodeIndices.ContainsKey(item.Property.Id.Value))
continue;
minimumDateTime = Stateless.A_Property.GetMinimumDateTime(propertyHolder.Property);
personKeys = propertyLogic.NamedFaceInfoDeterministicHashCodeIndices[propertyHolder.Property.Id.Value];
(isWrongYear, _) = propertyHolder.Property.IsWrongYear(propertyHolder.ImageFileHolder.FullName, minimumDateTime);
minimumDateTime = Stateless.A_Property.GetMinimumDateTime(item.Property);
personKeys = propertyLogic.NamedFaceInfoDeterministicHashCodeIndices[item.Property.Id.Value];
(isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime);
for (int j = 0; j < personKeys.Length; j++)
{
segments = Shared.Models.Stateless.Methods.IPersonBirthday.GetSegments(personKeys[j]);
@ -138,14 +121,15 @@ public class PropertyHolder
pixelPercentage = null;
else
pixelPercentage = value;
propertyHolder.Named.Add(new(isWrongYear, minimumDateTime, personBirthday, pixelPercentage));
item.Named.Add(new(isWrongYear, minimumDateTime, personBirthday, pixelPercentage));
}
}
}
public static List<(PropertyHolder, (string, IFace?, (string, string, string, string))[])> GetCollection(PropertyLogic propertyLogic, PropertyHolder[] filteredPropertyHolderCollection, string dFacesContentDirectory)
public static List<(Item, (string, IFace?, (string, string, string, string))[])> GetCollection(PropertyLogic propertyLogic, Item[] filteredItems, string dFacesContentDirectory)
{
List<(PropertyHolder, (string, IFace?, (string, string, string, string))[])> results = new();
List<(Item, (string, IFace?, (string, string, string, string))[])> results = new();
Item item;
string[] keys;
string directory;
string personKey;
@ -160,37 +144,40 @@ public class PropertyHolder
string shortcutFileName;
string subDirectoryName;
List<int> indices = new();
DateTime? minimumDateTime;
List<IFace> faceCollection;
PropertyHolder propertyHolder;
PersonBirthday? personBirthday;
List<(string, IFace?, (string, string, string, string))> collection;
for (int i = 0; i < filteredPropertyHolderCollection.Length; i++)
for (int i = 0; i < filteredItems.Length; i++)
{
indices.Clear();
personKey = string.Empty;
copyFileName = string.Empty;
copyDirectory = string.Empty;
propertyHolder = filteredPropertyHolderCollection[i];
if (propertyHolder.ImageFileHolder is null)
item = filteredItems[i];
if (item.ImageFileHolder is null)
continue;
relativePath = Path.GetDirectoryName($"C:{propertyHolder.RelativePath}");
relativePath = Path.GetDirectoryName($"C:{item.RelativePath}");
if (string.IsNullOrEmpty(relativePath) || relativePath.Length < 3)
continue;
if (propertyHolder.Property?.Id is null || propertyHolder.MinimumDateTime is null || propertyHolder.ResizedFileHolder is null)
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
collection = new();
if (!propertyLogic.NamedFaceInfoDeterministicHashCodeIndices.ContainsKey(propertyHolder.Property.Id.Value))
if (!propertyLogic.NamedFaceInfoDeterministicHashCodeIndices.ContainsKey(item.Property.Id.Value))
{
faceCollection = new();
directory = Path.Combine(dFacesContentDirectory, $"Unnamed{relativePath[2..]}");
}
else
{
faceCollection = propertyHolder.Faces;
keys = propertyLogic.NamedFaceInfoDeterministicHashCodeIndices[propertyHolder.Property.Id.Value];
(isWrongYear, _) = propertyHolder.Property.IsWrongYear(propertyHolder.ImageFileHolder.FullName, propertyHolder.MinimumDateTime.Value);
faceCollection = item.Faces;
keys = propertyLogic.NamedFaceInfoDeterministicHashCodeIndices[item.Property.Id.Value];
minimumDateTime = Stateless.A_Property.GetMinimumDateTime(item.Property);
if (minimumDateTime is null)
continue;
(isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime.Value);
isWrongYearFlag = GetWrongYearFlag(isWrongYear);
subDirectoryName = $"{isWrongYearFlag}{propertyHolder.MinimumDateTime.Value:yyyy}";
subDirectoryName = $"{isWrongYearFlag}{minimumDateTime.Value:yyyy}";
if (!faceCollection.Any())
directory = Path.Combine(dFacesContentDirectory, $"None{relativePath[2..]}", subDirectoryName);
else if (keys.Length != 1)
@ -204,7 +191,7 @@ public class PropertyHolder
personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(keys[zero]);
if (personBirthday is null)
continue;
timeSpan = Shared.Models.Stateless.Methods.IPersonBirthday.GetTimeSpan(propertyHolder.MinimumDateTime.Value, isWrongYear, personBirthday);
timeSpan = Shared.Models.Stateless.Methods.IPersonBirthday.GetTimeSpan(minimumDateTime.Value, isWrongYear, personBirthday);
if (timeSpan.HasValue)
{
if (timeSpan.Value.Ticks < 0)
@ -218,10 +205,10 @@ public class PropertyHolder
copyDirectory = Path.Combine(dFacesContentDirectory, "Images", personKey, subDirectoryName);
else
copyDirectory = Path.Combine(dFacesContentDirectory, "ImagesBut", personKey, subDirectoryName);
copyFileName = Path.Combine(copyDirectory, $"{propertyHolder.Property.Id.Value}{propertyHolder.ResizedFileHolder.Extension}");
copyFileName = Path.Combine(copyDirectory, $"{item.Property.Id.Value}{item.ResizedFileHolder.ExtensionLowered}");
}
}
shortcutFileName = Path.Combine(directory, $"{propertyHolder.Property.Id.Value}.lnk");
shortcutFileName = Path.Combine(directory, $"{item.Property.Id.Value}.lnk");
if (string.IsNullOrEmpty(personKey) || !indices.Any())
collection.Add(new(personKey, null, (directory, copyDirectory, copyFileName, shortcutFileName)));
else
@ -229,56 +216,75 @@ public class PropertyHolder
foreach (int index in indices)
collection.Add(new(personKey, faceCollection[index], (directory, copyDirectory, copyFileName, shortcutFileName)));
}
results.Add(new(propertyHolder, collection.ToArray()));
results.Add(new(item, collection.ToArray()));
}
return results;
}
public static Dictionary<string, List<(string[], PersonBirthday, IFace)>> GetKeyValuePairs(string argZero, List<PropertyHolder[]> propertyHolderCollections)
public static string GetKey(DateTime minimumDateTime, bool? isWrongYear, PersonBirthday personBirthday)
{
Dictionary<string, List<(string[], PersonBirthday, IFace)>> results = new();
string key;
string personKey;
TimeSpan? timeSpan;
string[] directories;
string isWrongYearFlag;
const string facePopulatedKey = "Images";
foreach (PropertyHolder[] propertyHolderCollection in propertyHolderCollections)
string result;
string personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthday);
TimeSpan? timeSpan = Shared.Models.Stateless.Methods.IPersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear, personBirthday);
if (timeSpan.HasValue && timeSpan.Value.Ticks < 0)
result = string.Concat(personKey, "!---");
else if (timeSpan.HasValue)
result = string.Concat(personKey, $"^{Math.Floor(timeSpan.Value.TotalDays / 365):000}");
else
{
if (!propertyHolderCollection.Any())
string isWrongYearFlag = GetWrongYearFlag(isWrongYear);
result = string.Concat(personKey, $"{isWrongYearFlag}{minimumDateTime:yyyy}");
}
return result;
}
public static string GetDirectory(string directory, string subDirectory, DateTime minimumDateTime, bool? isWrongYear, PersonBirthday personBirthday, string personKey)
{
string result;
TimeSpan? timeSpan = Shared.Models.Stateless.Methods.IPersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear, personBirthday);
if (timeSpan.HasValue && timeSpan.Value.Ticks < 0)
result = Path.Combine(directory, subDirectory, personKey, "!---");
else if (timeSpan.HasValue)
result = Path.Combine(directory, subDirectory, personKey, $"^{Math.Floor(timeSpan.Value.TotalDays / 365):000}");
else
{
string isWrongYearFlag = GetWrongYearFlag(isWrongYear);
result = Path.Combine(directory, subDirectory, personKey, $"{isWrongYearFlag}{minimumDateTime:yyyy}");
}
return result;
}
public static Dictionary<string, List<(DateTime, bool?, PersonBirthday, IFace)>> GetKeyValuePairs(string argZero, List<Container> containers)
{
Dictionary<string, List<(DateTime, bool?, PersonBirthday, IFace)>> results = new();
string key;
foreach (Container container in containers)
{
if (!container.Items.Any())
continue;
if (!propertyHolderCollection[0].SourceDirectory.StartsWith(argZero))
if (!container.SourceDirectory.StartsWith(argZero))
continue;
foreach (PropertyHolder propertyHolder in propertyHolderCollection)
foreach (Item item in container.Items)
{
if (propertyHolder.ImageFileHolder is null || propertyHolder.Property is null || !propertyHolder.Named.Any())
if (item.ImageFileHolder is null || item.Property is null || !item.Named.Any())
continue;
foreach ((bool? isWrongYear, DateTime minimumDateTime, PersonBirthday personBirthday, double? pixelPercentage) in propertyHolder.Named)
foreach (Named named in item.Named)
{
if (pixelPercentage is null && (propertyHolder.Named.Count != 1 || propertyHolder.Faces.Count != 1))
if (named.PixelPercentage is null && (item.Named.Count != 1 || item.Faces.Count != 1))
continue;
foreach (IFace face in propertyHolder.Faces)
foreach (IFace face in item.Faces)
{
if (!face.Populated)
continue;
if (pixelPercentage.HasValue && pixelPercentage.Value != face.Location.PixelPercentage)
if (named.PersonBirthday is null)
continue;
personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthday);
timeSpan = Shared.Models.Stateless.Methods.IPersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear, personBirthday);
if (timeSpan.HasValue && timeSpan.Value.Ticks < 0)
directories = new string[] { string.Empty, facePopulatedKey, personKey, "!---" };
else if (timeSpan.HasValue)
directories = new string[] { string.Empty, facePopulatedKey, personKey, $"^{Math.Floor(timeSpan.Value.TotalDays / 365):000}" };
else
{
isWrongYearFlag = GetWrongYearFlag(isWrongYear);
directories = new string[] { string.Empty, facePopulatedKey, personKey, $"{isWrongYearFlag}{minimumDateTime:yyyy}" };
}
key = string.Join('\t', directories);
if (named.PixelPercentage.HasValue && named.PixelPercentage.Value != face.Location.PixelPercentage)
continue;
key = GetKey(named.MinimumDateTime, named.IsWrongYear, named.PersonBirthday);
if (!results.ContainsKey(key))
results.Add(key, new());
results[key].Add(new(directories, personBirthday, face));
if (pixelPercentage is null)
results[key].Add(new(named.MinimumDateTime, named.IsWrongYear, named.PersonBirthday, face));
if (named.PixelPercentage is null)
break;
}
}

27
Property/Models/Named.cs Normal file
View File

@ -0,0 +1,27 @@
using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Property.Models;
public class Named
{
protected readonly bool? _IsWrongYear;
protected readonly DateTime _MinimumDateTime;
protected readonly PersonBirthday? _PersonBirthday;
protected readonly double? _PixelPercentage;
public bool? IsWrongYear => _IsWrongYear;
public DateTime MinimumDateTime => _MinimumDateTime;
public PersonBirthday? PersonBirthday => _PersonBirthday;
public double? PixelPercentage => _PixelPercentage;
[JsonConstructor]
public Named(bool? isWrongYear, DateTime minimumDateTime, PersonBirthday? personBirthday, double? pixelPercentage)
{
_IsWrongYear = isWrongYear;
_MinimumDateTime = minimumDateTime;
_PersonBirthday = personBirthday;
_PixelPercentage = pixelPercentage;
}
}

View File

@ -21,24 +21,30 @@ public class PropertyLogic
protected readonly Dictionary<int, string[]> _SixCharacterNamedFaceInfo;
protected readonly Dictionary<int, string[]> _NamedFaceInfoDeterministicHashCodeIndices;
public bool Reverse { get; }
public List<string> AngleBracketCollection { get; }
public Dictionary<int, int[]> KeyValuePairs => _KeyValuePairs;
public Dictionary<int, int[]> IndicesFromNew => _IndicesFromNew;
public List<string> ExceptionsDirectories => _ExceptionsDirectories;
public Dictionary<int, string[]> NamedFaceInfoDeterministicHashCodeIndices => _NamedFaceInfoDeterministicHashCodeIndices;
private readonly Model? _Model;
private readonly Serilog.ILogger? _Log;
private readonly string[] _VerifyToSeason;
private readonly int _MaxDegreeOfParallelism;
private readonly ASCIIEncoding _ASCIIEncoding;
private readonly Configuration _Configuration;
private readonly PredictorModel? _PredictorModel;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
public PropertyLogic(int maxDegreeOfParallelism, Configuration configuration)
public PropertyLogic(int maxDegreeOfParallelism, Configuration configuration, bool reverse, Model? model, PredictorModel? predictorModel)
{
_Model = model;
Reverse = reverse;
_AllCollection = new();
_Configuration = configuration;
_ExceptionsDirectories = new();
_PredictorModel = predictorModel;
_ASCIIEncoding = new ASCIIEncoding();
AngleBracketCollection = new List<string>();
_Log = Serilog.Log.ForContext<A_Property>();
@ -57,7 +63,7 @@ public class PropertyLogic
Dictionary<int, string[]>? sixCharacterNamedFaceInfo;
string? rootDirectoryParent = Path.GetDirectoryName(configuration.RootDirectory);
if (string.IsNullOrEmpty(rootDirectoryParent))
throw new ArgumentNullException(nameof(rootDirectoryParent));
throw new NullReferenceException(nameof(rootDirectoryParent));
files = Directory.GetFiles(rootDirectoryParent, "*DeterministicHashCode*.json", SearchOption.TopDirectoryOnly);
if (files.Length != 1)
namedFaceInfoDeterministicHashCodeIndices = new();
@ -66,7 +72,7 @@ public class PropertyLogic
json = File.ReadAllText(files[0]);
namedFaceInfoDeterministicHashCodeIndices = JsonSerializer.Deserialize<Dictionary<int, string[]>>(json);
if (namedFaceInfoDeterministicHashCodeIndices is null)
throw new ArgumentNullException(nameof(namedFaceInfoDeterministicHashCodeIndices));
throw new NullReferenceException(nameof(namedFaceInfoDeterministicHashCodeIndices));
}
if (namedFaceInfoDeterministicHashCodeIndices.Any())
sixCharacterNamedFaceInfo = new();
@ -80,7 +86,7 @@ public class PropertyLogic
json = File.ReadAllText(files[0]);
sixCharacterNamedFaceInfo = JsonSerializer.Deserialize<Dictionary<int, string[]>>(json);
if (sixCharacterNamedFaceInfo is null)
throw new ArgumentNullException(nameof(sixCharacterNamedFaceInfo));
throw new NullReferenceException(nameof(sixCharacterNamedFaceInfo));
}
}
files = Directory.GetFiles(rootDirectoryParent, "*keyValuePairs*.json", SearchOption.TopDirectoryOnly);
@ -91,7 +97,7 @@ public class PropertyLogic
json = File.ReadAllText(files[0]);
keyValuePairs = JsonSerializer.Deserialize<Dictionary<int, int[]>>(json);
if (keyValuePairs is null)
throw new ArgumentNullException(nameof(keyValuePairs));
throw new NullReferenceException(nameof(keyValuePairs));
}
foreach (string propertyContentCollectionFile in configuration.PropertyContentCollectionFiles)
{
@ -103,7 +109,7 @@ public class PropertyLogic
json = File.ReadAllText(fullPath);
collection = JsonSerializer.Deserialize<List<KeyValuePair<int, int[]>>>(json);
if (collection is null)
throw new ArgumentNullException(nameof(collection));
throw new NullReferenceException(nameof(collection));
foreach (KeyValuePair<int, int[]> keyValuePair in collection)
{
if (indicesFromNew.ContainsKey(keyValuePair.Key))
@ -127,7 +133,7 @@ public class PropertyLogic
{
long result;
if (_Log is null)
throw new ArgumentNullException(nameof(_Log));
throw new NullReferenceException(nameof(_Log));
double delta = new TimeSpan(DateTime.Now.Ticks - ticks).TotalMilliseconds;
_Log.Debug($"{methodName} took {Math.Floor(delta)} millisecond(s)");
result = DateTime.Now.Ticks;
@ -168,13 +174,13 @@ public class PropertyLogic
#pragma warning disable CA1416
private A_Property GetImageProperty(string angleBracket, FileHolder filteredSourceDirectoryFileHolder, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id, List<int> indices)
private A_Property GetImageProperty(FileHolder filteredSourceDirectoryFileHolder, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id, List<int> indices)
{
A_Property result;
if (_Log is null)
throw new ArgumentNullException(nameof(_Log));
throw new NullReferenceException(nameof(_Log));
if (_Configuration.WriteBitmapDataBytes is null)
throw new ArgumentNullException(nameof(_Configuration.WriteBitmapDataBytes));
throw new NullReferenceException(nameof(_Configuration.WriteBitmapDataBytes));
long ticks;
byte[] bytes;
string value;
@ -201,7 +207,7 @@ public class PropertyLogic
}
else if (!isIgnoreExtension && isValidImageFormatExtension)
{
if (!_IndicesFromNew.Any() && !_KeyValuePairs.Any())
if (populateId && (id is null || !indices.Any()) && !_IndicesFromNew.Any() && !_KeyValuePairs.Any())
throw new Exception("In order to keep six character indices at least one need to have an item!");
try
{
@ -209,6 +215,7 @@ public class PropertyLogic
if (populateId && (id is null || !indices.Any()))
{
using Bitmap bitmap = new(image);
string angleBracket = AngleBracketCollection[0];
Rectangle rectangle = new(0, 0, image.Width, image.Height);
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
IntPtr intPtr = bitmapData.Scan0;
@ -341,24 +348,27 @@ public class PropertyLogic
#pragma warning restore CA1416
private A_Property GetPropertyOfPrivate(string angleBracket, PropertyHolder propertyHolder, bool firstPass, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, string extensionLowered)
private A_Property GetPropertyOfPrivate(Item item, bool firstPass, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension, bool isValidMetadataExtensions)
{
A_Property? result;
if (_Configuration.ForcePropertyLastWriteTimeToCreationTime is null)
throw new ArgumentNullException(nameof(_Configuration.ForcePropertyLastWriteTimeToCreationTime));
throw new NullReferenceException(nameof(_Configuration.ForcePropertyLastWriteTimeToCreationTime));
if (_Configuration.PopulatePropertyId is null)
throw new ArgumentNullException(nameof(_Configuration.PopulatePropertyId));
throw new NullReferenceException(nameof(_Configuration.PopulatePropertyId));
if (_Configuration.PropertiesChangedForProperty is null)
throw new ArgumentNullException(nameof(_Configuration.PropertiesChangedForProperty));
throw new NullReferenceException(nameof(_Configuration.PropertiesChangedForProperty));
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
string json;
int? id = null;
List<int> indices = new();
bool hasWrongYearProperty = false;
string[] changesFrom = Array.Empty<string>();
string angleBracket = AngleBracketCollection[0];
bool populateId = !firstPass && _Configuration.PopulatePropertyId.Value;
string without = Path.Combine(angleBracket.Replace("<>", "{}"), $"{propertyHolder.ImageFileNameWithoutExtension}.json");
FileInfo fileInfo = new(Path.Combine(angleBracket.Replace("<>", "{}"), $"{propertyHolder.ImageFileNameWithoutExtension}{extensionLowered}.json"));
if (isValidImageFormatExtension && File.Exists(without))
string without = Path.Combine(angleBracket.Replace("<>", "{}"), $"{item.ImageFileHolder.NameWithoutExtension}.json");
FileInfo fileInfo = new(Path.Combine(angleBracket.Replace("<>", "{}"), $"{item.ImageFileHolder.NameWithoutExtension}{item.ImageFileHolder.ExtensionLowered}.json"));
if (item.ValidImageFormatExtension && File.Exists(without))
{
File.Move(without, fileInfo.FullName);
fileInfo.Refresh();
@ -398,40 +408,40 @@ public class PropertyLogic
json = File.ReadAllText(fileInfo.FullName);
try
{
if (propertyHolder.ImageFileHolder is null)
throw new ArgumentException($"{propertyHolder.ImageFileHolder} is null!");
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
bool check = true;
A_Property? property = JsonSerializer.Deserialize<A_Property>(json);
if (!isIgnoreExtension && isValidImageFormatExtension && ((populateId && property?.Id is null) || property?.Width is null || property?.Height is null))
if (!isIgnoreExtension && item.ValidImageFormatExtension && ((populateId && property?.Id is null) || property?.Width is null || property?.Height is null))
{
check = false;
id = property?.Id;
if (property is not null && property.Indices.Any())
indices = property.Indices.ToList();
property = GetImageProperty(angleBracket, propertyHolder.ImageFileHolder, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
property = GetImageProperty(item.ImageFileHolder, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices);
}
if (!isIgnoreExtension && isValidImageFormatExtension && populateId && property is not null && !property.Indices.Any())
if (!isIgnoreExtension && item.ValidImageFormatExtension && populateId && property is not null && !property.Indices.Any())
{
check = false;
id = property?.Id;
if (property is not null && property.Indices.Any())
indices = property.Indices.ToList();
property = GetImageProperty(angleBracket, propertyHolder.ImageFileHolder, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
property = GetImageProperty(item.ImageFileHolder, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices);
}
if (!isIgnoreExtension && isValidImageFormatExtension && populateId && property is not null && property.LastWriteTime != propertyHolder.ImageFileHolder.LastWriteTime)
if (!isIgnoreExtension && item.ValidImageFormatExtension && populateId && property is not null && property.LastWriteTime != item.ImageFileHolder.LastWriteTime)
{
check = false;
id = null;
indices.Clear();
property = GetImageProperty(angleBracket, propertyHolder.ImageFileHolder, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
property = GetImageProperty(item.ImageFileHolder, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices);
}
if (!isIgnoreExtension && isValidImageFormatExtension && property?.Width is not null && property?.Height is not null && property.Width.Value == property.Height.Value && propertyHolder.ImageFileHolder.Exists)
if (!isIgnoreExtension && item.ValidImageFormatExtension && property?.Width is not null && property?.Height is not null && property.Width.Value == property.Height.Value && item.ImageFileHolder.Exists)
{
check = false;
id = property?.Id;
if (property is not null && property.Indices.Any())
indices = property.Indices.ToList();
property = GetImageProperty(angleBracket, propertyHolder.ImageFileHolder, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
property = GetImageProperty(item.ImageFileHolder, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices);
if (property?.Width is not null && property?.Height is not null && property.Width.Value != property.Height.Value)
throw new Exception("Was square!");
}
@ -440,7 +450,7 @@ public class PropertyLogic
// check = false;
// id = null;
// indices.Clear();
// property = GetImagePropertyB(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
// property = GetImagePropertyB(filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
// }
if (json.Contains("WrongYear"))
{
@ -465,9 +475,9 @@ public class PropertyLogic
}
if (result is null)
{
if (propertyHolder.ImageFileHolder is null)
throw new ArgumentException($"{propertyHolder.ImageFileHolder} is null!");
result = GetImageProperty(angleBracket, propertyHolder.ImageFileHolder, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
result = GetImageProperty(item.ImageFileHolder, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices);
json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions);
if (populateId && IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true))
{
@ -494,11 +504,11 @@ public class PropertyLogic
return result;
}
private bool AnyFilesMoved(string sourceDirectory, PropertyHolder[] filteredPropertyHolderCollection)
private bool AnyFilesMoved(string sourceDirectory, Item[] filteredItems)
{
bool result = false;
if (_Log is null)
throw new ArgumentNullException(nameof(_Log));
throw new NullReferenceException(nameof(_Log));
int season;
string[] matches;
string deleteFile;
@ -510,20 +520,16 @@ public class PropertyLogic
string destinationDirectory;
string[] sourceDirectorySegments;
DateTime directoryMaximumOfMinimumDateTime = DateTime.MinValue;
foreach (PropertyHolder propertyHolder in filteredPropertyHolderCollection)
foreach (Item filteredItem in filteredItems)
{
if (propertyHolder.ValidImageFormatExtension is null || !propertyHolder.ValidImageFormatExtension.Value)
if (!filteredItem.ValidImageFormatExtension || filteredItem.Property is null || filteredItem.ImageFileHolder is null)
continue;
if (propertyHolder.Property is null)
continue;
if (propertyHolder.ImageFileHolder is null)
continue;
minimumDateTime = Stateless.A_Property.GetMinimumDateTime(propertyHolder.Property);
minimumDateTime = Stateless.A_Property.GetMinimumDateTime(filteredItem.Property);
if (minimumDateTime > directoryMaximumOfMinimumDateTime)
directoryMaximumOfMinimumDateTime = minimumDateTime;
if (minimumDateTime != propertyHolder.ImageFileHolder.CreationTime)
if (minimumDateTime != filteredItem.ImageFileHolder.CreationTime)
{
(isWrongYear, matches) = propertyHolder.Property.IsWrongYear(propertyHolder.ImageFileHolder.FullName, minimumDateTime);
(isWrongYear, matches) = filteredItem.Property.IsWrongYear(filteredItem.ImageFileHolder.FullName, minimumDateTime);
if (isWrongYear is null || !isWrongYear.Value)
dateTime = minimumDateTime;
else
@ -534,20 +540,20 @@ public class PropertyLogic
continue;
}
try
{ File.SetCreationTime(propertyHolder.ImageFileHolder.FullName, dateTime); }
{ File.SetCreationTime(filteredItem.ImageFileHolder.FullName, dateTime); }
catch (Exception)
{ }
}
if (!_VerifyToSeason.Contains(sourceDirectory))
continue;
if (!propertyHolder.ImageFileHolder.FullName.Contains("zzz ") && !propertyHolder.ImageFileHolder.FullName.Contains("Camera ") && propertyHolder.Property.DateTimeOriginal.HasValue)
if (!filteredItem.ImageFileHolder.FullName.Contains("zzz ") && !filteredItem.ImageFileHolder.FullName.Contains("Camera ") && filteredItem.Property.DateTimeOriginal.HasValue)
{
TimeSpan timeSpan = new(propertyHolder.Property.DateTimeOriginal.Value.Ticks - propertyHolder.Property.LastWriteTime.Ticks);
TimeSpan timeSpan = new(filteredItem.Property.DateTimeOriginal.Value.Ticks - filteredItem.Property.LastWriteTime.Ticks);
if (timeSpan.TotalHours > 6)
{
_Log.Warning($"*** propertyHolder.FileInfo.FullName <{propertyHolder.ImageFileHolder.FullName}>");
_Log.Warning($"*** DateTimeOriginal <{propertyHolder.Property.DateTimeOriginal.Value}>");
_Log.Warning($"*** LastWriteTime <{propertyHolder.Property.LastWriteTime}>");
_Log.Warning($"*** propertyHolder.FileInfo.FullName <{filteredItem.ImageFileHolder.FullName}>");
_Log.Warning($"*** DateTimeOriginal <{filteredItem.Property.DateTimeOriginal.Value}>");
_Log.Warning($"*** LastWriteTime <{filteredItem.Property.LastWriteTime}>");
_Log.Warning($"*** TotalHours <{timeSpan.TotalHours}>");
}
}
@ -561,41 +567,41 @@ public class PropertyLogic
destinationDirectory = Path.Combine(_Configuration.RootDirectory, $"={minimumDateTime:yyyy}.{season} {seasonName}");
if (destinationDirectory == sourceDirectory)
continue;
lock (propertyHolder)
propertyHolder.SetMoved(true);
lock (filteredItem)
filteredItem.SetMoved(true);
if (!result)
result = true;
if (!Directory.Exists(destinationDirectory))
_ = Directory.CreateDirectory(destinationDirectory);
destinationFile = Path.Combine(destinationDirectory, propertyHolder.ImageFileHolder.Name);
destinationFile = Path.Combine(destinationDirectory, filteredItem.ImageFileHolder.Name);
if (File.Exists(destinationFile))
{
if (destinationFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
destinationFile = Path.Combine(destinationDirectory, Path.ChangeExtension(propertyHolder.ImageFileHolder.Name, ".jpeg"));
destinationFile = Path.Combine(destinationDirectory, Path.ChangeExtension(filteredItem.ImageFileHolder.Name, ".jpeg"));
else if (destinationFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
destinationFile = Path.Combine(destinationDirectory, Path.ChangeExtension(propertyHolder.ImageFileHolder.Name, ".jpg"));
destinationFile = Path.Combine(destinationDirectory, Path.ChangeExtension(filteredItem.ImageFileHolder.Name, ".jpg"));
}
if (File.Exists(destinationFile))
{
_Log.Information($"*** source <{propertyHolder.ImageFileHolder.FullName}>");
_Log.Information($"*** source <{filteredItem.ImageFileHolder.FullName}>");
_Log.Information($"*** destination <{destinationFile}>");
if (propertyHolder.ImageFileHolder.Exists)
if (filteredItem.ImageFileHolder.Exists)
{
deleteFile = Path.ChangeExtension(propertyHolder.ImageFileHolder.FullName, ".delete");
deleteFile = Path.ChangeExtension(filteredItem.ImageFileHolder.FullName, ".delete");
if (File.Exists(deleteFile))
File.Delete(deleteFile);
File.Move(propertyHolder.ImageFileHolder.FullName, deleteFile);
File.Move(filteredItem.ImageFileHolder.FullName, deleteFile);
}
}
else
{
File.Move(propertyHolder.ImageFileHolder.FullName, destinationFile);
if (propertyHolder.ImageFileHolder.Exists)
File.Move(filteredItem.ImageFileHolder.FullName, destinationFile);
if (filteredItem.ImageFileHolder.Exists)
{
deleteFile = Path.ChangeExtension(propertyHolder.ImageFileHolder.FullName, ".delete");
deleteFile = Path.ChangeExtension(filteredItem.ImageFileHolder.FullName, ".delete");
if (File.Exists(deleteFile))
File.Delete(deleteFile);
File.Move(propertyHolder.ImageFileHolder.FullName, deleteFile);
File.Move(filteredItem.ImageFileHolder.FullName, deleteFile);
}
}
}
@ -608,46 +614,42 @@ public class PropertyLogic
return result;
}
private void ParallelForWork(bool firstPass, string angleBracket, string sourceDirectory, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, PropertyHolder propertyHolder)
private void ParallelForWork(bool firstPass, string sourceDirectory, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item item)
{
if (propertyHolder.ImageFileHolder is null)
throw new ArgumentNullException(nameof(propertyHolder.ImageFileHolder));
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
A_Property property;
List<string> parseExceptions = new();
string extensionLowered = propertyHolder.ImageFileHolder.Extension.ToLower();
bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(extensionLowered);
bool isValidImageFormatExtension = _Configuration.ValidImageFormatExtensions.Contains(extensionLowered);
lock (propertyHolder)
propertyHolder.SetValidImageFormatExtension(isValidImageFormatExtension);
bool isIgnoreExtension = isValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(extensionLowered);
string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{propertyHolder.ImageFileNameWithoutExtension}{extensionLowered}");
if (isValidImageFormatExtension && propertyHolder.ImageFileHolder.FullName.Length == filteredSourceDirectoryFileExtensionLowered.Length && propertyHolder.ImageFileHolder.FullName != filteredSourceDirectoryFileExtensionLowered)
File.Move(propertyHolder.ImageFileHolder.FullName, filteredSourceDirectoryFileExtensionLowered);
if (propertyHolder.Changed is null || propertyHolder.Changed.Value || propertyHolder.Property is null)
bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
bool isIgnoreExtension = item.ValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{item.ImageFileHolder.NameWithoutExtension}{item.ImageFileHolder.ExtensionLowered}");
if (item.ValidImageFormatExtension && item.ImageFileHolder.FullName.Length == filteredSourceDirectoryFileExtensionLowered.Length && item.ImageFileHolder.FullName != filteredSourceDirectoryFileExtensionLowered)
File.Move(item.ImageFileHolder.FullName, filteredSourceDirectoryFileExtensionLowered);
if (item.Changed is null || item.Changed.Value || item.Property is null)
{
property = GetPropertyOfPrivate(angleBracket, propertyHolder, firstPass, filteredSourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, extensionLowered);
property = GetPropertyOfPrivate(item, firstPass, filteredSourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidMetadataExtensions);
lock (sourceDirectoryChanges)
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
lock (propertyHolder)
propertyHolder.Update(property);
lock (item)
item.Update(property);
}
}
private void ParallelWork(bool firstPass, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, int propertyHolderCollectionsCount, int g, string sourceDirectory, int r, PropertyHolder[] filteredPropertyHolderCollection, int totalSeconds, string angleBracket)
private void ParallelWork(bool firstPass, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, int containersCount, Container container, Item[] filteredItems, int totalSeconds)
{
List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples = new();
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _MaxDegreeOfParallelism };
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
string message = $"{r + 1:000}.{g} / {propertyHolderCollectionsCount:000}) {filteredPropertyHolderCollection.Length:000} file(s) - {totalSeconds} total second(s) - {sourceDirectory}";
using ProgressBar progressBar = new(filteredPropertyHolderCollection.Length, message, options);
_ = Parallel.For(0, filteredPropertyHolderCollection.Length, parallelOptions, i =>
string message = $"{container.R + 1:000}.{container.G} / {containersCount:000}) {filteredItems.Length:000} file(s) - {totalSeconds} total second(s) - {container.SourceDirectory}";
using ProgressBar progressBar = new(filteredItems.Length, message, options);
_ = Parallel.For(0, filteredItems.Length, parallelOptions, i =>
{
try
{
long ticks = DateTime.Now.Ticks;
DateTime dateTime = DateTime.Now;
List<Tuple<string, DateTime>> collection;
ParallelForWork(firstPass, angleBracket, sourceDirectory, sourceDirectoryChanges, filteredSourceDirectoryFileTuples, filteredPropertyHolderCollection[i]);
ParallelForWork(firstPass, container.SourceDirectory, sourceDirectoryChanges, filteredSourceDirectoryFileTuples, filteredItems[i]);
if (i == 0 || sourceDirectoryChanges.Any())
progressBar.Tick();
lock (filteredSourceDirectoryFileTuples)
@ -663,13 +665,12 @@ public class PropertyLogic
});
}
private string SetAngleBracketCollectionAndGetZero(Configuration configuration, Model? model, PredictorModel? predictorModel, string sourceDirectory)
private void SetAngleBracketCollection(string sourceDirectory)
{
string result;
AngleBracketCollection.Clear();
AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(configuration,
model,
predictorModel,
AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(_Configuration,
_Model,
_PredictorModel,
sourceDirectory,
nameof(A_Property),
string.Empty,
@ -679,54 +680,45 @@ public class PropertyLogic
contentDescription: string.Empty,
singletonDescription: "Properties for each image",
collectionDescription: string.Empty));
result = AngleBracketCollection[0];
return result;
}
public void ParallelWork(Configuration configuration, Model? model, PredictorModel? predictorModel, long ticks, List<PropertyHolder[]> propertyHolderCollections, bool firstPass)
public void ParallelWork(long ticks, List<Container> containers, bool firstPass)
{
if (_Log is null)
throw new ArgumentNullException(nameof(_Log));
throw new NullReferenceException(nameof(_Log));
if (_Configuration.PopulatePropertyId is null)
throw new ArgumentNullException(nameof(_Configuration.PopulatePropertyId));
int g;
int r;
throw new NullReferenceException(nameof(_Configuration.PopulatePropertyId));
int totalSeconds;
bool? anyFilesMoved;
string angleBracket;
string sourceDirectory;
Item[] filteredItems;
List<Exception> exceptions = new();
PropertyHolder[] filteredPropertyHolderCollection;
int containersCount = containers.Count;
List<Tuple<string, DateTime>> sourceDirectoryChanges = new();
int propertyHolderCollectionsCount = propertyHolderCollections.Count;
string propertyRoot = IResult.GetResultsGroupDirectory(configuration, nameof(A_Property));
foreach (PropertyHolder[] propertyHolderCollection in propertyHolderCollections)
string propertyRoot = IResult.GetResultsGroupDirectory(_Configuration, nameof(A_Property));
foreach (Container container in containers)
{
if (!propertyHolderCollection.Any())
if (!container.Items.Any())
continue;
sourceDirectoryChanges.Clear();
if (firstPass)
filteredPropertyHolderCollection = (from l in propertyHolderCollection where l.NoJson is null || !l.NoJson.Value && (l.Changed is null || l.Changed.Value) select l).ToArray();
filteredItems = (from l in container.Items where l.NoJson is null || !l.NoJson.Value && (l.Changed is null || l.Changed.Value) select l).ToArray();
else
filteredPropertyHolderCollection = (from l in propertyHolderCollection where l.ImageFileHolder is not null && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.Extension) select l).ToArray();
if (!filteredPropertyHolderCollection.Any())
filteredItems = (from l in container.Items where l.ImageFileHolder is not null && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray();
if (!filteredItems.Any())
continue;
g = filteredPropertyHolderCollection[0].G;
r = filteredPropertyHolderCollection[0].R;
sourceDirectory = filteredPropertyHolderCollection[0].SourceDirectory;
totalSeconds = (int)Math.Truncate(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
angleBracket = SetAngleBracketCollectionAndGetZero(configuration, model, predictorModel, sourceDirectory);
ParallelWork(firstPass, exceptions, sourceDirectoryChanges, propertyHolderCollectionsCount, g, sourceDirectory, r, filteredPropertyHolderCollection, totalSeconds, angleBracket);
SetAngleBracketCollection(container.SourceDirectory);
ParallelWork(firstPass, exceptions, sourceDirectoryChanges, containersCount, container, filteredItems, totalSeconds);
foreach (Exception exception in exceptions)
_Log.Error(string.Concat(sourceDirectory, Environment.NewLine, exception.Message, Environment.NewLine, exception.StackTrace), exception);
if (exceptions.Count == filteredPropertyHolderCollection.Length)
throw new Exception(string.Concat("All in [", sourceDirectory, "]failed!"));
_Log.Error(string.Concat(container.SourceDirectory, Environment.NewLine, exception.Message, Environment.NewLine, exception.StackTrace), exception);
if (exceptions.Count == filteredItems.Length)
throw new Exception(string.Concat("All in [", container.SourceDirectory, "]failed!"));
if (exceptions.Count != 0)
_ExceptionsDirectories.Add(sourceDirectory);
_ExceptionsDirectories.Add(container.SourceDirectory);
if (!firstPass || exceptions.Count != 0)
anyFilesMoved = null;
else
anyFilesMoved = AnyFilesMoved(sourceDirectory, filteredPropertyHolderCollection);
anyFilesMoved = AnyFilesMoved(container.SourceDirectory, filteredItems);
if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any())
{
for (int y = 0; y < int.MaxValue; y++)
@ -740,32 +732,30 @@ public class PropertyLogic
}
}
public A_Property GetProperty(string angleBracket, PropertyHolder propertyHolder, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<string> parseExceptions)
public A_Property GetProperty(Item item, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<string> parseExceptions)
{
A_Property result;
if (propertyHolder.ImageFileHolder is null)
throw new ArgumentException($"{propertyHolder.ImageFileHolder} is null!");
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
bool firstPass = false;
string extensionLowered = propertyHolder.ImageFileHolder.Extension.ToLower();
bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(extensionLowered);
bool isValidImageFormatExtension = _Configuration.ValidImageFormatExtensions.Contains(extensionLowered);
bool isIgnoreExtension = isValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(extensionLowered);
result = GetPropertyOfPrivate(angleBracket, propertyHolder, firstPass, filteredSourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, extensionLowered);
bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
bool isIgnoreExtension = item.ValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
result = GetPropertyOfPrivate(item, firstPass, filteredSourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidMetadataExtensions);
return result;
}
public (long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] GetPropertyIds(Configuration configuration, Model? model, PredictorModel? predictorModel, List<DirectoryInfo> groupCollection, bool saveToCollection)
public (long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] GetPropertyIds(List<DirectoryInfo> groupCollection, bool saveToCollection)
{
List<(long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)> results = new();
int level;
string angleBracket;
A_Property? property;
string checkDirectory;
List<string> directories;
string propertyDirectory;
string angleBracket = AngleBracketCollection[0];
foreach (DirectoryInfo group in groupCollection)
{
angleBracket = SetAngleBracketCollectionAndGetZero(configuration, model, predictorModel, group.SourceDirectory);
SetAngleBracketCollection(group.SourceDirectory);
if (string.IsNullOrEmpty(group.SourceDirectory))
throw new Exception();
if (!saveToCollection)
@ -789,23 +779,23 @@ public class PropertyLogic
return results.OrderBy(l => l.Ticks).ToArray();
}
public void AddToPropertyLogicAllCollection(PropertyHolder[] filteredPropertyHolderCollection)
public void AddToPropertyLogicAllCollection(Item[] filteredItems)
{
if (_SixCharacterNamedFaceInfo.Any())
{
string[] keys;
PropertyHolder propertyHolder;
for (int i = 0; i < filteredPropertyHolderCollection.Length; i++)
Item item;
for (int i = 0; i < filteredItems.Length; i++)
{
propertyHolder = filteredPropertyHolderCollection[i];
if (propertyHolder.Property?.Id is null)
item = filteredItems[i];
if (item.Property?.Id is null)
continue;
foreach (int sixCharacterIndex in propertyHolder.Property.Indices)
foreach (int sixCharacterIndex in item.Property.Indices)
{
if (!_SixCharacterNamedFaceInfo.ContainsKey(sixCharacterIndex))
continue;
keys = _SixCharacterNamedFaceInfo[sixCharacterIndex];
_AllCollection.Add(new(propertyHolder.Property.Id.Value, keys));
_AllCollection.Add(new(item.Property.Id.Value, keys));
}
}
}
@ -818,7 +808,7 @@ public class PropertyLogic
string[] keys;
string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.RootDirectory);
if (string.IsNullOrEmpty(rootDirectoryParent))
throw new ArgumentNullException(nameof(rootDirectoryParent));
throw new NullReferenceException(nameof(rootDirectoryParent));
Dictionary<int, string[]> namedFaceInfoDeterministicHashCodeIndices = new();
List<(int, string[])> allCollection = _AllCollection.OrderBy(l => l.Item1).ToList();
foreach ((int deterministicHashCode, string[] values) in allCollection)

View File

@ -1,6 +1,3 @@
using System.Text.Json;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Property.Models.Stateless;
public static class A_Property
@ -21,237 +18,14 @@ public static class A_Property
return result;
}
public static List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> GetGroupCollection(string rootDirectory, string searchPattern, List<string> topDirectories, int maxImagesInDirectoryForTopLevelFirstPass = 50, bool reverse = false)
public static List<Models.Container> Get(Models.Configuration configuration, PropertyLogic propertyLogic)
{
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> results = new();
string? parentDirectory;
string[] subDirectories;
string[] sourceDirectoryFiles;
List<string[]> fileCollections = new();
if (!topDirectories.Any())
topDirectories.AddRange(from l in Directory.GetDirectories(rootDirectory, "*", SearchOption.TopDirectoryOnly) select Path.GetFullPath(l));
for (int g = 1; g < 5; g++)
{
if (g == 4)
{
for (int i = fileCollections.Count - 1; i > -1; i--)
{
parentDirectory = Path.GetDirectoryName(fileCollections[i][0]);
if (string.IsNullOrEmpty(parentDirectory))
continue;
results.Add(new(g, parentDirectory, fileCollections[i], results.Count));
fileCollections.RemoveAt(i);
}
}
else if (g == 2)
{
fileCollections = (from l in fileCollections orderby l.Length descending select l).ToList();
for (int i = fileCollections.Count - 1; i > -1; i--)
{
if (fileCollections[i].Length > maxImagesInDirectoryForTopLevelFirstPass * g)
break;
parentDirectory = Path.GetDirectoryName(fileCollections[i][0]);
if (string.IsNullOrEmpty(parentDirectory))
continue;
results.Add(new(g, parentDirectory, fileCollections[i], results.Count));
fileCollections.RemoveAt(i);
}
}
else if (g == 3)
{
subDirectories = Directory.GetDirectories(rootDirectory, "*", SearchOption.AllDirectories);
if (reverse)
subDirectories = subDirectories.Reverse().ToArray();
foreach (string subDirectory in subDirectories)
{
sourceDirectoryFiles = Directory.GetFiles(subDirectory, "*", SearchOption.TopDirectoryOnly);
if (!topDirectories.Contains(subDirectory))
results.Add(new(g, subDirectory, sourceDirectoryFiles, results.Count));
}
}
else if (g == 1)
{
sourceDirectoryFiles = Directory.GetFiles(rootDirectory, searchPattern, SearchOption.TopDirectoryOnly);
if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass)
fileCollections.Add(sourceDirectoryFiles);
else
results.Add(new(g, rootDirectory, sourceDirectoryFiles, results.Count));
if (reverse)
topDirectories.Reverse();
subDirectories = topDirectories.ToArray();
foreach (string subDirectory in subDirectories)
{
sourceDirectoryFiles = Directory.GetFiles(subDirectory, searchPattern, SearchOption.TopDirectoryOnly);
if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass)
fileCollections.Add(sourceDirectoryFiles);
else
{
if (sourceDirectoryFiles.Any() || Directory.GetDirectories(subDirectory, "*", SearchOption.TopDirectoryOnly).Any())
results.Add(new(g, subDirectory, sourceDirectoryFiles, results.Count));
else if (searchPattern == "*")
{
sourceDirectoryFiles = Directory.GetFiles(subDirectory, searchPattern, SearchOption.TopDirectoryOnly);
foreach (string subFile in sourceDirectoryFiles)
File.Delete(subFile);
Directory.Delete(subDirectory);
}
}
}
fileCollections.Reverse();
}
else
throw new Exception();
}
return results;
}
public static List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> GetJsonGroupCollection(string rootDirectory)
{
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> results;
bool reverse = false;
string searchPattern = "*.json";
List<string> topDirectories = new();
int maxImagesInDirectoryForTopLevelFirstPass = 50;
results = GetGroupCollection(rootDirectory, searchPattern, topDirectories, maxImagesInDirectoryForTopLevelFirstPass, reverse);
return results;
}
public static List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles, int r)> GetFileHolderGroupCollection(Models.Configuration configuration, bool reverse, string searchPattern, List<string> topDirectories)
{
if (configuration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new ArgumentNullException(nameof(configuration.MaxImagesInDirectoryForTopLevelFirstPass));
List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles, int r)> results = new();
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)>? collection = GetGroupCollection(configuration.RootDirectory, searchPattern, topDirectories, configuration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse);
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in collection)
results.Add(new(g, sourceDirectory, (from l in sourceDirectoryFiles select new FileHolder(l)).ToArray(), r));
return results;
}
private static List<(int g, string sourceDirectory, List<(string sourceDirectoryFile, Models.A_Property? property)> collection, int r)> GetCollection(string rootDirectory, List<(int g, string sourceDirectory, string[] SourceDirectoryFiles, int r)> jsonCollection)
{
List<(int, string, List<(string, Models.A_Property?)>, int)> results = new();
int length = rootDirectory.Length;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = Environment.ProcessorCount };
_ = Parallel.For(0, jsonCollection.Count, parallelOptions, i => ParallelFor(jsonCollection, i, length, results));
return results;
}
private static List<PropertyHolder[]> Populate(Models.Configuration configuration, string aPropertySingletonDirectory, List<(int, string, FileHolder[], int)> fileHolderGroupCollection, List<(int, string, List<(string, Models.A_Property?)>, int)> collectionFromJson)
{
List<PropertyHolder[]> results = new();
if (configuration.PropertiesChangedForProperty is null)
throw new Exception($"{configuration.PropertiesChangedForProperty} is null");
int length;
string inferred;
string relativePath;
FileHolder keyFileHolder;
string keySourceDirectory;
List<PropertyHolder> propertyHolderCollection;
Dictionary<string, (string SourceDirectory, FileHolder FileHolder)> fileHolderKeyValuePairs = new();
length = configuration.RootDirectory.Length;
foreach ((int g, string sourceDirectory, FileHolder[] sourceDirectoryFileHolderCollection, int r) in fileHolderGroupCollection)
{
foreach (FileHolder sourceDirectoryFileHolder in sourceDirectoryFileHolderCollection)
{
relativePath = $"{XPath.GetRelativePath(sourceDirectoryFileHolder.FullName, length)}.json";
fileHolderKeyValuePairs.Add(relativePath, new(sourceDirectory, sourceDirectoryFileHolder));
}
}
length = aPropertySingletonDirectory.Length;
foreach ((int g, string _, List<(string, Models.A_Property?)> collection, int r) in collectionFromJson)
{
if (!collection.Any())
continue;
propertyHolderCollection = new();
foreach ((string sourceDirectoryFile, Models.A_Property? property) in collection)
{
relativePath = XPath.GetRelativePath(sourceDirectoryFile, length);
if (!fileHolderKeyValuePairs.ContainsKey(relativePath))
{
inferred = string.Concat(configuration.RootDirectory, relativePath);
keyFileHolder = new(inferred[..^5]);
if (keyFileHolder.Extension is ".json")
continue;
keySourceDirectory = string.Concat(keyFileHolder.DirectoryName);
propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileHolder, property, true, null, null, null));
}
else
{
keyFileHolder = fileHolderKeyValuePairs[relativePath].FileHolder;
keySourceDirectory = fileHolderKeyValuePairs[relativePath].SourceDirectory;
if (!fileHolderKeyValuePairs.Remove(relativePath))
throw new Exception();
if (keyFileHolder.Extension is ".json")
continue;
if (property?.Id is null || property?.Width is null || property?.Height is null)
propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileHolder, property, false, null, null, null));
else if (configuration.PropertiesChangedForProperty.Value || property.LastWriteTime != keyFileHolder.LastWriteTime || property.FileSize != keyFileHolder.Length)
propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileHolder, property, false, true, null, null));
else
propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileHolder, property, false, false, null, null));
}
}
if (propertyHolderCollection.Any())
results.Add(propertyHolderCollection.ToArray());
}
length = configuration.RootDirectory.Length;
foreach ((int g, string sourceDirectory, FileHolder[] sourceDirectoryFileHolderCollection, int r) in fileHolderGroupCollection)
{
propertyHolderCollection = new();
foreach (FileHolder sourceDirectoryFileHolder in sourceDirectoryFileHolderCollection)
{
relativePath = $"{XPath.GetRelativePath(sourceDirectoryFileHolder.FullName, length)}.json";
if (!fileHolderKeyValuePairs.ContainsKey(relativePath))
continue;
if (!fileHolderKeyValuePairs.Remove(relativePath))
throw new Exception();
if (sourceDirectoryFileHolder.Extension is ".json")
continue;
propertyHolderCollection.Add(new(g, sourceDirectory, relativePath, sourceDirectoryFileHolder.FullName, r, sourceDirectoryFileHolder, null, null, null, null, null));
}
if (propertyHolderCollection.Any())
results.Add(propertyHolderCollection.ToArray());
}
if (fileHolderKeyValuePairs.Any())
throw new Exception();
results = (from l in results orderby l[0].G, l[0].R select l).ToList();
return results;
}
private static void ParallelFor(List<(int, string, string[], int)> jsonCollection, int i, int length, List<(int, string, List<(string, Models.A_Property?)>, int)> results)
{
string key;
string json;
Models.A_Property? property;
(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) = jsonCollection[i];
List<(string, Models.A_Property?)> collection = new();
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
{
json = File.ReadAllText(sourceDirectoryFile);
key = XPath.GetRelativePath(sourceDirectoryFile, length);
property = JsonSerializer.Deserialize<Models.A_Property>(json);
collection.Add(new(sourceDirectoryFile, property));
}
lock (results)
results.Add(new(g, sourceDirectory, collection, r));
}
public static List<PropertyHolder[]> Get(Models.Configuration configuration, bool reverse, Model? model, PredictorModel? predictorModel, PropertyLogic propertyLogic)
{
List<PropertyHolder[]> results;
string searchPattern = "*";
List<Models.Container> results;
long ticks = DateTime.Now.Ticks;
List<string> topDirectories = new();
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> jsonCollection;
List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles, int r)> fileHolderGroupCollection;
string aPropertySingletonDirectory = IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
List<(int g, string sourceDirectory, List<(string sourceDirectoryFile, Models.A_Property? property)> collection, int r)> collectionFromJson;
jsonCollection = GetJsonGroupCollection(aPropertySingletonDirectory);
fileHolderGroupCollection = GetFileHolderGroupCollection(configuration, reverse, searchPattern, topDirectories);
collectionFromJson = GetCollection(aPropertySingletonDirectory, jsonCollection);
results = Populate(configuration, aPropertySingletonDirectory, fileHolderGroupCollection, collectionFromJson);
propertyLogic.ParallelWork(configuration, model, predictorModel, ticks, results, firstPass: false);
if (propertyLogic.ExceptionsDirectories.Any())
List<string> exceptionsDirectories = new();
results = Container.GetContainers(configuration, propertyLogic);
propertyLogic.ParallelWork(ticks, results, firstPass: false);
if (exceptionsDirectories.Any())
throw new Exception();
return results;
}
@ -413,15 +187,19 @@ public static class A_Property
return result;
}
public static TimeSpan GetThreeStandardDeviationHigh(int minimum, PropertyHolder[] propertyHolderCollection)
public static TimeSpan GetThreeStandardDeviationHigh(int minimum, Models.Container container)
{
TimeSpan result;
DateTime? minimumDateTime;
List<long> ticksCollection = new();
foreach (PropertyHolder propertyHolder in propertyHolderCollection)
foreach (Item item in container.Items)
{
if (propertyHolder.Property is null || propertyHolder.MinimumDateTime is null)
if (item.Property is null)
continue;
ticksCollection.Add(propertyHolder.MinimumDateTime.Value.Ticks);
minimumDateTime = GetMinimumDateTime(item.Property);
if (minimumDateTime is null)
continue;
ticksCollection.Add(minimumDateTime.Value.Ticks);
}
long threeStandardDeviationHigh;
long min;
@ -443,35 +221,42 @@ public static class A_Property
return result;
}
public static (int, List<DateTime>, List<PropertyHolder>) Get(PropertyHolder[] propertyHolderCollection, TimeSpan threeStandardDeviationHigh, int i)
public static (int, List<DateTime>, List<Item>) Get(Models.Container container, TimeSpan threeStandardDeviationHigh, int i)
{
List<PropertyHolder> results = new();
List<Item> results = new();
int j = i;
Item item;
long? ticks;
Item nextItem;
TimeSpan timeSpan;
PropertyHolder propertyHolder;
DateTime? minimumDateTime;
DateTime? nextMinimumDateTime;
List<DateTime> dateTimes = new();
PropertyHolder nextPropertyHolder;
for (; j < propertyHolderCollection.Length; j++)
for (; j < container.Items.Count; j++)
{
ticks = null;
propertyHolder = propertyHolderCollection[j];
if (propertyHolder.Property is null || propertyHolder.MinimumDateTime is null)
item = container.Items[j];
if (item.Property is null)
continue;
for (int k = j + 1; k < propertyHolderCollection.Length; k++)
minimumDateTime = GetMinimumDateTime(item.Property);
if (minimumDateTime is null)
continue;
for (int k = j + 1; k < container.Items.Count; k++)
{
nextPropertyHolder = propertyHolderCollection[k];
if (nextPropertyHolder.Property is not null && nextPropertyHolder.MinimumDateTime is not null)
{
ticks = nextPropertyHolder.MinimumDateTime.Value.Ticks;
break;
}
nextItem = container.Items[k];
if (nextItem.Property is null)
continue;
nextMinimumDateTime = GetMinimumDateTime(nextItem.Property);
if (nextMinimumDateTime is null)
continue;
ticks = nextMinimumDateTime.Value.Ticks;
break;
}
results.Add(propertyHolder);
dateTimes.Add(propertyHolder.MinimumDateTime.Value);
results.Add(item);
dateTimes.Add(minimumDateTime.Value);
if (ticks.HasValue)
{
timeSpan = new(ticks.Value - propertyHolder.MinimumDateTime.Value.Ticks);
timeSpan = new(ticks.Value - minimumDateTime.Value.Ticks);
if (timeSpan > threeStandardDeviationHigh)
break;
}
@ -479,14 +264,14 @@ public static class A_Property
return new(j, dateTimes, results);
}
public static bool Any(List<PropertyHolder[]> propertyHolderCollections)
public static bool Any(List<Models.Container> propertyHolderCollections)
{
bool result = false;
foreach (PropertyHolder[] propertyHolderCollection in propertyHolderCollections)
foreach (Models.Container container in propertyHolderCollections)
{
if (!propertyHolderCollection.Any())
if (!container.Items.Any())
continue;
if ((from l in propertyHolderCollection where l.Any() select true).Any())
if ((from l in container.Items where l.Any() select true).Any())
{
result = true;
break;

View File

@ -0,0 +1,267 @@
using System.Text.Json;
namespace View_by_Distance.Property.Models.Stateless;
public class Container
{
public static List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> GetGroupCollection(string rootDirectory, int maxImagesInDirectoryForTopLevelFirstPass, bool reverse, string searchPattern, List<string> topDirectories)
{
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> results = new();
string? parentDirectory;
string[] subDirectories;
string[] sourceDirectoryFiles;
List<string[]> fileCollections = new();
if (!topDirectories.Any())
topDirectories.AddRange(from l in Directory.GetDirectories(rootDirectory, "*", SearchOption.TopDirectoryOnly) select Path.GetFullPath(l));
for (int g = 1; g < 5; g++)
{
if (g == 4)
{
for (int i = fileCollections.Count - 1; i > -1; i--)
{
parentDirectory = Path.GetDirectoryName(fileCollections[i][0]);
if (string.IsNullOrEmpty(parentDirectory))
continue;
results.Add(new(g, parentDirectory, fileCollections[i], results.Count));
fileCollections.RemoveAt(i);
}
}
else if (g == 2)
{
fileCollections = (from l in fileCollections orderby l.Length descending select l).ToList();
for (int i = fileCollections.Count - 1; i > -1; i--)
{
if (fileCollections[i].Length > maxImagesInDirectoryForTopLevelFirstPass * g)
break;
parentDirectory = Path.GetDirectoryName(fileCollections[i][0]);
if (string.IsNullOrEmpty(parentDirectory))
continue;
results.Add(new(g, parentDirectory, fileCollections[i], results.Count));
fileCollections.RemoveAt(i);
}
}
else if (g == 3)
{
subDirectories = Directory.GetDirectories(rootDirectory, "*", SearchOption.AllDirectories);
if (reverse)
subDirectories = subDirectories.Reverse().ToArray();
foreach (string subDirectory in subDirectories)
{
sourceDirectoryFiles = Directory.GetFiles(subDirectory, "*", SearchOption.TopDirectoryOnly);
if (!topDirectories.Contains(subDirectory))
results.Add(new(g, subDirectory, sourceDirectoryFiles, results.Count));
}
}
else if (g == 1)
{
sourceDirectoryFiles = Directory.GetFiles(rootDirectory, searchPattern, SearchOption.TopDirectoryOnly);
if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass)
fileCollections.Add(sourceDirectoryFiles);
else
results.Add(new(g, rootDirectory, sourceDirectoryFiles, results.Count));
if (reverse)
topDirectories.Reverse();
subDirectories = topDirectories.ToArray();
foreach (string subDirectory in subDirectories)
{
sourceDirectoryFiles = Directory.GetFiles(subDirectory, searchPattern, SearchOption.TopDirectoryOnly);
if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass)
fileCollections.Add(sourceDirectoryFiles);
else
{
if (sourceDirectoryFiles.Any() || Directory.GetDirectories(subDirectory, "*", SearchOption.TopDirectoryOnly).Any())
results.Add(new(g, subDirectory, sourceDirectoryFiles, results.Count));
else if (searchPattern == "*")
{
sourceDirectoryFiles = Directory.GetFiles(subDirectory, searchPattern, SearchOption.TopDirectoryOnly);
foreach (string subFile in sourceDirectoryFiles)
File.Delete(subFile);
Directory.Delete(subDirectory);
}
}
}
fileCollections.Reverse();
}
else
throw new Exception();
}
return results;
}
public static List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> GetGroupCollection(string rootDirectory, string searchPattern, List<string> topDirectories)
{
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> results;
int maxImagesInDirectoryForTopLevelFirstPass = 50;
bool reverse = false;
results = GetGroupCollection(rootDirectory, maxImagesInDirectoryForTopLevelFirstPass, reverse, searchPattern, topDirectories);
return results;
}
private static List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> GetJsonGroupCollection(Models.Configuration configuration, PropertyLogic propertyLogic, string rootDirectory)
{
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> results;
if (configuration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new NullReferenceException(nameof(configuration.MaxImagesInDirectoryForTopLevelFirstPass));
string searchPattern = "*.json";
List<string> topDirectories = new();
results = GetGroupCollection(rootDirectory, configuration.MaxImagesInDirectoryForTopLevelFirstPass.Value, propertyLogic.Reverse, searchPattern, topDirectories);
return results;
}
private static List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles, int r)> GetFileHolderGroupCollection(Models.Configuration configuration, PropertyLogic propertyLogic, string searchPattern, List<string> topDirectories)
{
List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles, int r)> results = new();
if (configuration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new NullReferenceException(nameof(configuration.MaxImagesInDirectoryForTopLevelFirstPass));
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)>? collection = GetGroupCollection(configuration.RootDirectory, configuration.MaxImagesInDirectoryForTopLevelFirstPass.Value, propertyLogic.Reverse, searchPattern, topDirectories);
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in collection)
results.Add(new(g, sourceDirectory, (from l in sourceDirectoryFiles select new FileHolder(l)).ToArray(), r));
return results;
}
private static void ParallelFor(List<(int, string, string[], int)> jsonCollection, int i, int length, List<(int, string, List<(string, Models.A_Property?)>, int)> results)
{
string key;
string json;
Models.A_Property? property;
(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) = jsonCollection[i];
List<(string, Models.A_Property?)> collection = new();
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
{
json = File.ReadAllText(sourceDirectoryFile);
key = XPath.GetRelativePath(sourceDirectoryFile, length);
property = JsonSerializer.Deserialize<Models.A_Property>(json);
collection.Add(new(sourceDirectoryFile, property));
}
lock (results)
results.Add(new(g, sourceDirectory, collection, r));
}
private static List<(int g, string sourceDirectory, List<(string sourceDirectoryFile, Models.A_Property? property)> collection, int r)> GetCollection(string rootDirectory, List<(int g, string sourceDirectory, string[] SourceDirectoryFiles, int r)> jsonCollection)
{
List<(int, string, List<(string, Models.A_Property?)>, int)> results = new();
int length = rootDirectory.Length;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = Environment.ProcessorCount };
_ = Parallel.For(0, jsonCollection.Count, parallelOptions, i => ParallelFor(jsonCollection, i, length, results));
return results;
}
private static List<Models.Container> GetContainers(Models.Configuration configuration, string aPropertySingletonDirectory, List<(int, string, FileHolder[], int)> fileHolderGroupCollection, List<(int, string, List<(string, Models.A_Property?)>, int)> collectionFromJson)
{
List<Models.Container> results = new();
if (configuration.PropertiesChangedForProperty is null)
throw new Exception($"{configuration.PropertiesChangedForProperty} is null");
int length;
string key;
string inferred;
List<Item> items;
string relativePath;
FileHolder keyFileHolder;
Models.Container container;
bool isValidImageFormatExtension;
List<string> keySourceDirectories;
Dictionary<string, (string SourceDirectory, FileHolder FileHolder)> fileHolderKeyValuePairs = new();
length = configuration.RootDirectory.Length;
foreach ((int g, string sourceDirectory, FileHolder[] sourceDirectoryFileHolderCollection, int r) in fileHolderGroupCollection)
{
foreach (FileHolder sourceDirectoryFileHolder in sourceDirectoryFileHolderCollection)
{
relativePath = XPath.GetRelativePath(sourceDirectoryFileHolder.FullName, length);
key = string.Concat(relativePath, ".json");
fileHolderKeyValuePairs.Add(key, new(sourceDirectory, sourceDirectoryFileHolder));
}
}
length = aPropertySingletonDirectory.Length;
foreach ((int g, string _, List<(string, Models.A_Property?)> collection, int r) in collectionFromJson)
{
if (!collection.Any())
continue;
items = new();
keySourceDirectories = new();
foreach ((string sourceDirectoryFile, Models.A_Property? property) in collection)
{
key = XPath.GetRelativePath(sourceDirectoryFile, length);
relativePath = key[..^5];
if (!fileHolderKeyValuePairs.ContainsKey(key))
{
inferred = string.Concat(configuration.RootDirectory, relativePath);
keyFileHolder = new(inferred);
if (keyFileHolder.ExtensionLowered is ".json")
continue;
keySourceDirectories.Add(string.Concat(keyFileHolder.DirectoryName));
isValidImageFormatExtension = configuration.ValidImageFormatExtensions.Contains(keyFileHolder.ExtensionLowered);
items.Add(new(sourceDirectoryFile, relativePath, keyFileHolder, isValidImageFormatExtension, property, true, null));
}
else
{
keyFileHolder = fileHolderKeyValuePairs[key].FileHolder;
keySourceDirectories.Add(fileHolderKeyValuePairs[key].SourceDirectory);
if (!fileHolderKeyValuePairs.Remove(key))
throw new Exception();
if (keyFileHolder.ExtensionLowered is ".json")
continue;
isValidImageFormatExtension = configuration.ValidImageFormatExtensions.Contains(keyFileHolder.ExtensionLowered);
if (property?.Id is null || property?.Width is null || property?.Height is null)
items.Add(new(sourceDirectoryFile, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, null));
else if (configuration.PropertiesChangedForProperty.Value || property.LastWriteTime != keyFileHolder.LastWriteTime || property.FileSize != keyFileHolder.Length)
items.Add(new(sourceDirectoryFile, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, true));
else
items.Add(new(sourceDirectoryFile, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, false));
}
}
if (items.Any())
{
if (keySourceDirectories.Distinct().Count() != 1)
continue;
container = new(g, r, items, keySourceDirectories[0]);
results.Add(container);
}
}
length = configuration.RootDirectory.Length;
foreach ((int g, string sourceDirectory, FileHolder[] sourceDirectoryFileHolderCollection, int r) in fileHolderGroupCollection)
{
items = new();
foreach (FileHolder sourceDirectoryFileHolder in sourceDirectoryFileHolderCollection)
{
relativePath = XPath.GetRelativePath(sourceDirectoryFileHolder.FullName, length);
key = string.Concat(relativePath, ".json");
if (!fileHolderKeyValuePairs.ContainsKey(key))
continue;
if (!fileHolderKeyValuePairs.Remove(key))
throw new Exception();
if (sourceDirectoryFileHolder.ExtensionLowered is ".json")
continue;
isValidImageFormatExtension = configuration.ValidImageFormatExtensions.Contains(sourceDirectoryFileHolder.ExtensionLowered);
items.Add(new(relativePath, sourceDirectoryFileHolder.FullName, sourceDirectoryFileHolder, isValidImageFormatExtension, null, null, null));
}
if (items.Any())
{
container = new(g, r, items, sourceDirectory);
results.Add(container);
}
}
if (fileHolderKeyValuePairs.Any())
throw new Exception();
results = (from l in results orderby l.G, l.R select l).ToList();
return results;
}
public static List<Models.Container> GetContainers(Models.Configuration configuration, PropertyLogic propertyLogic)
{
List<Models.Container> results;
string searchPattern = "*";
long ticks = DateTime.Now.Ticks;
List<string> topDirectories = new();
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> jsonCollection;
List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles, int r)> fileHolderGroupCollection;
string aPropertySingletonDirectory = IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
List<(int g, string sourceDirectory, List<(string sourceDirectoryFile, Models.A_Property? property)> collection, int r)> collectionFromJson;
jsonCollection = GetJsonGroupCollection(configuration, propertyLogic, aPropertySingletonDirectory);
fileHolderGroupCollection = GetFileHolderGroupCollection(configuration, propertyLogic, searchPattern, topDirectories);
collectionFromJson = GetCollection(aPropertySingletonDirectory, jsonCollection);
results = GetContainers(configuration, aPropertySingletonDirectory, fileHolderGroupCollection, collectionFromJson);
return results;
}
}

View File

@ -92,7 +92,7 @@ internal class XPath
string? pathRoot = Path.GetPathRoot(directory);
string extension = Path.GetExtension(directory);
if (string.IsNullOrEmpty(pathRoot))
throw new ArgumentNullException(nameof(pathRoot));
throw new NullReferenceException(nameof(pathRoot));
if (Directory.Exists(directory))
results.Add(Path.GetFileName(directory));
else if ((string.IsNullOrEmpty(extension) || extension.Length > 3) && !File.Exists(directory))