This commit is contained in:
2022-08-22 09:10:19 -07:00
parent f72fcee1db
commit bc2174b17a
150 changed files with 4323 additions and 6259 deletions

View File

@ -1,84 +1,62 @@
using ShellProgressBar;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Methods;
using View_by_Distance.Property.Models.Stateless;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Property.Models;
/// <summary>
// A_Property
/// </summary>
public class A_Property : Shared.Models.Properties.IProperty, IProperty
public class A_Property
{
protected DateTime _CreationTime;
protected DateTime? _DateTime;
protected DateTime? _DateTimeDigitized;
protected DateTime? _DateTimeOriginal;
protected long _FileSize;
protected DateTime? _GPSDateStamp;
protected int? _Height;
protected int? _Id;
protected int[] _Indices;
protected DateTime _LastWriteTime;
protected string _Make;
protected string _Model;
protected string _Orientation;
protected int? _Width;
public DateTime CreationTime => _CreationTime;
public DateTime? DateTime => _DateTime;
public DateTime? DateTimeDigitized => _DateTimeDigitized;
public DateTime? DateTimeOriginal => _DateTimeOriginal;
public long FileSize => _FileSize;
public DateTime? GPSDateStamp => _GPSDateStamp;
public int? Height => _Height;
public int? Id => _Id;
public int[] Indices => _Indices;
public DateTime LastWriteTime => _LastWriteTime;
public string Make => _Make;
public string Model => _Model;
public string Orientation => _Orientation;
public int? Width => _Width;
protected readonly List<string> _ExceptionsDirectories;
protected readonly Dictionary<int, int[]> _KeyValuePairs;
protected readonly Dictionary<int, int[]> _IndicesFromNew;
[JsonConstructor]
public A_Property(DateTime creationTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeOriginal, long fileSize, DateTime? gpsDateStamp, int? height, int? id, int[] indices, DateTime lastWriteTime, string make, string model, string orientation, int? width)
public bool Reverse { get; }
public List<string> AngleBracketCollection { get; }
public List<string> ExceptionsDirectories => _ExceptionsDirectories;
private readonly Model? _Model;
private readonly Serilog.ILogger? _Log;
private readonly string _OutputExtension;
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 A_Property(int maxDegreeOfParallelism, Configuration configuration, string outputExtension, bool reverse, Model? model, PredictorModel? predictorModel, Dictionary<int, int[]> indicesFromNew, Dictionary<int, int[]> keyValuePairs)
{
_CreationTime = creationTime;
_DateTime = dateTime;
_DateTimeDigitized = dateTimeDigitized;
_DateTimeOriginal = dateTimeOriginal;
_FileSize = fileSize;
_GPSDateStamp = gpsDateStamp;
_Height = height;
_Id = id;
_Indices = indices;
_LastWriteTime = lastWriteTime;
_Make = make;
_Model = model;
_Orientation = orientation;
_Width = width;
Reverse = reverse;
_KeyValuePairs = keyValuePairs;
_Configuration = configuration;
_ExceptionsDirectories = new();
_IndicesFromNew = indicesFromNew;
_PredictorModel = predictorModel;
_OutputExtension = outputExtension;
_ASCIIEncoding = new ASCIIEncoding();
AngleBracketCollection = new List<string>();
_Log = Serilog.Log.ForContext<A_Property>();
_MaxDegreeOfParallelism = maxDegreeOfParallelism;
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
if (configuration.VerifyToSeason is null || !configuration.VerifyToSeason.Any())
throw new Exception();
_VerifyToSeason = configuration.VerifyToSeason.Select(l => Path.Combine(configuration.RootDirectory, l)).ToArray();
}
#nullable disable
public A_Property()
{
_CreationTime = System.DateTime.MinValue;
_DateTime = null;
_DateTimeDigitized = null;
_DateTimeOriginal = null;
_FileSize = long.MinValue;
_GPSDateStamp = null;
_Height = null;
_Id = null;
_Indices = Array.Empty<int>();
_LastWriteTime = System.DateTime.MinValue;
_Make = string.Empty;
_Model = string.Empty;
_Orientation = string.Empty;
_Width = null;
}
#nullable restore
public A_Property(int maxDegreeOfParallelism, Configuration configuration, string outputExtension, bool reverse, Model? model, PredictorModel? predictorModel) :
this(maxDegreeOfParallelism, configuration, outputExtension, reverse, model, predictorModel, new(), new())
{ }
public override string ToString()
{
@ -86,38 +64,658 @@ public class A_Property : Shared.Models.Properties.IProperty, IProperty
return result;
}
public List<DateTime> GetDateTimes() => Stateless.A_Property.GetDateTimes(_CreationTime, _LastWriteTime, _DateTime, _DateTimeDigitized, _DateTimeOriginal, _GPSDateStamp);
public (bool?, string[]) IsWrongYear(string filteredSourceDirectoryFile, DateTime? minimumDateTime)
private long LogDelta(long ticks, string? methodName)
{
string[] results = Array.Empty<string>();
bool? result = null;
string year;
string directoryName;
string[] directorySegments;
string? check = Path.GetFullPath(filteredSourceDirectoryFile);
string? pathRoot = Path.GetPathRoot(filteredSourceDirectoryFile);
if (string.IsNullOrEmpty(pathRoot))
throw new Exception();
if (minimumDateTime.HasValue)
year = minimumDateTime.Value.ToString("yyyy");
long result;
if (_Log is null)
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;
return result;
}
public static List<DateTime> GetMetadataDateTimesByPattern(string dateTimeFormat, string filteredSourceDirectoryFile)
{
List<DateTime> results = new();
try
{
DateTime checkDateTime;
DateTime kristy = new(1976, 3, 8);
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(filteredSourceDirectoryFile);
foreach (MetadataExtractor.Directory directory in directories)
{
foreach (MetadataExtractor.Tag tag in directory.Tags)
{
if (string.IsNullOrEmpty(tag.Description) || tag.Description.Length != dateTimeFormat.Length)
continue;
if (!DateTime.TryParseExact(tag.Description, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
continue;
if (checkDateTime < kristy)
continue;
results.Add(checkDateTime);
}
}
}
catch (Exception) { }
return results;
}
public static List<DateTime> GetMetadataDateTimesByPattern(string dateTimeFormat, IFileHolder filteredSourceDirectoryFileHolder)
{
List<DateTime> results = GetMetadataDateTimesByPattern(dateTimeFormat, filteredSourceDirectoryFileHolder.FullName);
return results;
}
#pragma warning disable CA1416
private Shared.Models.Property GetImageProperty(IFileHolder filteredSourceDirectoryFileHolder, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id, List<int> indices)
{
Shared.Models.Property result;
if (_Log is null)
throw new NullReferenceException(nameof(_Log));
long ticks;
byte[] bytes;
string value;
long fileLength;
int encodingHash;
int? width = null;
int? height = null;
string dateTimeFormat;
DateTime checkDateTime;
DateTime? dateTime = null;
PropertyItem? propertyItem;
string make = string.Empty;
string model = string.Empty;
DateTime? gpsDateStamp = null;
DateTime? dateTimeOriginal = null;
string orientation = string.Empty;
DateTime? dateTimeDigitized = null;
if (!isValidImageFormatExtension && isValidMetadataExtensions)
{
dateTimeFormat = "ddd MMM dd HH:mm:ss yyyy";
List<DateTime> dateTimes = GetMetadataDateTimesByPattern(dateTimeFormat, filteredSourceDirectoryFileHolder);
if (dateTimes.Any())
dateTimeOriginal = dateTimes.Min();
}
else if (!isIgnoreExtension && isValidImageFormatExtension)
{
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
{
using Image image = Image.FromFile(filteredSourceDirectoryFileHolder.FullName);
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;
int length = bitmapData.Stride * bitmap.Height;
bytes = new byte[length];
Marshal.Copy(intPtr, bytes, 0, length);
bitmap.UnlockBits(bitmapData);
if (id is null)
{
ticks = DateTime.Now.Ticks;
id = Shared.Models.Stateless.Methods.IProperty.GetDeterministicHashCode(bytes);
if (_MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Shared.Models.Stateless.Methods.IProperty.GetDeterministicHashCode));
}
if (_Configuration.WriteBitmapDataBytes)
{
FileInfo contentFileInfo = new(Path.Combine(angleBracket.Replace("<>", "()"), filteredSourceDirectoryFileHolder.Name));
File.WriteAllBytes(Path.ChangeExtension(contentFileInfo.FullName, string.Empty), bytes);
}
if (_IndicesFromNew.ContainsKey(id.Value) && _IndicesFromNew[id.Value].Any())
indices.AddRange(_IndicesFromNew[id.Value]);
else
{
ticks = DateTime.Now.Ticks;
string encoding = Encoding.Default.GetString(bytes);
if (_MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Encoding.Default.GetString));
encodingHash = Shared.Models.Stateless.Methods.IProperty.GetDeterministicHashCode(encoding);
if (_MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Shared.Models.Stateless.Methods.IProperty.GetDeterministicHashCode));
if (!_KeyValuePairs.ContainsKey(encodingHash))
indices.Add(encodingHash);
else
indices.AddRange(_KeyValuePairs[encodingHash]);
}
}
width = image.Width;
height = image.Height;
dateTimeFormat = Shared.Models.Stateless.Methods.IProperty.DateTimeFormat();
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTime))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTime);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTime = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeDigitized))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeDigitized);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTimeDigitized = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeOriginal))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeOriginal);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTimeOriginal = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.GPSDateStamp))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.GPSDateStamp);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
gpsDateStamp = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Make))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Make);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
make = value;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Model))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Model);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
model = value;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Orientation))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Orientation);
if (propertyItem?.Value is not null)
{
value = BitConverter.ToInt16(propertyItem.Value, 0).ToString();
orientation = value;
}
}
}
catch (Exception)
{
_Log.Info(string.Concat(new StackFrame().GetMethod()?.Name, " <", filteredSourceDirectoryFileHolder.Name, ">"));
}
}
else
dateTimeOriginal = null;
if (filteredSourceDirectoryFileHolder.Length is null)
fileLength = 0;
else
fileLength = filteredSourceDirectoryFileHolder.Length.Value;
result = new(filteredSourceDirectoryFileHolder.CreationTime, dateTime, dateTimeDigitized, dateTimeOriginal, fileLength, gpsDateStamp, height, id, indices.ToArray(), filteredSourceDirectoryFileHolder.LastWriteTime, make, model, orientation, width);
return result;
}
#pragma warning restore CA1416
private Shared.Models.Property GetPropertyOfPrivate(Item item, bool firstPass, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension, bool isValidMetadataExtensions)
{
Shared.Models.Property? result;
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;
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();
}
List<DateTime> dateTimes = (from l in filteredSourceDirectoryFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
if (!fileInfo.Exists)
{
if (fileInfo.Directory?.Parent is null)
throw new Exception();
string parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name);
if (File.Exists(parentCheck))
{
File.Move(parentCheck, fileInfo.FullName);
fileInfo.Refresh();
}
}
if (_Configuration.ForcePropertyLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
{
File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName);
fileInfo.Refresh();
}
if (_Configuration.ForcePropertyLastWriteTimeToCreationTime && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime)
{
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
fileInfo.Refresh();
}
if (_Configuration.PropertiesChangedForProperty)
result = null;
else if (!fileInfo.Exists)
result = null;
else if (!fileInfo.FullName.EndsWith(".json") && !fileInfo.FullName.EndsWith(".old"))
throw new ArgumentException("must be a *.json file");
else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
result = null;
else
{
List<DateTime> dateTimes = GetDateTimes();
year = dateTimes.Min().ToString("yyyy");
json = File.ReadAllText(fileInfo.FullName);
try
{
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
bool check = true;
Shared.Models.Property? property = JsonSerializer.Deserialize<Shared.Models.Property>(json);
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(item.ImageFileHolder, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices);
}
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(item.ImageFileHolder, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices);
}
if (!isIgnoreExtension && item.ValidImageFormatExtension && populateId && property is not null && property.LastWriteTime != item.ImageFileHolder.LastWriteTime)
{
check = false;
id = null;
indices.Clear();
property = GetImageProperty(item.ImageFileHolder, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices);
}
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(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!");
}
// if (filteredSourceDirectoryFileFileInfo.CreationTime != property?.CreationTime || filteredSourceDirectoryFileFileInfo.LastWriteTime != property?.LastWriteTime)
// {
// check = false;
// id = null;
// indices.Clear();
// property = GetImagePropertyB(filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
// }
if (json.Contains("WrongYear"))
{
id = property?.Id;
hasWrongYearProperty = true;
}
if (property is null)
throw new Exception();
if (!check)
result = null;
else
{
result = property;
filteredSourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), fileInfo.LastWriteTime));
}
}
catch (Exception)
{
result = null;
parseExceptions.Add(nameof(A_Property));
}
}
for (int i = 0; i < int.MaxValue; i++)
if (result is null)
{
check = Path.GetDirectoryName(check);
if (string.IsNullOrEmpty(check) || check == pathRoot)
break;
directoryName = Path.GetFileName(check);
directorySegments = directoryName.Split(' ');
(result, results) = Stateless.A_Property.IsWrongYear(directorySegments, year);
if (result.HasValue)
break;
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 && Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true))
{
if (!_Configuration.ForcePropertyLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime))
filteredSourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
else
{
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
fileInfo.Refresh();
filteredSourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), fileInfo.CreationTime));
}
}
}
return new(result, results);
else if (hasWrongYearProperty)
{
json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions);
if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true))
{
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
fileInfo.Refresh();
filteredSourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), fileInfo.CreationTime));
}
}
return result;
}
private bool AnyFilesMoved(string sourceDirectory, Item[] filteredItems)
{
bool result = false;
if (_Log is null)
throw new NullReferenceException(nameof(_Log));
int season;
string[] matches;
string deleteFile;
bool? isWrongYear;
string seasonName;
DateTime dateTime;
string destinationFile;
DateTime minimumDateTime;
string destinationDirectory;
string[] sourceDirectorySegments;
DateTime directoryMaximumOfMinimumDateTime = DateTime.MinValue;
foreach (Item filteredItem in filteredItems)
{
if (!filteredItem.ValidImageFormatExtension || filteredItem.Property is null || filteredItem.ImageFileHolder is null)
continue;
minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(filteredItem.Property);
if (minimumDateTime > directoryMaximumOfMinimumDateTime)
directoryMaximumOfMinimumDateTime = minimumDateTime;
if (minimumDateTime != filteredItem.ImageFileHolder.CreationTime)
{
(isWrongYear, matches) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(filteredItem.ImageFileHolder.FullName, minimumDateTime);
if (isWrongYear is null || !isWrongYear.Value)
dateTime = minimumDateTime;
else
{
if (!matches.Any())
continue;
if (!DateTime.TryParseExact(matches[0], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
continue;
}
try
{ File.SetCreationTime(filteredItem.ImageFileHolder.FullName, dateTime); }
catch (Exception)
{ }
}
if (!_VerifyToSeason.Contains(sourceDirectory))
continue;
if (!filteredItem.ImageFileHolder.FullName.Contains("zzz ") && !filteredItem.ImageFileHolder.FullName.Contains("Camera ") && filteredItem.Property.DateTimeOriginal.HasValue)
{
TimeSpan timeSpan = new(filteredItem.Property.DateTimeOriginal.Value.Ticks - filteredItem.Property.LastWriteTime.Ticks);
if (timeSpan.TotalHours > 6)
{
_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}>");
}
}
sourceDirectorySegments = Path.GetFileName(sourceDirectory).Split(' ');
(season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(minimumDateTime.DayOfYear);
if (sourceDirectorySegments[0] == "zzz")
destinationDirectory = Path.Combine(_Configuration.RootDirectory, $"zzz ={minimumDateTime:yyyy}.{season} {seasonName} {string.Join(' ', sourceDirectorySegments.Skip(3))}");
else if (sourceDirectorySegments.Length > 2)
destinationDirectory = Path.Combine(_Configuration.RootDirectory, $"={minimumDateTime:yyyy}.{season} {seasonName} {string.Join(' ', sourceDirectorySegments.Skip(2))}");
else
destinationDirectory = Path.Combine(_Configuration.RootDirectory, $"={minimumDateTime:yyyy}.{season} {seasonName}");
if (destinationDirectory == sourceDirectory)
continue;
lock (filteredItem)
filteredItem.SetMoved(true);
if (!result)
result = true;
if (!Directory.Exists(destinationDirectory))
_ = Directory.CreateDirectory(destinationDirectory);
destinationFile = Path.Combine(destinationDirectory, filteredItem.ImageFileHolder.Name);
if (File.Exists(destinationFile))
{
if (_OutputExtension is not ".jpg" and not ".jpeg")
throw new Exception();
if (destinationFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
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(filteredItem.ImageFileHolder.Name, ".jpg"));
}
if (File.Exists(destinationFile))
{
_Log.Information($"*** source <{filteredItem.ImageFileHolder.FullName}>");
_Log.Information($"*** destination <{destinationFile}>");
if (filteredItem.ImageFileHolder.Exists)
{
deleteFile = Path.ChangeExtension(filteredItem.ImageFileHolder.FullName, ".delete");
if (File.Exists(deleteFile))
File.Delete(deleteFile);
File.Move(filteredItem.ImageFileHolder.FullName, deleteFile);
}
}
else
{
File.Move(filteredItem.ImageFileHolder.FullName, destinationFile);
if (filteredItem.ImageFileHolder.Exists)
{
deleteFile = Path.ChangeExtension(filteredItem.ImageFileHolder.FullName, ".delete");
if (File.Exists(deleteFile))
File.Delete(deleteFile);
File.Move(filteredItem.ImageFileHolder.FullName, deleteFile);
}
}
}
if (directoryMaximumOfMinimumDateTime != DateTime.MinValue)
{
System.IO.DirectoryInfo directoryInfo = new(sourceDirectory);
if (directoryInfo.LastWriteTime != directoryMaximumOfMinimumDateTime)
Directory.SetLastWriteTime(sourceDirectory, directoryMaximumOfMinimumDateTime);
}
return result;
}
private void ParallelForWork(bool firstPass, string sourceDirectory, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item item)
{
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
Shared.Models.Property property;
List<string> parseExceptions = new();
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(item, firstPass, filteredSourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidMetadataExtensions);
lock (sourceDirectoryChanges)
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
lock (item)
item.Update(property);
}
}
private void ParallelWork(bool firstPass, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, int containersCount, Shared.Models.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 = $"{container.R: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, container.SourceDirectory, sourceDirectoryChanges, filteredSourceDirectoryFileTuples, filteredItems[i]);
if (i == 0 || sourceDirectoryChanges.Any())
progressBar.Tick();
lock (filteredSourceDirectoryFileTuples)
collection = (from l in filteredSourceDirectoryFileTuples where l.Item2 > dateTime select l).ToList();
lock (sourceDirectoryChanges)
sourceDirectoryChanges.AddRange(collection);
}
catch (Exception ex)
{
lock (exceptions)
exceptions.Add(ex);
}
});
}
private void SetAngleBracketCollection(string sourceDirectory)
{
AngleBracketCollection.Clear();
AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(_Configuration,
_Model,
_PredictorModel,
sourceDirectory,
nameof(A_Property),
string.Empty,
includeResizeGroup: false,
includeModel: false,
includePredictorModel: false,
contentDescription: string.Empty,
singletonDescription: "Properties for each image",
collectionDescription: string.Empty));
}
public void ParallelWork(long ticks, List<Shared.Models.Container> containers, bool firstPass)
{
if (_Log is null)
throw new NullReferenceException(nameof(_Log));
int totalSeconds;
bool? anyFilesMoved;
Item[] filteredItems;
List<Exception> exceptions = new();
int containersCount = containers.Count;
List<Tuple<string, DateTime>> sourceDirectoryChanges = new();
string propertyRoot = IResult.GetResultsGroupDirectory(_Configuration, nameof(A_Property));
foreach (Shared.Models.Container container in containers)
{
if (!container.Items.Any())
continue;
sourceDirectoryChanges.Clear();
if (firstPass)
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
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;
totalSeconds = (int)Math.Truncate(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
SetAngleBracketCollection(container.SourceDirectory);
ParallelWork(firstPass, exceptions, sourceDirectoryChanges, containersCount, container, filteredItems, totalSeconds);
foreach (Exception exception in exceptions)
_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(container.SourceDirectory);
if (!firstPass || exceptions.Count != 0)
anyFilesMoved = null;
else
anyFilesMoved = AnyFilesMoved(container.SourceDirectory, filteredItems);
if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any())
{
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key when ready to continue or close console");
if (System.Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
}
}
}
public Shared.Models.Property GetProperty(Item item, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<string> parseExceptions)
{
Shared.Models.Property result;
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
bool firstPass = false;
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(List<DirectoryInfo> groupCollection, bool saveToCollection)
{
List<(long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)> results = new();
int level;
string checkDirectory;
List<string> directories;
string propertyDirectory;
Shared.Models.Property? property;
string angleBracket = AngleBracketCollection[0];
foreach (DirectoryInfo group in groupCollection)
{
SetAngleBracketCollection(group.SourceDirectory);
if (string.IsNullOrEmpty(group.SourceDirectory))
throw new Exception();
if (!saveToCollection)
propertyDirectory = angleBracket.Replace("<>", "()");
else
{
(level, directories) = Shared.Models.Stateless.Methods.IPath.Get(_Configuration.RootDirectory, group.SourceDirectory);
checkDirectory = Shared.Models.Stateless.Methods.IPath.GetDirectory(angleBracket, level, "[()]");
propertyDirectory = Path.Combine(checkDirectory, string.Join(_Configuration.FileNameDirectorySeparator, directories));
}
if (!Directory.Exists(propertyDirectory))
_ = Directory.CreateDirectory(propertyDirectory);
for (int i = 0; i < group.SourceDirectoryFileHolderCollection.Length; i++)
{
property = group.PropertyCollection[i];
if (property?.Id is null)
continue;
results.Add(new(property.GetDateTimes().Min().Ticks, group.FilteredSourceDirectoryFiles[i], propertyDirectory, property.Id.Value));
}
}
return results.OrderBy(l => l.Ticks).ToArray();
}
public static List<Shared.Models.Container> Get(Configuration configuration, A_Property propertyLogic)
{
List<Shared.Models.Container> results;
long ticks = DateTime.Now.Ticks;
List<string> exceptionsDirectories = new();
results = Stateless.Container.GetContainers(configuration, propertyLogic);
propertyLogic.ParallelWork(ticks, results, firstPass: false);
if (exceptionsDirectories.Any())
throw new Exception();
return results;
}
}

View File

@ -1,3 +1,5 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
@ -6,6 +8,8 @@ namespace View_by_Distance.Property.Models.Binder;
public class Configuration
{
#nullable disable
[Display(Name = "Date Group"), Required] public string DateGroup { get; set; }
[Display(Name = "File Name Directory Separator"), Required] public string FileNameDirectorySeparator { get; set; }
[Display(Name = "Force Property Last Write Time to Creation Time"), Required] public bool? ForcePropertyLastWriteTimeToCreationTime { get; set; }
@ -21,23 +25,7 @@ public class Configuration
[Display(Name = "Verify to Season"), Required] public string[] VerifyToSeason { get; set; }
[Display(Name = "Write Bitmap Data Bytes"), Required] public bool? WriteBitmapDataBytes { get; set; }
public Configuration()
{
DateGroup = string.Empty;
FileNameDirectorySeparator = string.Empty;
ForcePropertyLastWriteTimeToCreationTime = null;
IgnoreExtensions = Array.Empty<string>();
MaxImagesInDirectoryForTopLevelFirstPass = null;
Pattern = string.Empty;
PopulatePropertyId = null;
PropertiesChangedForProperty = null;
PropertyContentCollectionFiles = Array.Empty<string>();
RootDirectory = string.Empty;
ValidImageFormatExtensions = Array.Empty<string>();
ValidMetadataExtensions = Array.Empty<string>();
VerifyToSeason = Array.Empty<string>();
WriteBitmapDataBytes = null;
}
#nullable restore
public override string ToString()
{
@ -45,4 +33,61 @@ public class Configuration
return result;
}
private static Models.Configuration Get(Configuration configuration)
{
Models.Configuration result;
if (configuration.ForcePropertyLastWriteTimeToCreationTime is null)
throw new NullReferenceException(nameof(configuration.ForcePropertyLastWriteTimeToCreationTime));
if (configuration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new NullReferenceException(nameof(configuration.MaxImagesInDirectoryForTopLevelFirstPass));
if (configuration.PopulatePropertyId is null)
throw new NullReferenceException(nameof(configuration.PopulatePropertyId));
if (configuration.PropertiesChangedForProperty is null)
throw new NullReferenceException(nameof(configuration.PropertiesChangedForProperty));
if (configuration.WriteBitmapDataBytes is null)
throw new NullReferenceException(nameof(configuration.WriteBitmapDataBytes));
if (configuration.IgnoreExtensions is null)
configuration.IgnoreExtensions = Array.Empty<string>();
if (configuration.PropertyContentCollectionFiles is null)
configuration.PropertyContentCollectionFiles = Array.Empty<string>();
if (configuration.ValidImageFormatExtensions is null)
configuration.ValidImageFormatExtensions = Array.Empty<string>();
if (configuration.ValidMetadataExtensions is null)
configuration.ValidMetadataExtensions = Array.Empty<string>();
if (configuration.VerifyToSeason is null)
configuration.VerifyToSeason = Array.Empty<string>();
result = new(configuration.DateGroup,
configuration.FileNameDirectorySeparator,
configuration.ForcePropertyLastWriteTimeToCreationTime.Value,
configuration.IgnoreExtensions,
configuration.MaxImagesInDirectoryForTopLevelFirstPass.Value,
configuration.Pattern,
configuration.PopulatePropertyId.Value,
configuration.PropertiesChangedForProperty.Value,
configuration.PropertyContentCollectionFiles,
configuration.RootDirectory,
configuration.ValidImageFormatExtensions,
configuration.ValidMetadataExtensions,
configuration.VerifyToSeason,
configuration.WriteBitmapDataBytes.Value);
return result;
}
public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot)
{
Models.Configuration result;
Configuration configuration;
if (isEnvironment is null)
configuration = configurationRoot.Get<Configuration>();
else
{
string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment);
string section = string.Concat(environmentName, ":", nameof(Configuration));
IConfigurationSection configurationSection = configurationRoot.GetSection(section);
configuration = configurationSection.Get<Configuration>();
}
result = Get(configuration);
return result;
}
}

View File

@ -1,49 +0,0 @@
using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Property.Models;
public class Closest
{
public const int MaximumPer = 50;
public const float MaximumMinimum = 0.50f;
public const bool SkipIsWrongYear = true;
public const float MinimumMinimum = 0.05f;
protected readonly double? _Average;
protected readonly int? _NormalizedPixelPercentage;
protected readonly bool? _IsWrongYear;
protected readonly double? _Minimum;
protected readonly DateTime _MinimumDateTime;
protected readonly PersonBirthday? _PersonBirthday;
public double? Average => _Average;
public int? NormalizedPixelPercentage => _NormalizedPixelPercentage;
public bool? IsWrongYear => _IsWrongYear;
public double? Minimum => _Minimum;
public DateTime MinimumDateTime => _MinimumDateTime;
public PersonBirthday? PersonBirthday => _PersonBirthday;
[JsonConstructor]
public Closest(double? average, int? normalizedPixelPercentage, bool? isWrongYear, double? minimum, DateTime minimumDateTime, PersonBirthday? personBirthday)
{
_Average = average;
_NormalizedPixelPercentage = normalizedPixelPercentage;
_IsWrongYear = isWrongYear;
_Minimum = minimum;
_MinimumDateTime = minimumDateTime;
_PersonBirthday = personBirthday;
}
public Closest(int? normalizedPixelPercentage, DateTime minimumDateTime, bool? isWrongYear) :
this(null, normalizedPixelPercentage, isWrongYear, null, minimumDateTime, null)
{
}
public Closest(int? normalizedPixelPercentage, DateTime minimumDateTime, bool? isWrongYear, PersonBirthday? personBirthday, List<double> faceDistances) :
this(faceDistances.Average(), normalizedPixelPercentage, isWrongYear, faceDistances.Min(), minimumDateTime, personBirthday)
{
}
public static Closest[] Get(List<Closest> collection) => (from l in collection orderby l.Minimum < MinimumMinimum, l.Average select l).ToArray();
}

View File

@ -6,52 +6,40 @@ namespace View_by_Distance.Property.Models;
public class Configuration
{
protected readonly string _DateGroup;
protected readonly string _FileNameDirectorySeparator;
protected readonly bool? _ForcePropertyLastWriteTimeToCreationTime;
protected readonly string[] _IgnoreExtensions;
protected readonly int? _MaxImagesInDirectoryForTopLevelFirstPass;
protected readonly string _Pattern;
protected readonly bool? _PopulatePropertyId;
protected readonly bool? _PropertiesChangedForProperty;
protected readonly string[] _PropertyContentCollectionFiles;
protected string _RootDirectory;
protected readonly string[] _ValidImageFormatExtensions;
protected readonly string[] _ValidMetadataExtensions;
protected readonly string[] _VerifyToSeason;
protected readonly bool? _WriteBitmapDataBytes;
public string DateGroup => _DateGroup;
public string FileNameDirectorySeparator => _FileNameDirectorySeparator;
public bool? ForcePropertyLastWriteTimeToCreationTime => _ForcePropertyLastWriteTimeToCreationTime;
public string[] IgnoreExtensions => _IgnoreExtensions;
public int? MaxImagesInDirectoryForTopLevelFirstPass => _MaxImagesInDirectoryForTopLevelFirstPass;
public string Pattern => _Pattern;
public bool? PopulatePropertyId => _PopulatePropertyId;
public bool? PropertiesChangedForProperty => _PropertiesChangedForProperty;
public string[] PropertyContentCollectionFiles => _PropertyContentCollectionFiles;
public string RootDirectory => _RootDirectory;
public string[] ValidImageFormatExtensions => _ValidImageFormatExtensions;
public string[] ValidMetadataExtensions => _ValidMetadataExtensions;
public string[] VerifyToSeason => _VerifyToSeason;
public bool? WriteBitmapDataBytes => _WriteBitmapDataBytes;
public string DateGroup { init; get; }
public string FileNameDirectorySeparator { init; get; }
public bool ForcePropertyLastWriteTimeToCreationTime { init; get; }
public string[] IgnoreExtensions { init; get; }
public int MaxImagesInDirectoryForTopLevelFirstPass { init; get; }
public string Pattern { init; get; }
public bool PopulatePropertyId { init; get; }
public bool PropertiesChangedForProperty { init; get; }
public string[] PropertyContentCollectionFiles { init; get; }
public string[] ValidImageFormatExtensions { init; get; }
public string[] ValidMetadataExtensions { init; get; }
public string[] VerifyToSeason { init; get; }
public bool WriteBitmapDataBytes { init; get; }
[JsonConstructor]
public Configuration(string dateGroup, string fileNameDirectorySeparator, bool? forcePropertyLastWriteTimeToCreationTime, string[] ignoreExtensions, int? maxImagesInDirectoryForTopLevelFirstPass, string pattern, bool? populatePropertyId, bool? propertiesChangedForProperty, string[] propertyContentCollectionFiles, string rootDirectory, string[] validImageFormatExtensions, string[] validMetadataExtensions, string[] verifyToSeason, bool? writeBitmapDataBytes)
public Configuration(string dateGroup, string fileNameDirectorySeparator, bool forcePropertyLastWriteTimeToCreationTime, string[] ignoreExtensions, int maxImagesInDirectoryForTopLevelFirstPass, string pattern, bool populatePropertyId, bool propertiesChangedForProperty, string[] propertyContentCollectionFiles, string rootDirectory, string[] validImageFormatExtensions, string[] validMetadataExtensions, string[] verifyToSeason, bool writeBitmapDataBytes)
{
_DateGroup = dateGroup;
_FileNameDirectorySeparator = fileNameDirectorySeparator;
_ForcePropertyLastWriteTimeToCreationTime = forcePropertyLastWriteTimeToCreationTime;
_IgnoreExtensions = ignoreExtensions;
_MaxImagesInDirectoryForTopLevelFirstPass = maxImagesInDirectoryForTopLevelFirstPass;
_Pattern = pattern;
_PopulatePropertyId = populatePropertyId;
_PropertiesChangedForProperty = propertiesChangedForProperty;
_PropertyContentCollectionFiles = propertyContentCollectionFiles;
DateGroup = dateGroup;
FileNameDirectorySeparator = fileNameDirectorySeparator;
ForcePropertyLastWriteTimeToCreationTime = forcePropertyLastWriteTimeToCreationTime;
IgnoreExtensions = ignoreExtensions;
MaxImagesInDirectoryForTopLevelFirstPass = maxImagesInDirectoryForTopLevelFirstPass;
Pattern = pattern;
PopulatePropertyId = populatePropertyId;
PropertiesChangedForProperty = propertiesChangedForProperty;
PropertyContentCollectionFiles = propertyContentCollectionFiles;
_RootDirectory = rootDirectory;
_ValidImageFormatExtensions = validImageFormatExtensions;
_ValidMetadataExtensions = validMetadataExtensions;
_VerifyToSeason = verifyToSeason;
_WriteBitmapDataBytes = writeBitmapDataBytes;
ValidImageFormatExtensions = validImageFormatExtensions;
ValidMetadataExtensions = validMetadataExtensions;
VerifyToSeason = verifyToSeason;
WriteBitmapDataBytes = writeBitmapDataBytes;
}
public override string ToString()
@ -62,18 +50,14 @@ public class Configuration
public void Update() => _RootDirectory = Path.GetFullPath(_RootDirectory);
public static void Verify(Configuration? propertyConfiguration)
public void ChangeRootDirectory(string rootDirectory) => _RootDirectory = rootDirectory;
public static void Verify(Configuration propertyConfiguration)
{
if (propertyConfiguration is null)
throw new NullReferenceException(nameof(propertyConfiguration));
if (propertyConfiguration.ForcePropertyLastWriteTimeToCreationTime is null)
throw new NullReferenceException(nameof(propertyConfiguration.ForcePropertyLastWriteTimeToCreationTime));
if (propertyConfiguration.IgnoreExtensions is null || !propertyConfiguration.IgnoreExtensions.Any())
throw new NullReferenceException(nameof(propertyConfiguration.IgnoreExtensions));
if (propertyConfiguration.PopulatePropertyId is null)
throw new NullReferenceException(nameof(propertyConfiguration.PopulatePropertyId));
if (propertyConfiguration.PropertiesChangedForProperty is null)
throw new NullReferenceException(nameof(propertyConfiguration.PropertiesChangedForProperty));
if (propertyConfiguration.PropertyContentCollectionFiles is null)
throw new NullReferenceException(nameof(propertyConfiguration.PropertyContentCollectionFiles));
if (propertyConfiguration.ValidImageFormatExtensions is null || !propertyConfiguration.ValidImageFormatExtensions.Any())
@ -82,8 +66,6 @@ public class Configuration
throw new NullReferenceException(nameof(propertyConfiguration.ValidMetadataExtensions));
if (propertyConfiguration.VerifyToSeason is null || !propertyConfiguration.VerifyToSeason.Any())
throw new NullReferenceException(nameof(propertyConfiguration.VerifyToSeason));
if (propertyConfiguration.WriteBitmapDataBytes is null)
throw new NullReferenceException(nameof(propertyConfiguration.WriteBitmapDataBytes));
if (Path.GetPathRoot(propertyConfiguration.RootDirectory) == propertyConfiguration.RootDirectory)
throw new NullReferenceException(nameof(propertyConfiguration.RootDirectory));
if (propertyConfiguration is null)
@ -98,6 +80,4 @@ public class Configuration
throw new NullReferenceException(nameof(propertyConfiguration.RootDirectory));
}
public void ChangeRootDirectory(string rootDirectory) => _RootDirectory = rootDirectory;
}

View File

@ -1,34 +0,0 @@
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

@ -3,24 +3,24 @@ namespace View_by_Distance.Property.Models;
public class DirectoryInfo
{
protected readonly FileHolder[] _SourceDirectoryFileHolderCollection;
protected readonly Shared.Models.FileHolder[] _SourceDirectoryFileHolderCollection;
protected readonly string[] _FilteredSourceDirectoryFiles;
protected readonly int _G;
protected readonly bool[] _Moved;
protected readonly bool?[] _Changed;
protected readonly A_Property?[] _PropertyCollection;
protected readonly Shared.Models.Property?[] _PropertyCollection;
protected readonly FileInfo?[] _PropertyFileHolderCollection;
protected readonly int _R;
protected readonly string _SourceDirectory;
protected readonly bool[] _ValidImageFormatExtensionCollection;
protected readonly bool[] _WrongYear;
public FileHolder[] SourceDirectoryFileHolderCollection => _SourceDirectoryFileHolderCollection;
public Shared.Models.FileHolder[] SourceDirectoryFileHolderCollection => _SourceDirectoryFileHolderCollection;
[Obsolete($"Use {nameof(SourceDirectoryFileHolderCollection)}")]
public string[] FilteredSourceDirectoryFiles => _FilteredSourceDirectoryFiles;
public int G => _G;
public bool[] Moved => _Moved;
public bool?[] Changed => _Changed;
public A_Property?[] PropertyCollection => _PropertyCollection;
public Shared.Models.Property?[] PropertyCollection => _PropertyCollection;
public FileInfo?[] PropertyFileHolderCollection => _PropertyFileHolderCollection;
public int R => _R;
public string SourceDirectory => _SourceDirectory;
@ -37,10 +37,11 @@ public class DirectoryInfo
_Moved = Enumerable.Repeat(false, length).ToArray();
_WrongYear = Enumerable.Repeat(false, length).ToArray();
_FilteredSourceDirectoryFiles = filteredSourceDirectoryFiles;
_PropertyCollection = Enumerable.Repeat<A_Property?>(null, length).ToArray();
_ValidImageFormatExtensionCollection = Enumerable.Repeat(false, length).ToArray();
_PropertyFileHolderCollection = Enumerable.Repeat<FileInfo?>(null, length).ToArray();
_SourceDirectoryFileHolderCollection = (from l in filteredSourceDirectoryFiles select new FileHolder(l)).ToArray();
_PropertyCollection = Enumerable.Repeat<Shared.Models.Property?>(null, length).ToArray();
_SourceDirectoryFileHolderCollection = (from l in filteredSourceDirectoryFiles select new Shared.Models.FileHolder(l)).ToArray();
}
}

View File

@ -1,70 +0,0 @@
namespace View_by_Distance.Property.Models;
public class FileHolder
{
protected readonly DateTime _CreationTime;
protected readonly string? _DirectoryName;
protected readonly bool _Exists;
protected readonly string _ExtensionLowered;
protected readonly string _FullName;
protected readonly DateTime _LastWriteTime;
protected readonly long? _Length;
protected readonly string _Name;
protected readonly string _NameWithoutExtension;
public DateTime CreationTime => _CreationTime;
public string? DirectoryName => _DirectoryName;
public bool Exists => _Exists;
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 extensionLowered, string fullName, DateTime lastWriteTime, long? length, string name, string nameWithoutExtension)
{
_CreationTime = creationTime;
_DirectoryName = directoryName;
_Exists = exists;
_ExtensionLowered = extensionLowered;
_FullName = fullName;
_LastWriteTime = lastWriteTime;
_Length = length;
_Name = name;
_NameWithoutExtension = nameWithoutExtension;
}
public FileHolder(string fileName)
{
FileInfo fileInfo = new(fileName);
_CreationTime = fileInfo.CreationTime;
_CreationTime = fileInfo.CreationTime;
_DirectoryName = fileInfo.DirectoryName;
_Exists = fileInfo.Exists;
_ExtensionLowered = fileInfo.Extension.ToLower();
_FullName = fileInfo.FullName;
_LastWriteTime = fileInfo.LastWriteTime;
if (fileInfo.Exists)
_Length = fileInfo.Length;
_Name = fileInfo.Name;
_NameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);
}
public FileHolder(FileInfo fileInfo)
{
_CreationTime = fileInfo.CreationTime;
_CreationTime = fileInfo.CreationTime;
_DirectoryName = fileInfo.DirectoryName;
_Exists = fileInfo.Exists;
_ExtensionLowered = fileInfo.Extension.ToLower();
_FullName = fileInfo.FullName;
_LastWriteTime = fileInfo.LastWriteTime;
if (fileInfo.Exists)
_Length = fileInfo.Length;
_Name = fileInfo.Name;
_NameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);
}
public static FileHolder Refresh(FileHolder fileHolder) => new(fileHolder.FullName);
}

View File

@ -1,318 +0,0 @@
using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties;
namespace View_by_Distance.Property.Models;
public class Item
{
protected readonly bool? _Abandoned;
protected readonly bool? _Changed;
protected List<Closest> _Closest;
protected List<IFace> _Faces;
protected readonly FileHolder? _ImageFileHolder;
protected bool? _Moved;
protected List<Named> _Named;
protected readonly bool? _NoJson;
protected A_Property? _Property;
protected readonly string _RelativePath;
protected FileHolder? _ResizedFileHolder;
protected readonly string _SourceDirectoryFile;
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 bool? Moved => _Moved;
public bool? NoJson => _NoJson;
public List<Named> Named => _Named;
public A_Property? Property => _Property;
public string RelativePath => _RelativePath;
public FileHolder? ResizedFileHolder => _ResizedFileHolder;
public string SourceDirectoryFile => _SourceDirectoryFile;
public bool ValidImageFormatExtension => _ValidImageFormatExtension;
[JsonConstructor]
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)
{
_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;
_Property = property;
_Abandoned = abandoned;
_NoJson = abandoned is null;
_RelativePath = relativePath;
_ImageFileHolder = imageFileInfo;
_SourceDirectoryFile = sourceDirectoryFile;
_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!");
}
internal void SetMoved(bool moved) => _Moved = moved;
public static string GetWrongYearFlag(bool? isWrongYear) => isWrongYear is null ? "#" : isWrongYear.Value ? "~" : "=";
public void SetResizedFileHolder(FileHolder fileHolder) => _ResizedFileHolder = fileHolder;
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;
public (bool?, string[]) IsWrongYear()
{
(bool?, string[]) result;
if (_Property is null || _ImageFileHolder is null)
throw new NullReferenceException();
DateTime? minimumDateTime = Stateless.A_Property.GetMinimumDateTime(_Property);
result = _Property.IsWrongYear(_ImageFileHolder.FullName, minimumDateTime);
return result;
}
public static void AddToNamed(PropertyLogic propertyLogic, List<Item> items)
{
bool? isWrongYear;
DateTime minimumDateTime;
PersonBirthday? personBirthday;
double deterministicHashCodeKey;
List<string> personKeys = new();
foreach (Item item in items)
{
if (item.ImageFileHolder is null)
continue;
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
foreach (IFace face in item.Faces)
{
personKeys.Clear();
if (face.LocationIndex is null)
continue;
deterministicHashCodeKey = Models.Named.GetDeterministicHashCodeKey(item, face);
if (!propertyLogic.NamedDeterministicHashCodeKeyValuePairs.ContainsKey(deterministicHashCodeKey))
continue;
minimumDateTime = Stateless.A_Property.GetMinimumDateTime(item.Property);
personKeys.AddRange(propertyLogic.NamedDeterministicHashCodeKeyValuePairs[deterministicHashCodeKey]);
(isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime);
for (int i = 0; i < personKeys.Count; i++)
{
personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKeys[i]);
if (personBirthday is null)
continue;
item.Named.Add(new(isWrongYear, minimumDateTime, face.Location.NormalizedPixelPercentage, personBirthday));
}
}
if (!personKeys.Any())
{
if (!propertyLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs.ContainsKey(item.Property.Id.Value))
continue;
minimumDateTime = Stateless.A_Property.GetMinimumDateTime(item.Property);
personKeys.AddRange(propertyLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs[item.Property.Id.Value]);
(isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime);
for (int i = 0; i < personKeys.Count; i++)
{
personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKeys[i]);
if (personBirthday is null)
continue;
item.Named.Add(new(isWrongYear, minimumDateTime, personBirthday));
}
}
}
}
public static List<(Item, (string, IFace?, (string, string, string, string))[])> GetCollection(PropertyLogic propertyLogic, List<Item> items, string dFacesContentDirectory)
{
List<(Item, (string, IFace?, (string, string, string, string))[])> results = new();
Item item;
string[] keys;
string directory;
string personKey;
bool? isWrongYear;
const int zero = 0;
TimeSpan? timeSpan;
string copyFileName;
string copyDirectory;
string? relativePath;
string isWrongYearFlag;
string shortcutFileName;
string subDirectoryName;
List<int> indices = new();
DateTime? minimumDateTime;
List<IFace> faceCollection;
PersonBirthday? personBirthday;
List<(string, IFace?, (string, string, string, string))> collection;
for (int i = 0; i < items.Count; i++)
{
indices.Clear();
copyFileName = string.Empty;
copyDirectory = string.Empty;
item = items[i];
if (item.ImageFileHolder is null)
continue;
relativePath = Path.GetDirectoryName($"C:{item.RelativePath}");
if (string.IsNullOrEmpty(relativePath) || relativePath.Length < 3)
continue;
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
collection = new();
if (!propertyLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs.ContainsKey(item.Property.Id.Value))
{
faceCollection = new();
personKey = string.Empty;
directory = Path.Combine(dFacesContentDirectory, $"Unnamed{relativePath[2..]}");
}
else
{
faceCollection = item.Faces;
keys = propertyLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs[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}{minimumDateTime.Value:yyyy}";
if (!faceCollection.Any())
{
personKey = string.Empty;
directory = Path.Combine(dFacesContentDirectory, $"None{relativePath[2..]}", subDirectoryName);
}
else if (keys.Length != 1)
{
personKey = string.Empty;
directory = Path.Combine(dFacesContentDirectory, $"Not Supported{relativePath[2..]}", subDirectoryName);
}
else if (faceCollection.Count != 1)
{
personKey = string.Empty;
directory = Path.Combine(dFacesContentDirectory, $"Many{relativePath[2..]}", subDirectoryName);
}
else
{
indices.Add(zero);
personKey = keys[zero];
personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKey);
if (personBirthday is null)
continue;
timeSpan = Shared.Models.Stateless.Methods.IPersonBirthday.GetTimeSpan(minimumDateTime.Value, isWrongYear, personBirthday);
if (timeSpan.HasValue)
{
if (timeSpan.Value.Ticks < 0)
subDirectoryName = "!---";
else
subDirectoryName = $"^{Math.Floor(timeSpan.Value.TotalDays / 365):000}";
}
directory = Path.Combine(dFacesContentDirectory, "Shortcuts", personKey, subDirectoryName);
if (faceCollection[zero].Populated)
copyDirectory = Path.Combine(dFacesContentDirectory, "Images", personKey, subDirectoryName);
else
copyDirectory = Path.Combine(dFacesContentDirectory, "ImagesBut", personKey, subDirectoryName);
copyFileName = Path.Combine(copyDirectory, $"{item.Property.Id.Value}{item.ResizedFileHolder.ExtensionLowered}");
}
}
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
{
foreach (int index in indices)
collection.Add(new(personKey, faceCollection[index], (directory, copyDirectory, copyFileName, shortcutFileName)));
}
results.Add(new(item, collection.ToArray()));
}
return results;
}
public static string GetKey(DateTime minimumDateTime, bool? isWrongYear, PersonBirthday personBirthday)
{
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
{
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 (!container.SourceDirectory.StartsWith(argZero))
continue;
foreach (Item item in container.Items)
{
if (item.ImageFileHolder is null || item.Property is null || !item.Named.Any())
continue;
foreach (Named named in item.Named)
{
if (named.NormalizedPixelPercentage is null && (item.Named.Count != 1 || item.Faces.Count != 1))
continue;
foreach (IFace face in item.Faces)
{
if (!face.Populated)
continue;
if (named.PersonBirthday is null)
continue;
if (named.NormalizedPixelPercentage.HasValue && named.NormalizedPixelPercentage.Value != face.Location?.NormalizedPixelPercentage)
continue;
key = GetKey(named.MinimumDateTime, named.IsWrongYear, named.PersonBirthday);
if (!results.ContainsKey(key))
results.Add(key, new());
results[key].Add(new(named.MinimumDateTime, named.IsWrongYear, named.PersonBirthday, face));
if (named.NormalizedPixelPercentage is null)
break;
}
}
}
}
return results;
}
}

View File

@ -1,142 +0,0 @@
using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties;
namespace View_by_Distance.Property.Models;
public class Named
{
protected readonly bool? _IsWrongYear;
protected readonly DateTime _MinimumDateTime;
protected readonly int? _NormalizedPixelPercentage;
protected readonly PersonBirthday? _PersonBirthday;
public bool? IsWrongYear => _IsWrongYear;
public DateTime MinimumDateTime => _MinimumDateTime;
public int? NormalizedPixelPercentage => _NormalizedPixelPercentage;
public PersonBirthday? PersonBirthday => _PersonBirthday;
[JsonConstructor]
public Named(bool? isWrongYear, DateTime minimumDateTime, int? normalizedPixelPercentage, PersonBirthday? personBirthday)
{
_IsWrongYear = isWrongYear;
_MinimumDateTime = minimumDateTime;
_NormalizedPixelPercentage = normalizedPixelPercentage;
_PersonBirthday = personBirthday;
}
public Named(bool? isWrongYear, DateTime minimumDateTime, PersonBirthday? personBirthday) :
this(isWrongYear, minimumDateTime, null, personBirthday)
{ }
private static double GetDeterministicHashCodeFileName(int id, int normalizedPixelPercentage)
=> double.Parse($"{id}.{normalizedPixelPercentage}");
public static double GetDeterministicHashCodeKey(Item item, Closest closest)
{
double result;
if (item.Property?.Id is null || item.ImageFileHolder is null || closest.NormalizedPixelPercentage is null)
throw new NullReferenceException();
result = GetDeterministicHashCodeFileName(item.Property.Id.Value, closest.NormalizedPixelPercentage.Value);
return result;
}
public static double GetDeterministicHashCodeKey(Item item, IFace face)
{
double result;
if (item.Property?.Id is null || item.ImageFileHolder is null || face.Location?.NormalizedPixelPercentage is null)
throw new NullReferenceException();
result = GetDeterministicHashCodeFileName(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value);
return result;
}
public static double? GetReversedDeterministicHashCode(string fileName)
{
double? result;
if (fileName.Length < 2 || fileName[1..].Contains('-'))
result = null;
else
{
string[] segments = fileName.Split('.');
if (segments.Length < 2)
throw new Exception();
string id = segments[0];
string normalizedPixelPercentage = segments[1];
if (!double.TryParse(string.Concat(id, '.', normalizedPixelPercentage), out double resultValue))
result = null;
else
result = resultValue;
}
return result;
}
public static (string?, double?) GetReversedDeterministicHashCode(Dictionary<int, List<IFace>> keyValuePairs, string file)
{
double? result;
string? check;
string fileName = Path.GetFileName(file);
if (!fileName.Contains('-'))
{
check = null;
result = null;
}
else
{
string id;
int? normalizedPixelPercentage;
if (!keyValuePairs.Any())
{
check = null;
id = string.Empty;
normalizedPixelPercentage = null;
}
else
{
string[] segments = fileName.Split(' ');
if (segments.Length < 3)
throw new Exception();
id = segments[2].Split('.')[0];
string locationIdex = segments[0];
if (!int.TryParse(id, out int idValue) || !int.TryParse(locationIdex, out int locationIndexValue) || !keyValuePairs.ContainsKey(idValue))
{
check = null;
id = string.Empty;
normalizedPixelPercentage = null;
}
else
{
List<IFace> faces = keyValuePairs[idValue];
if (faces.Count <= locationIndexValue)
{
check = null;
id = string.Empty;
normalizedPixelPercentage = null;
}
else
{
IFace face = faces[locationIndexValue];
if (face.Location?.NormalizedPixelPercentage is null)
{
check = null;
id = string.Empty;
normalizedPixelPercentage = null;
}
else
{
string extensionLowered = Path.GetExtension(file).ToLower();
normalizedPixelPercentage = face.Location.NormalizedPixelPercentage.Value;
double deterministicHashCodeKey = GetDeterministicHashCodeFileName(idValue, normalizedPixelPercentage.Value);
check = Path.Combine(string.Concat(Path.GetDirectoryName(file)), $"{deterministicHashCodeKey}{extensionLowered}");
}
}
}
}
if (normalizedPixelPercentage is null || !double.TryParse(string.Concat(id, '.', normalizedPixelPercentage.Value), out double resultValue))
result = null;
else
result = resultValue;
}
return new(check, result);
}
}

View File

@ -1,972 +0,0 @@
using ShellProgressBar;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using View_by_Distance.Property.Models.Stateless;
using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Property.Models;
public class PropertyLogic
{
protected readonly List<(int, string[])> _AllCollection;
protected readonly List<string> _ExceptionsDirectories;
protected readonly Dictionary<int, int[]> _KeyValuePairs;
protected readonly Dictionary<int, int[]> _IndicesFromNew;
protected readonly string _DeterministicHashCodeRootDirectory;
protected readonly Dictionary<int, string[]> _SixCharacterNamedFaceInfo;
protected readonly Dictionary<int, string[]> _NamedFaceInfoDeterministicHashCodeKeyValuePairs;
protected readonly Dictionary<double, string[]> _NamedDeterministicHashCodeKeyValuePairs;
protected readonly Dictionary<double, string[]> _IncorrectDeterministicHashCodeKeyValuePairs;
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 string DeterministicHashCodeRootDirectory => _DeterministicHashCodeRootDirectory;
public Dictionary<double, string[]> NamedDeterministicHashCodeKeyValuePairs => _NamedDeterministicHashCodeKeyValuePairs;
public Dictionary<double, string[]> IncorrectDeterministicHashCodeKeyValuePairs => _IncorrectDeterministicHashCodeKeyValuePairs;
public Dictionary<int, string[]> NamedFaceInfoDeterministicHashCodeKeyValuePairs => _NamedFaceInfoDeterministicHashCodeKeyValuePairs;
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, 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>();
_MaxDegreeOfParallelism = maxDegreeOfParallelism;
Dictionary<int, string[]>? namedFaceInfoDeterministicHashCode;
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
if (configuration.VerifyToSeason is null || !configuration.VerifyToSeason.Any())
throw new Exception();
_VerifyToSeason = configuration.VerifyToSeason.Select(l => Path.Combine(configuration.RootDirectory, l)).ToArray();
string json;
string[] files;
string fullPath;
Dictionary<int, int[]>? keyValuePairs;
string deterministicHashCodeRootDirectory;
List<KeyValuePair<int, int[]>>? collection;
Dictionary<int, int[]> indicesFromNew = new();
Dictionary<int, string[]>? sixCharacterNamedFaceInfo;
Dictionary<double, string[]> namedDeterministicHashCode = new();
Dictionary<double, string[]> incorrectDeterministicHashCode = new();
string? rootDirectoryParent = Path.GetDirectoryName(configuration.RootDirectory);
if (string.IsNullOrEmpty(rootDirectoryParent))
throw new NullReferenceException(nameof(rootDirectoryParent));
files = Directory.GetFiles(rootDirectoryParent, "*DeterministicHashCode*.json", SearchOption.TopDirectoryOnly);
if (files.Length != 1)
namedFaceInfoDeterministicHashCode = new();
else
{
json = File.ReadAllText(files[0]);
namedFaceInfoDeterministicHashCode = JsonSerializer.Deserialize<Dictionary<int, string[]>>(json);
if (namedFaceInfoDeterministicHashCode is null)
throw new NullReferenceException(nameof(namedFaceInfoDeterministicHashCode));
}
string[] directories = Directory.GetDirectories(rootDirectoryParent, "*DeterministicHashCode*", SearchOption.TopDirectoryOnly);
if (!directories.Any())
deterministicHashCodeRootDirectory = string.Empty;
else
{
Dictionary<int, List<IFace>> faces = new();
deterministicHashCodeRootDirectory = directories[0];
SetKeyValuePairs(deterministicHashCodeRootDirectory, namedDeterministicHashCode, incorrectDeterministicHashCode, faces);
}
if (!namedFaceInfoDeterministicHashCode.Any())
sixCharacterNamedFaceInfo = new();
else
{
files = Directory.GetFiles(rootDirectoryParent, "*SixCharacter*.json", SearchOption.TopDirectoryOnly);
if (files.Length != 1)
sixCharacterNamedFaceInfo = new();
else
{
json = File.ReadAllText(files[0]);
sixCharacterNamedFaceInfo = JsonSerializer.Deserialize<Dictionary<int, string[]>>(json);
if (sixCharacterNamedFaceInfo is null)
throw new NullReferenceException(nameof(sixCharacterNamedFaceInfo));
}
}
files = Directory.GetFiles(rootDirectoryParent, "*keyValuePairs*.json", SearchOption.TopDirectoryOnly);
if (files.Length != 1)
keyValuePairs = new();
else
{
json = File.ReadAllText(files[0]);
keyValuePairs = JsonSerializer.Deserialize<Dictionary<int, int[]>>(json);
if (keyValuePairs is null)
throw new NullReferenceException(nameof(keyValuePairs));
}
foreach (string propertyContentCollectionFile in configuration.PropertyContentCollectionFiles)
{
fullPath = Path.GetFullPath(string.Concat(rootDirectoryParent, propertyContentCollectionFile));
if (fullPath.Contains(configuration.RootDirectory))
continue;
if (!File.Exists(fullPath))
continue;
json = File.ReadAllText(fullPath);
collection = JsonSerializer.Deserialize<List<KeyValuePair<int, int[]>>>(json);
if (collection is null)
throw new NullReferenceException(nameof(collection));
foreach (KeyValuePair<int, int[]> keyValuePair in collection)
{
if (indicesFromNew.ContainsKey(keyValuePair.Key))
continue;
indicesFromNew.Add(keyValuePair.Key, keyValuePair.Value);
}
}
_KeyValuePairs = keyValuePairs;
_IndicesFromNew = indicesFromNew;
_SixCharacterNamedFaceInfo = sixCharacterNamedFaceInfo;
_NamedDeterministicHashCodeKeyValuePairs = namedDeterministicHashCode;
_DeterministicHashCodeRootDirectory = deterministicHashCodeRootDirectory;
_IncorrectDeterministicHashCodeKeyValuePairs = incorrectDeterministicHashCode;
_NamedFaceInfoDeterministicHashCodeKeyValuePairs = namedFaceInfoDeterministicHashCode;
}
private static void SetKeyValuePairs(string deterministicHashCodeRootDirectory, List<(string, double)> named, List<(string, double)> incorrect, Dictionary<int, List<IFace>> keyValuePairs)
{
string[] files;
string fileName;
string personKey;
string? checkFile;
string[] yearDirectories;
string[] personKeyDirectories;
string[] personNameDirectories;
double? idAndNormalizedPixelPercentage;
string[] ticksDirectories = Directory.GetDirectories(deterministicHashCodeRootDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string ticksDirectory in ticksDirectories)
{
if (!ticksDirectory.EndsWith(')'))
continue;
personKeyDirectories = Directory.GetDirectories(ticksDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string personKeyDirectory in personKeyDirectories)
{
personKey = Path.GetFileName(personKeyDirectory);
yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string yearDirectory in yearDirectories)
{
files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly);
personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
if (file.EndsWith(".lnk"))
continue;
fileName = Path.GetFileName(file);
idAndNormalizedPixelPercentage = Named.GetReversedDeterministicHashCode(fileName);
if (idAndNormalizedPixelPercentage is null)
{
(checkFile, idAndNormalizedPixelPercentage) = Named.GetReversedDeterministicHashCode(keyValuePairs, file);
if (idAndNormalizedPixelPercentage is null)
break;
if (!string.IsNullOrEmpty(checkFile))
File.Move(file, checkFile);
}
incorrect.Add(new(personKey, idAndNormalizedPixelPercentage.Value));
}
foreach (string personNameDirectory in personNameDirectories)
{
files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
if (file.EndsWith(".lnk"))
continue;
fileName = Path.GetFileName(file);
idAndNormalizedPixelPercentage = Named.GetReversedDeterministicHashCode(fileName);
if (idAndNormalizedPixelPercentage is null)
{
(checkFile, idAndNormalizedPixelPercentage) = Named.GetReversedDeterministicHashCode(keyValuePairs, file);
if (idAndNormalizedPixelPercentage is null)
break;
if (!string.IsNullOrEmpty(checkFile))
File.Move(file, checkFile);
}
named.Add(new(personKey, idAndNormalizedPixelPercentage.Value));
}
}
}
}
}
}
private static void SetKeyValuePairs(string deterministicHashCodeRootDirectory, Dictionary<double, string[]> namedDeterministicHashCode, Dictionary<double, string[]> incorrectDeterministicHashCode, Dictionary<int, List<IFace>> keyValuePairs)
{
Dictionary<double, List<string>> namedKeyValuePairs = new();
Dictionary<double, List<string>> incorrectKeyValuePairs = new();
List<(string PersonKey, double IdAndNormalizedPixelPercentage)> named = new();
List<(string PersonKey, double IdAndNormalizedPixelPercentage)> incorrect = new();
SetKeyValuePairs(deterministicHashCodeRootDirectory, named, incorrect, keyValuePairs);
named = (from l in named orderby l.IdAndNormalizedPixelPercentage select l).ToList();
incorrect = (from l in incorrect orderby l.IdAndNormalizedPixelPercentage select l).ToList();
foreach ((string personKey, double idAndNormalizedPixelPercentage) in named)
{
if (!namedKeyValuePairs.ContainsKey(idAndNormalizedPixelPercentage))
namedKeyValuePairs.Add(idAndNormalizedPixelPercentage, new());
namedKeyValuePairs[idAndNormalizedPixelPercentage].Add(personKey);
}
foreach ((string personKey, double idAndNormalizedPixelPercentage) in incorrect)
{
if (!incorrectKeyValuePairs.ContainsKey(idAndNormalizedPixelPercentage))
incorrectKeyValuePairs.Add(idAndNormalizedPixelPercentage, new());
incorrectKeyValuePairs[idAndNormalizedPixelPercentage].Add(personKey);
}
foreach (KeyValuePair<double, List<string>> keyValuePair in namedKeyValuePairs)
namedDeterministicHashCode.Add(keyValuePair.Key, keyValuePair.Value.Distinct().ToArray());
foreach (KeyValuePair<double, List<string>> keyValuePair in incorrectKeyValuePairs)
incorrectDeterministicHashCode.Add(keyValuePair.Key, keyValuePair.Value.Distinct().ToArray());
}
public void UpdateKeyValuePairs(List<Container> containers)
{
Dictionary<int, List<IFace>> keyValuePairs = new();
Dictionary<double, string[]> namedDeterministicHashCode = new();
Dictionary<double, string[]> incorrectDeterministicHashCode = new();
foreach (Container container in containers)
{
foreach (Item item in container.Items)
{
if (item.ImageFileHolder is null || item.Property?.Id is null || !item.Faces.Any())
continue;
if (keyValuePairs.ContainsKey(item.Property.Id.Value))
{
if (keyValuePairs[item.Property.Id.Value].Count != item.Faces.Count)
throw new Exception();
continue;
}
keyValuePairs.Add(item.Property.Id.Value, item.Faces);
}
}
SetKeyValuePairs(_DeterministicHashCodeRootDirectory, namedDeterministicHashCode, incorrectDeterministicHashCode, keyValuePairs);
foreach (KeyValuePair<double, string[]> keyValuePair in namedDeterministicHashCode)
_NamedDeterministicHashCodeKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value);
foreach (KeyValuePair<double, string[]> keyValuePair in incorrectDeterministicHashCode)
_IncorrectDeterministicHashCodeKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value);
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
private long LogDelta(long ticks, string methodName)
{
long result;
if (_Log is null)
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;
return result;
}
public static List<DateTime> GetMetadataDateTimesByPattern(string dateTimeFormat, string filteredSourceDirectoryFile)
{
List<DateTime> results = new();
try
{
DateTime checkDateTime;
DateTime kristy = new(1976, 3, 8);
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(filteredSourceDirectoryFile);
foreach (MetadataExtractor.Directory directory in directories)
{
foreach (MetadataExtractor.Tag tag in directory.Tags)
{
if (string.IsNullOrEmpty(tag.Description) || tag.Description.Length != dateTimeFormat.Length)
continue;
if (!DateTime.TryParseExact(tag.Description, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
continue;
if (checkDateTime < kristy)
continue;
results.Add(checkDateTime);
}
}
}
catch (Exception) { }
return results;
}
public static List<DateTime> GetMetadataDateTimesByPattern(string dateTimeFormat, FileHolder filteredSourceDirectoryFileHolder)
{
List<DateTime> results = GetMetadataDateTimesByPattern(dateTimeFormat, filteredSourceDirectoryFileHolder.FullName);
return results;
}
#pragma warning disable CA1416
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 NullReferenceException(nameof(_Log));
if (_Configuration.WriteBitmapDataBytes is null)
throw new NullReferenceException(nameof(_Configuration.WriteBitmapDataBytes));
long ticks;
byte[] bytes;
string value;
long fileLength;
int encodingHash;
int? width = null;
int? height = null;
string dateTimeFormat;
DateTime checkDateTime;
DateTime? dateTime = null;
PropertyItem? propertyItem;
string make = string.Empty;
string model = string.Empty;
DateTime? gpsDateStamp = null;
DateTime? dateTimeOriginal = null;
string orientation = string.Empty;
DateTime? dateTimeDigitized = null;
if (!isValidImageFormatExtension && isValidMetadataExtensions)
{
dateTimeFormat = "ddd MMM dd HH:mm:ss yyyy";
List<DateTime> dateTimes = GetMetadataDateTimesByPattern(dateTimeFormat, filteredSourceDirectoryFileHolder);
if (dateTimes.Any())
dateTimeOriginal = dateTimes.Min();
}
else if (!isIgnoreExtension && isValidImageFormatExtension)
{
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
{
using Image image = Image.FromFile(filteredSourceDirectoryFileHolder.FullName);
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;
int length = bitmapData.Stride * bitmap.Height;
bytes = new byte[length];
Marshal.Copy(intPtr, bytes, 0, length);
bitmap.UnlockBits(bitmapData);
if (id is null)
{
ticks = DateTime.Now.Ticks;
id = Stateless.A_Property.GetDeterministicHashCode(bytes);
if (_MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Stateless.A_Property.GetDeterministicHashCode));
}
if (_Configuration.WriteBitmapDataBytes.Value)
{
FileInfo contentFileInfo = new(Path.Combine(angleBracket.Replace("<>", "()"), filteredSourceDirectoryFileHolder.Name));
File.WriteAllBytes(Path.ChangeExtension(contentFileInfo.FullName, string.Empty), bytes);
}
if (_IndicesFromNew.ContainsKey(id.Value) && _IndicesFromNew[id.Value].Any())
indices.AddRange(_IndicesFromNew[id.Value]);
else
{
ticks = DateTime.Now.Ticks;
string encoding = Encoding.Default.GetString(bytes);
if (_MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Encoding.Default.GetString));
encodingHash = Stateless.A_Property.GetDeterministicHashCode(encoding);
if (_MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Stateless.A_Property.GetDeterministicHashCode));
if (!_KeyValuePairs.ContainsKey(encodingHash))
indices.Add(encodingHash);
else
indices.AddRange(_KeyValuePairs[encodingHash]);
}
}
width = image.Width;
height = image.Height;
dateTimeFormat = Stateless.A_Property.DateTimeFormat();
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTime))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTime);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTime = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeDigitized))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeDigitized);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTimeDigitized = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeOriginal))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeOriginal);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTimeOriginal = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.GPSDateStamp))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.GPSDateStamp);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
gpsDateStamp = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Make))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Make);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
make = value;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Model))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Model);
if (propertyItem?.Value is not null)
{
value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
model = value;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Orientation))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Orientation);
if (propertyItem?.Value is not null)
{
value = BitConverter.ToInt16(propertyItem.Value, 0).ToString();
orientation = value;
}
}
}
catch (Exception)
{
_Log.Info(string.Concat(new StackFrame().GetMethod()?.Name, " <", filteredSourceDirectoryFileHolder.Name, ">"));
}
}
else
dateTimeOriginal = null;
if (filteredSourceDirectoryFileHolder.Length is null)
fileLength = 0;
else
fileLength = filteredSourceDirectoryFileHolder.Length.Value;
result = new(filteredSourceDirectoryFileHolder.CreationTime, dateTime, dateTimeDigitized, dateTimeOriginal, fileLength, gpsDateStamp, height, id, indices.ToArray(), filteredSourceDirectoryFileHolder.LastWriteTime, make, model, orientation, width);
return result;
}
#pragma warning restore CA1416
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 NullReferenceException(nameof(_Configuration.ForcePropertyLastWriteTimeToCreationTime));
if (_Configuration.PopulatePropertyId is null)
throw new NullReferenceException(nameof(_Configuration.PopulatePropertyId));
if (_Configuration.PropertiesChangedForProperty is null)
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("<>", "{}"), $"{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();
}
List<DateTime> dateTimes = (from l in filteredSourceDirectoryFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
if (!fileInfo.Exists)
{
if (fileInfo.Directory?.Parent is null)
throw new Exception();
string parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name);
if (File.Exists(parentCheck))
{
File.Move(parentCheck, fileInfo.FullName);
fileInfo.Refresh();
}
}
if (_Configuration.ForcePropertyLastWriteTimeToCreationTime.Value && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
{
File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName);
fileInfo.Refresh();
}
if (_Configuration.ForcePropertyLastWriteTimeToCreationTime.Value && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime)
{
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
fileInfo.Refresh();
}
if (_Configuration.PropertiesChangedForProperty.Value)
result = null;
else if (!fileInfo.Exists)
result = null;
else if (!fileInfo.FullName.EndsWith(".json") && !fileInfo.FullName.EndsWith(".old"))
throw new ArgumentException("must be a *.json file");
else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
result = null;
else
{
json = File.ReadAllText(fileInfo.FullName);
try
{
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
bool check = true;
A_Property? property = JsonSerializer.Deserialize<A_Property>(json);
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(item.ImageFileHolder, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices);
}
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(item.ImageFileHolder, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices);
}
if (!isIgnoreExtension && item.ValidImageFormatExtension && populateId && property is not null && property.LastWriteTime != item.ImageFileHolder.LastWriteTime)
{
check = false;
id = null;
indices.Clear();
property = GetImageProperty(item.ImageFileHolder, populateId, isIgnoreExtension, item.ValidImageFormatExtension, isValidMetadataExtensions, id, indices);
}
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(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!");
}
// if (filteredSourceDirectoryFileFileInfo.CreationTime != property?.CreationTime || filteredSourceDirectoryFileFileInfo.LastWriteTime != property?.LastWriteTime)
// {
// check = false;
// id = null;
// indices.Clear();
// property = GetImagePropertyB(filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
// }
if (json.Contains("WrongYear"))
{
id = property?.Id;
hasWrongYearProperty = true;
}
if (property is null)
throw new Exception();
if (!check)
result = null;
else
{
result = property;
filteredSourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), fileInfo.LastWriteTime));
}
}
catch (Exception)
{
result = null;
parseExceptions.Add(nameof(A_Property));
}
}
if (result is null)
{
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))
{
if (!_Configuration.ForcePropertyLastWriteTimeToCreationTime.Value && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime))
filteredSourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
else
{
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
fileInfo.Refresh();
filteredSourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), fileInfo.CreationTime));
}
}
}
else if (hasWrongYearProperty)
{
json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions);
if (IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true))
{
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
fileInfo.Refresh();
filteredSourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), fileInfo.CreationTime));
}
}
return result;
}
private bool AnyFilesMoved(string sourceDirectory, Item[] filteredItems)
{
bool result = false;
if (_Log is null)
throw new NullReferenceException(nameof(_Log));
int season;
string[] matches;
string deleteFile;
bool? isWrongYear;
string seasonName;
DateTime dateTime;
string destinationFile;
DateTime minimumDateTime;
string destinationDirectory;
string[] sourceDirectorySegments;
DateTime directoryMaximumOfMinimumDateTime = DateTime.MinValue;
foreach (Item filteredItem in filteredItems)
{
if (!filteredItem.ValidImageFormatExtension || filteredItem.Property is null || filteredItem.ImageFileHolder is null)
continue;
minimumDateTime = Stateless.A_Property.GetMinimumDateTime(filteredItem.Property);
if (minimumDateTime > directoryMaximumOfMinimumDateTime)
directoryMaximumOfMinimumDateTime = minimumDateTime;
if (minimumDateTime != filteredItem.ImageFileHolder.CreationTime)
{
(isWrongYear, matches) = filteredItem.Property.IsWrongYear(filteredItem.ImageFileHolder.FullName, minimumDateTime);
if (isWrongYear is null || !isWrongYear.Value)
dateTime = minimumDateTime;
else
{
if (!matches.Any())
continue;
if (!DateTime.TryParseExact(matches[0], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
continue;
}
try
{ File.SetCreationTime(filteredItem.ImageFileHolder.FullName, dateTime); }
catch (Exception)
{ }
}
if (!_VerifyToSeason.Contains(sourceDirectory))
continue;
if (!filteredItem.ImageFileHolder.FullName.Contains("zzz ") && !filteredItem.ImageFileHolder.FullName.Contains("Camera ") && filteredItem.Property.DateTimeOriginal.HasValue)
{
TimeSpan timeSpan = new(filteredItem.Property.DateTimeOriginal.Value.Ticks - filteredItem.Property.LastWriteTime.Ticks);
if (timeSpan.TotalHours > 6)
{
_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}>");
}
}
sourceDirectorySegments = Path.GetFileName(sourceDirectory).Split(' ');
(season, seasonName) = Stateless.A_Property.GetSeason(minimumDateTime.DayOfYear);
if (sourceDirectorySegments[0] == "zzz")
destinationDirectory = Path.Combine(_Configuration.RootDirectory, $"zzz ={minimumDateTime:yyyy}.{season} {seasonName} {string.Join(' ', sourceDirectorySegments.Skip(3))}");
else if (sourceDirectorySegments.Length > 2)
destinationDirectory = Path.Combine(_Configuration.RootDirectory, $"={minimumDateTime:yyyy}.{season} {seasonName} {string.Join(' ', sourceDirectorySegments.Skip(2))}");
else
destinationDirectory = Path.Combine(_Configuration.RootDirectory, $"={minimumDateTime:yyyy}.{season} {seasonName}");
if (destinationDirectory == sourceDirectory)
continue;
lock (filteredItem)
filteredItem.SetMoved(true);
if (!result)
result = true;
if (!Directory.Exists(destinationDirectory))
_ = Directory.CreateDirectory(destinationDirectory);
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(filteredItem.ImageFileHolder.Name, ".jpeg"));
else if (destinationFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
destinationFile = Path.Combine(destinationDirectory, Path.ChangeExtension(filteredItem.ImageFileHolder.Name, ".jpg"));
}
if (File.Exists(destinationFile))
{
_Log.Information($"*** source <{filteredItem.ImageFileHolder.FullName}>");
_Log.Information($"*** destination <{destinationFile}>");
if (filteredItem.ImageFileHolder.Exists)
{
deleteFile = Path.ChangeExtension(filteredItem.ImageFileHolder.FullName, ".delete");
if (File.Exists(deleteFile))
File.Delete(deleteFile);
File.Move(filteredItem.ImageFileHolder.FullName, deleteFile);
}
}
else
{
File.Move(filteredItem.ImageFileHolder.FullName, destinationFile);
if (filteredItem.ImageFileHolder.Exists)
{
deleteFile = Path.ChangeExtension(filteredItem.ImageFileHolder.FullName, ".delete");
if (File.Exists(deleteFile))
File.Delete(deleteFile);
File.Move(filteredItem.ImageFileHolder.FullName, deleteFile);
}
}
}
if (directoryMaximumOfMinimumDateTime != DateTime.MinValue)
{
System.IO.DirectoryInfo directoryInfo = new(sourceDirectory);
if (directoryInfo.LastWriteTime != directoryMaximumOfMinimumDateTime)
Directory.SetLastWriteTime(sourceDirectory, directoryMaximumOfMinimumDateTime);
}
return result;
}
private void ParallelForWork(bool firstPass, string sourceDirectory, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item item)
{
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
A_Property property;
List<string> parseExceptions = new();
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(item, firstPass, filteredSourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidMetadataExtensions);
lock (sourceDirectoryChanges)
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
lock (item)
item.Update(property);
}
}
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 = $"{container.R: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, container.SourceDirectory, sourceDirectoryChanges, filteredSourceDirectoryFileTuples, filteredItems[i]);
if (i == 0 || sourceDirectoryChanges.Any())
progressBar.Tick();
lock (filteredSourceDirectoryFileTuples)
collection = (from l in filteredSourceDirectoryFileTuples where l.Item2 > dateTime select l).ToList();
lock (sourceDirectoryChanges)
sourceDirectoryChanges.AddRange(collection);
}
catch (Exception ex)
{
lock (exceptions)
exceptions.Add(ex);
}
});
}
private void SetAngleBracketCollection(string sourceDirectory)
{
AngleBracketCollection.Clear();
AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(_Configuration,
_Model,
_PredictorModel,
sourceDirectory,
nameof(A_Property),
string.Empty,
includeResizeGroup: false,
includeModel: false,
includePredictorModel: false,
contentDescription: string.Empty,
singletonDescription: "Properties for each image",
collectionDescription: string.Empty));
}
public void ParallelWork(long ticks, List<Container> containers, bool firstPass)
{
if (_Log is null)
throw new NullReferenceException(nameof(_Log));
if (_Configuration.PopulatePropertyId is null)
throw new NullReferenceException(nameof(_Configuration.PopulatePropertyId));
int totalSeconds;
bool? anyFilesMoved;
Item[] filteredItems;
List<Exception> exceptions = new();
int containersCount = containers.Count;
List<Tuple<string, DateTime>> sourceDirectoryChanges = new();
string propertyRoot = IResult.GetResultsGroupDirectory(_Configuration, nameof(A_Property));
foreach (Container container in containers)
{
if (!container.Items.Any())
continue;
sourceDirectoryChanges.Clear();
if (firstPass)
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
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;
totalSeconds = (int)Math.Truncate(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
SetAngleBracketCollection(container.SourceDirectory);
ParallelWork(firstPass, exceptions, sourceDirectoryChanges, containersCount, container, filteredItems, totalSeconds);
foreach (Exception exception in exceptions)
_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(container.SourceDirectory);
if (!firstPass || exceptions.Count != 0)
anyFilesMoved = null;
else
anyFilesMoved = AnyFilesMoved(container.SourceDirectory, filteredItems);
if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any())
{
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key when ready to continue or close console");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
}
}
}
public A_Property GetProperty(Item item, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<string> parseExceptions)
{
A_Property result;
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
bool firstPass = false;
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(List<DirectoryInfo> groupCollection, bool saveToCollection)
{
List<(long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)> results = new();
int level;
A_Property? property;
string checkDirectory;
List<string> directories;
string propertyDirectory;
string angleBracket = AngleBracketCollection[0];
foreach (DirectoryInfo group in groupCollection)
{
SetAngleBracketCollection(group.SourceDirectory);
if (string.IsNullOrEmpty(group.SourceDirectory))
throw new Exception();
if (!saveToCollection)
propertyDirectory = angleBracket.Replace("<>", "()");
else
{
(level, directories) = IPath.Get(_Configuration.RootDirectory, group.SourceDirectory);
checkDirectory = IPath.GetDirectory(angleBracket, level, "[()]");
propertyDirectory = Path.Combine(checkDirectory, string.Join(_Configuration.FileNameDirectorySeparator, directories));
}
if (!Directory.Exists(propertyDirectory))
_ = Directory.CreateDirectory(propertyDirectory);
for (int i = 0; i < group.SourceDirectoryFileHolderCollection.Length; i++)
{
property = group.PropertyCollection[i];
if (property?.Id is null)
continue;
results.Add(new(property.GetDateTimes().Min().Ticks, group.FilteredSourceDirectoryFiles[i], propertyDirectory, property.Id.Value));
}
}
return results.OrderBy(l => l.Ticks).ToArray();
}
public void AddToPropertyLogicAllCollection(Item[] filteredItems)
{
if (_SixCharacterNamedFaceInfo.Any())
{
string[] keys;
Item item;
for (int i = 0; i < filteredItems.Length; i++)
{
item = filteredItems[i];
if (item.Property?.Id is null)
continue;
foreach (int sixCharacterIndex in item.Property.Indices)
{
if (!_SixCharacterNamedFaceInfo.ContainsKey(sixCharacterIndex))
continue;
keys = _SixCharacterNamedFaceInfo[sixCharacterIndex];
_AllCollection.Add(new(item.Property.Id.Value, keys));
}
}
}
}
public void SaveAllCollection()
{
if (_AllCollection.Any())
{
string[] keys;
string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.RootDirectory);
if (string.IsNullOrEmpty(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)
{
if (namedFaceInfoDeterministicHashCodeIndices.ContainsKey(deterministicHashCode))
{
keys = namedFaceInfoDeterministicHashCodeIndices[deterministicHashCode];
if (JsonSerializer.Serialize(values) == JsonSerializer.Serialize(keys))
continue;
throw new Exception();
}
namedFaceInfoDeterministicHashCodeIndices.Add(deterministicHashCode, values);
}
string json = JsonSerializer.Serialize(namedFaceInfoDeterministicHashCodeIndices, new JsonSerializerOptions { WriteIndented = true });
string checkFile = Path.Combine(rootDirectoryParent, "NamedFaceInfoDeterministicHashCodeIndices.json");
_ = IPath.WriteAllText(checkFile, json, updateDateWhenMatches: true, compareBeforeWrite: true);
}
}
}

View File

@ -1,283 +0,0 @@
namespace View_by_Distance.Property.Models.Stateless;
public static class A_Property
{
public static string DateTimeFormat() => "yyyy:MM:dd HH:mm:ss";
public static (int Season, string seasonName) GetSeason(int dayOfYear)
{
(int Season, string seasonName) result = dayOfYear switch
{
< 78 => new(0, "Winter"),
< 171 => new(1, "Spring"),
< 264 => new(2, "Summer"),
< 354 => new(3, "Fall"),
_ => new(4, "Winter")
};
return result;
}
public static List<Models.Container> Get(Models.Configuration configuration, PropertyLogic propertyLogic)
{
List<Models.Container> results;
long ticks = DateTime.Now.Ticks;
List<string> exceptionsDirectories = new();
results = Container.GetContainers(configuration, propertyLogic);
propertyLogic.ParallelWork(ticks, results, firstPass: false);
if (exceptionsDirectories.Any())
throw new Exception();
return results;
}
public static int GetDeterministicHashCode(byte[] value)
{
int result;
unchecked
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1;
for (int i = 0; i < value.Length; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ value[i];
if (i == value.Length - 1)
break;
hash2 = ((hash2 << 5) + hash2) ^ value[i + 1];
}
result = hash1 + (hash2 * 1566083941);
}
return result;
}
public static int GetDeterministicHashCode(string value)
{
int result;
unchecked
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1;
for (int i = 0; i < value.Length; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ value[i];
if (i == value.Length - 1)
break;
hash2 = ((hash2 << 5) + hash2) ^ value[i + 1];
}
result = hash1 + (hash2 * 1566083941);
}
return result;
}
public static (bool?, string[]) IsWrongYear(string[] segments, string year)
{
bool? result;
string[] results = (
from l
in segments
where l?.Length > 2
&& (
l[..2] is "19" or "20"
|| (l.Length == 5 && l.Substring(1, 2) is "19" or "20" && (l[0] is '~' or '=' or '-' or '^' or '#'))
|| (l.Length == 6 && l[..2] is "19" or "20" && l[4] == '.')
|| (l.Length == 7 && l.Substring(1, 2) is "19" or "20" && l[5] == '.')
)
select l
).ToArray();
string[] matches = (
from l
in results
where l == year
|| (l.Length == 5 && l.Substring(1, 4) == year && (l[0] is '~' or '=' or '-' or '^' or '#'))
|| (l.Length == 6 && l[..4] == year && l[4] == '.')
|| (l.Length == 7 && l.Substring(1, 4) == year && l[5] == '.')
select l
).ToArray();
if (!results.Any())
result = null;
else
result = !matches.Any();
return new(result, results);
}
public static List<DateTime> GetDateTimes(DateTime creationTime, DateTime lastWriteTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeOriginal, DateTime? gpsDateStamp)
{
List<DateTime> results = new()
{
creationTime,
lastWriteTime
};
if (dateTime.HasValue)
results.Add(dateTime.Value);
if (dateTimeDigitized.HasValue)
results.Add(dateTimeDigitized.Value);
if (dateTimeOriginal.HasValue)
results.Add(dateTimeOriginal.Value);
if (gpsDateStamp.HasValue)
results.Add(gpsDateStamp.Value);
return results;
}
public static DateTime GetDateTime(Models.A_Property? property)
{
DateTime result;
if (property is null)
result = DateTime.MinValue;
else
{
List<DateTime> dateTimes = new()
{
property.CreationTime,
property.LastWriteTime
};
if (property.DateTime.HasValue)
dateTimes.Add(property.DateTime.Value);
if (property.DateTimeDigitized.HasValue)
dateTimes.Add(property.DateTimeDigitized.Value);
if (property.DateTimeOriginal.HasValue)
dateTimes.Add(property.DateTimeOriginal.Value);
if (property.GPSDateStamp.HasValue)
dateTimes.Add(property.GPSDateStamp.Value);
result = dateTimes.Min();
}
return result;
}
public static List<DateTime> GetDateTimes(Models.A_Property property) => GetDateTimes(property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeOriginal, property.GPSDateStamp);
public static DateTime GetMinimumDateTime(Models.A_Property? property)
{
DateTime result;
List<DateTime> dateTimes;
if (property is null)
result = DateTime.MinValue;
else
{
dateTimes = GetDateTimes(property);
result = dateTimes.Min();
}
return result;
}
public static string GetDiffRootDirectory(string diffPropertyDirectory)
{
string result = string.Empty;
string results = " - Results";
string? checkDirectory = diffPropertyDirectory;
for (int i = 0; i < int.MaxValue; i++)
{
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory))
break;
if (checkDirectory.EndsWith(results))
{
result = checkDirectory[..^results.Length];
break;
}
}
return result;
}
public static double GetStandardDeviation(IEnumerable<long> values, double average)
{
double result = 0;
if (!values.Any())
throw new Exception("Collection must have at least one value!");
double sum = values.Sum(l => (l - average) * (l - average));
result = Math.Sqrt(sum / values.Count());
return result;
}
public static TimeSpan GetThreeStandardDeviationHigh(int minimum, Models.Container container)
{
TimeSpan result;
DateTime? minimumDateTime;
List<long> ticksCollection = new();
foreach (Item item in container.Items)
{
if (item.Property is null)
continue;
minimumDateTime = GetMinimumDateTime(item.Property);
if (minimumDateTime is null)
continue;
ticksCollection.Add(minimumDateTime.Value.Ticks);
}
long threeStandardDeviationHigh;
long min;
if (!ticksCollection.Any())
min = 0;
else
min = ticksCollection.Min();
if (ticksCollection.Count < minimum)
threeStandardDeviationHigh = long.MaxValue;
else
{
ticksCollection = (from l in ticksCollection select l - min).ToList();
double sum = ticksCollection.Sum();
double average = sum / ticksCollection.Count;
double standardDeviation = GetStandardDeviation(ticksCollection, average);
threeStandardDeviationHigh = (long)Math.Ceiling(average + min + (standardDeviation * 3));
}
result = new TimeSpan(threeStandardDeviationHigh - min);
return result;
}
public static (int, List<DateTime>, List<Item>) Get(Models.Container container, TimeSpan threeStandardDeviationHigh, int i)
{
List<Item> results = new();
int j = i;
Item item;
long? ticks;
Item nextItem;
TimeSpan timeSpan;
DateTime? minimumDateTime;
DateTime? nextMinimumDateTime;
List<DateTime> dateTimes = new();
for (; j < container.Items.Count; j++)
{
ticks = null;
item = container.Items[j];
if (item.Property is null)
continue;
minimumDateTime = GetMinimumDateTime(item.Property);
if (minimumDateTime is null)
continue;
for (int k = j + 1; k < container.Items.Count; k++)
{
nextItem = container.Items[k];
if (nextItem.Property is null)
continue;
nextMinimumDateTime = GetMinimumDateTime(nextItem.Property);
if (nextMinimumDateTime is null)
continue;
ticks = nextMinimumDateTime.Value.Ticks;
break;
}
results.Add(item);
dateTimes.Add(minimumDateTime.Value);
if (ticks.HasValue)
{
timeSpan = new(ticks.Value - minimumDateTime.Value.Ticks);
if (timeSpan > threeStandardDeviationHigh)
break;
}
}
return new(j, dateTimes, results);
}
public static bool Any(List<Models.Container> propertyHolderCollections)
{
bool result = false;
foreach (Models.Container container in propertyHolderCollections)
{
if (!container.Items.Any())
continue;
if ((from l in container.Items where l.Any() select true).Any())
{
result = true;
break;
}
}
return result;
}
}

View File

@ -1,42 +0,0 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Text.Json;
namespace View_by_Distance.Property.Models.Stateless;
public abstract class Configuration
{
public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, string workingDirectory)
{
Models.Configuration? result;
string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment);
string section = string.Concat(environmentName, ":", nameof(Binder.Configuration));
IConfigurationSection configurationSection = configurationRoot.GetSection(section);
Binder.Configuration configuration = configurationSection.Get<Binder.Configuration>();
string json = JsonSerializer.Serialize(configuration, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.Configuration>(json);
if (result is null)
throw new Exception(json);
string jsonThis = result.ToString();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -1,4 +1,5 @@
using System.Text.Json;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Property.Models.Stateless;
@ -98,67 +99,61 @@ public class Container
return results;
}
private static List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> GetJsonGroupCollection(Models.Configuration configuration, PropertyLogic propertyLogic, string rootDirectory)
private static List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> GetJsonGroupCollection(Configuration configuration, A_Property 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);
results = GetGroupCollection(rootDirectory, configuration.MaxImagesInDirectoryForTopLevelFirstPass, 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)
private static List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles, int r)> GetFileHolderGroupCollection(Configuration configuration, A_Property 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);
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)>? collection = GetGroupCollection(configuration.RootDirectory, configuration.MaxImagesInDirectoryForTopLevelFirstPass, 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)
private static void ParallelFor(List<(int, string, string[], int)> jsonCollection, int i, int length, List<(int, string, List<(string, Shared.Models.Property?)>, int)> results)
{
string key;
string json;
Models.A_Property? property;
Shared.Models.Property? property;
(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) = jsonCollection[i];
List<(string, Models.A_Property?)> collection = new();
List<(string, Shared.Models.Property?)> collection = new();
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
{
json = File.ReadAllText(sourceDirectoryFile);
key = XPath.GetRelativePath(sourceDirectoryFile, length);
property = JsonSerializer.Deserialize<Models.A_Property>(json);
key = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFile, length);
property = JsonSerializer.Deserialize<Shared.Models.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)
private static List<(int g, string sourceDirectory, List<(string sourceDirectoryFile, Shared.Models.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();
List<(int, string, List<(string, Shared.Models.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)
private static List<Shared.Models.Container> GetContainers(Configuration configuration, string aPropertySingletonDirectory, List<(int, string, FileHolder[], int)> fileHolderGroupCollection, List<(int, string, List<(string, Shared.Models.Property?)>, int)> collectionFromJson)
{
List<Models.Container> results = new();
if (configuration.PropertiesChangedForProperty is null)
throw new Exception($"{configuration.PropertiesChangedForProperty} is null");
List<Shared.Models.Container> results = new();
int length;
string key;
string inferred;
List<Item> items;
string relativePath;
FileHolder keyFileHolder;
Models.Container container;
Shared.Models.Container container;
bool isValidImageFormatExtension;
List<string> keySourceDirectories;
Dictionary<string, (string SourceDirectory, FileHolder FileHolder)> fileHolderKeyValuePairs = new();
@ -167,21 +162,21 @@ public class Container
{
foreach (FileHolder sourceDirectoryFileHolder in sourceDirectoryFileHolderCollection)
{
relativePath = XPath.GetRelativePath(sourceDirectoryFileHolder.FullName, length);
relativePath = Shared.Models.Stateless.Methods.IPath.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)
foreach ((int g, string _, List<(string, Shared.Models.Property?)> collection, int r) in collectionFromJson)
{
if (!collection.Any())
continue;
items = new();
keySourceDirectories = new();
foreach ((string sourceDirectoryFile, Models.A_Property? property) in collection)
foreach ((string sourceDirectoryFile, Shared.Models.Property? property) in collection)
{
key = XPath.GetRelativePath(sourceDirectoryFile, length);
key = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFile, length);
relativePath = key[..^5];
if (!fileHolderKeyValuePairs.ContainsKey(key))
{
@ -204,7 +199,7 @@ public class Container
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)
else if (configuration.PropertiesChangedForProperty || 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));
@ -224,7 +219,7 @@ public class Container
items = new();
foreach (FileHolder sourceDirectoryFileHolder in sourceDirectoryFileHolderCollection)
{
relativePath = XPath.GetRelativePath(sourceDirectoryFileHolder.FullName, length);
relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFileHolder.FullName, length);
key = string.Concat(relativePath, ".json");
if (!fileHolderKeyValuePairs.ContainsKey(key))
continue;
@ -247,16 +242,15 @@ public class Container
return results;
}
public static List<Models.Container> GetContainers(Models.Configuration configuration, PropertyLogic propertyLogic)
public static List<Shared.Models.Container> GetContainers(Configuration configuration, A_Property propertyLogic)
{
List<Models.Container> results;
List<Shared.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;
List<(int g, string sourceDirectory, List<(string sourceDirectoryFile, Shared.Models.Property? property)> collection, int r)> collectionFromJson;
jsonCollection = GetJsonGroupCollection(configuration, propertyLogic, aPropertySingletonDirectory);
fileHolderGroupCollection = GetFileHolderGroupCollection(configuration, propertyLogic, searchPattern, topDirectories);
collectionFromJson = GetCollection(aPropertySingletonDirectory, jsonCollection);

View File

@ -1,24 +0,0 @@
namespace View_by_Distance.Property.Models.Stateless;
public interface IPath
{
string TestStatic_GetRelativePath(string path, int length);
static string GetRelativePath(string path, int length) => XPath.GetRelativePath(path, length);
bool TestStatic_DeleteEmptyDirectories(string rootDirectory);
static bool DeleteEmptyDirectories(string rootDirectory) => XPath.DeleteEmptyDirectories(rootDirectory);
List<string> TestStatic_GetDirectoryNames(string directory);
static List<string> GetDirectoryNames(string directory) => XPath.GetDirectoryNames(directory);
bool TestStatic_WriteAllText(string path, string contents, bool updateDateWhenMatches, bool compareBeforeWrite);
static bool WriteAllText(string path, string contents, bool updateDateWhenMatches, bool compareBeforeWrite, DateTime? updateToWhenMatches = null) => XPath.WriteAllText(path, contents, updateDateWhenMatches, compareBeforeWrite, updateToWhenMatches);
(int level, List<string> directories) TestStatic_Get(string rootDirectory, string sourceDirectory);
static (int level, List<string> directories) Get(string rootDirectory, string sourceDirectory) => XPath.Get(rootDirectory, sourceDirectory);
string TestStatic_GetDirectory(string sourceDirectory, int level, string directoryName);
static string GetDirectory(string sourceDirectory, int level, string directoryName) => XPath.GetDirectory(sourceDirectory, level, directoryName);
}

View File

@ -10,32 +10,32 @@ public interface IResult
public const string Collection = "[]";
public const string AllInOne = "_ _ _";
string TestStatic_GetRelativePath(Models.Configuration configuration, string path);
static string GetRelativePath(Models.Configuration configuration, string path)
string TestStatic_GetRelativePath(Configuration configuration, string path);
static string GetRelativePath(Configuration configuration, string path)
=> Result.GetRelativePath(configuration, path);
string TestStatic_GetResultsGroupDirectory(Models.Configuration configuration, string description);
static string GetResultsGroupDirectory(Models.Configuration configuration, string description)
string TestStatic_GetResultsGroupDirectory(Configuration configuration, string description);
static string GetResultsGroupDirectory(Configuration configuration, string description)
=> Result.GetResultsGroupDirectory(configuration, description);
string TestStatic_GetResultsDateGroupDirectory(Models.Configuration configuration, string description);
static string GetResultsDateGroupDirectory(Models.Configuration configuration, string description)
string TestStatic_GetResultsDateGroupDirectory(Configuration configuration, string description);
static string GetResultsDateGroupDirectory(Configuration configuration, string description)
=> Result.GetResultsDateGroupDirectory(configuration, description);
string TestStatic_GetResultsDateGroupDirectory(Models.Configuration configuration, string description, string jsonGroup);
static string GetResultsDateGroupDirectory(Models.Configuration configuration, string description, string jsonGroup)
string TestStatic_GetResultsDateGroupDirectory(Configuration configuration, string description, string jsonGroup);
static string GetResultsDateGroupDirectory(Configuration configuration, string description, string jsonGroup)
=> Result.GetResultsDateGroupDirectory(configuration, description, jsonGroup);
List<string> TestStatic_GetDirectoryInfoCollection(Models.Configuration configuration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription);
static List<string> GetDirectoryInfoCollection(Models.Configuration configuration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription, bool converted)
List<string> TestStatic_GetDirectoryInfoCollection(Configuration configuration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription);
static List<string> GetDirectoryInfoCollection(Configuration configuration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription, bool converted)
=> Result.GetDirectoryInfoCollection(configuration, sourceDirectory, dateGroupDirectory, contentDescription, singletonDescription, collectionDescription, converted);
string TestStatic_GetResultsFullGroupDirectory(Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel);
static string GetResultsFullGroupDirectory(Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel)
string TestStatic_GetResultsFullGroupDirectory(Configuration configuration, Model? model, PredictorModel? predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel);
static string GetResultsFullGroupDirectory(Configuration configuration, Model? model, PredictorModel? predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel)
=> Result.GetResultsFullGroupDirectory(configuration, model, predictorModel, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel);
List<string> TestStatic_GetDirectoryInfoCollection(Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription);
static List<string> GetDirectoryInfoCollection(Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription)
List<string> TestStatic_GetDirectoryInfoCollection(Configuration configuration, Model? model, PredictorModel? predictorModel, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription);
static List<string> GetDirectoryInfoCollection(Configuration configuration, Model? model, PredictorModel? predictorModel, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription)
=> Result.GetDirectoryInfoCollection(configuration, model, predictorModel, sourceDirectory, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel, contentDescription, singletonDescription, collectionDescription);
}

View File

@ -1,150 +0,0 @@
namespace View_by_Distance.Property.Models.Stateless;
internal class XPath
{
internal static string GetRelativePath(string path, int length)
{
string result = path[length..].Replace(@"\", "/");
return result;
}
internal static bool DeleteEmptyDirectories(string rootDirectory)
{
bool result;
if (!Directory.Exists(rootDirectory))
result = false;
else
{
string[] files;
string[] directories = Directory.GetDirectories(rootDirectory, "*", SearchOption.TopDirectoryOnly);
if (directories.Length > 0)
files = Array.Empty<string>();
else
files = Directory.GetFiles(rootDirectory, "*", SearchOption.AllDirectories);
if (directories.Length == 0 && files.Length == 0)
{
result = true;
Directory.Delete(rootDirectory);
}
else
{
result = false;
foreach (string directory in directories)
{
result = DeleteEmptyDirectories(directory);
if (result)
result = DeleteEmptyDirectories(directory);
}
if (files is null)
{
directories = Directory.GetDirectories(rootDirectory, "*", SearchOption.TopDirectoryOnly);
result = directories.Length == 0;
}
}
}
return result;
}
internal static bool WriteAllText(string path, string contents, bool updateDateWhenMatches, bool compareBeforeWrite, DateTime? updateToWhenMatches)
{
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 && updateDateWhenMatches)
{
if (updateToWhenMatches is null)
File.SetLastWriteTime(path, DateTime.Now);
else
File.SetLastWriteTime(path, updateToWhenMatches.Value);
}
}
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;
}
internal static List<string> GetDirectoryNames(string directory)
{
List<string> results = new();
string? checkDirectory = directory;
string? pathRoot = Path.GetPathRoot(directory);
string extension = Path.GetExtension(directory);
if (string.IsNullOrEmpty(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))
results.Add(Path.GetFileName(directory));
for (int i = 0; i < int.MaxValue; i++)
{
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == pathRoot)
break;
results.Add(Path.GetFileName(checkDirectory));
}
results.Add(pathRoot);
results.Reverse();
return results;
}
internal static (int level, List<string> directories) Get(string rootDirectory, string sourceDirectory)
{
int result = 0;
string? directory;
string? checkDirectory;
List<string> results = new();
checkDirectory = sourceDirectory;
for (int i = 0; i < int.MaxValue; i++)
{
result += 1;
directory = Path.GetFileName(checkDirectory);
if (string.IsNullOrEmpty(directory))
break;
results.Add(directory);
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (checkDirectory == rootDirectory)
break;
}
results.Reverse();
return new(result, results);
}
internal static string GetDirectory(string sourceDirectory, int level, string directoryName)
{
string result;
string? checkDirectory;
checkDirectory = Path.GetDirectoryName(sourceDirectory);
for (int i = 0; i < level; i++)
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory))
throw new Exception();
checkDirectory = Path.Combine(checkDirectory, directoryName);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
result = checkDirectory;
return result;
}
}

View File

@ -5,13 +5,13 @@ namespace View_by_Distance.Property.Models.Stateless;
internal class Result
{
internal static string GetRelativePath(Models.Configuration configuration, string path)
internal static string GetRelativePath(Configuration configuration, string path)
{
string result = XPath.GetRelativePath(path, configuration.RootDirectory.Length);
string result = Shared.Models.Stateless.Methods.IPath.GetRelativePath(path, configuration.RootDirectory.Length);
return result;
}
internal static string GetResultsGroupDirectory(Models.Configuration configuration, string description)
internal static string GetResultsGroupDirectory(Configuration configuration, string description)
{
string result = Path.Combine($"{configuration.RootDirectory} - Results", description.Replace("_", ") "));
if (!Directory.Exists(result))
@ -19,7 +19,7 @@ internal class Result
return result;
}
internal static string GetResultsDateGroupDirectory(Models.Configuration configuration, string description)
internal static string GetResultsDateGroupDirectory(Configuration configuration, string description)
{
string result = Path.Combine(GetResultsGroupDirectory(configuration, description), configuration.DateGroup);
if (!Directory.Exists(result))
@ -27,7 +27,7 @@ internal class Result
return result;
}
internal static string GetResultsDateGroupDirectory(Models.Configuration configuration, string description, string jsonGroup)
internal static string GetResultsDateGroupDirectory(Configuration configuration, string description, string jsonGroup)
{
string result = Path.Combine(GetResultsDateGroupDirectory(configuration, description), jsonGroup);
if (!Directory.Exists(result))
@ -35,7 +35,7 @@ internal class Result
return result;
}
internal static string GetResultsFullGroupDirectory(Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel)
internal static string GetResultsFullGroupDirectory(Configuration configuration, Model? model, PredictorModel? predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel)
{
string result = GetResultsDateGroupDirectory(configuration, description);
if (includeResizeGroup)
@ -64,59 +64,69 @@ internal class Result
return result;
}
internal static List<string> GetDirectoryInfoCollection(Models.Configuration configuration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription, bool converted)
private static void CheckContent(string dateGroupDirectory, string contentDescription, string result)
{
string checkDirectory;
checkDirectory = Path.Combine(dateGroupDirectory, IResult.Content, IResult.AllInOne);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
string contentDirectory = new(result.Replace("<>", IResult.Content));
if (!Directory.Exists(contentDirectory))
_ = Directory.CreateDirectory(contentDirectory);
checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("() - ", contentDescription));
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
}
private static void CheckSingleton(string dateGroupDirectory, string singletonDescription, bool converted, string result)
{
string checkDirectory;
checkDirectory = Path.Combine(dateGroupDirectory, IResult.Singleton, IResult.AllInOne);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
if (!converted)
{
string singletonDirectory = new(result.Replace("<>", IResult.Singleton));
if (!Directory.Exists(singletonDirectory))
_ = Directory.CreateDirectory(singletonDirectory);
}
checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("{} - ", singletonDescription));
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
}
private static void CheckCollection(string dateGroupDirectory, string collectionDescription, bool converted, string result)
{
string checkDirectory = Path.Combine(dateGroupDirectory, IResult.Collection, IResult.AllInOne);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
if (!converted)
{
string collectionDirectory = new(result.Replace("<>", IResult.Collection));
if (!Directory.Exists(collectionDirectory))
_ = Directory.CreateDirectory(collectionDirectory);
}
checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("[] - ", collectionDescription));
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
}
internal static List<string> GetDirectoryInfoCollection(Configuration configuration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription, bool converted)
{
List<string> results = new();
string checkDirectory;
string sourceDirectorySegment = GetRelativePath(configuration, sourceDirectory);
string result = string.Concat(Path.Combine(dateGroupDirectory, "<>"), sourceDirectorySegment);
if (!string.IsNullOrEmpty(contentDescription))
{
checkDirectory = Path.Combine(dateGroupDirectory, IResult.Content, IResult.AllInOne);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
string contentDirectory = new(result.Replace("<>", IResult.Content));
if (!Directory.Exists(contentDirectory))
_ = Directory.CreateDirectory(contentDirectory);
checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("() - ", contentDescription));
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
}
CheckContent(dateGroupDirectory, contentDescription, result);
if (!string.IsNullOrEmpty(singletonDescription))
{
checkDirectory = Path.Combine(dateGroupDirectory, IResult.Singleton, IResult.AllInOne);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
if (!converted)
{
string singletonDirectory = new(result.Replace("<>", IResult.Singleton));
if (!Directory.Exists(singletonDirectory))
_ = Directory.CreateDirectory(singletonDirectory);
}
checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("{} - ", singletonDescription));
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
}
CheckSingleton(dateGroupDirectory, singletonDescription, converted, result);
if (!string.IsNullOrEmpty(collectionDescription))
{
checkDirectory = Path.Combine(dateGroupDirectory, IResult.Collection, IResult.AllInOne);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
if (!converted)
{
string collectionDirectory = new(result.Replace("<>", IResult.Collection));
if (!Directory.Exists(collectionDirectory))
_ = Directory.CreateDirectory(collectionDirectory);
}
checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("[] - ", collectionDescription));
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
}
CheckCollection(dateGroupDirectory, collectionDescription, converted, result);
results.Add(result);
return results;
}
internal static List<string> GetDirectoryInfoCollection(Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription)
internal static List<string> GetDirectoryInfoCollection(Configuration configuration, Model? model, PredictorModel? predictorModel, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription)
{
List<string> results;
bool converted = false;

View File

@ -10,7 +10,7 @@
<PropertyGroup>
<PackageId>Phares.View.by.Distance.Property</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>5.0.402.104</Version>
<Version>6.0.100.1</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>