Init
This commit is contained in:
1
Property/.vscode/format-report.json
vendored
Normal file
1
Property/.vscode/format-report.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
[]
|
8
Property/.vscode/settings.json
vendored
Normal file
8
Property/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"dlib",
|
||||
"Exif",
|
||||
"nosj",
|
||||
"Serilog"
|
||||
]
|
||||
}
|
123
Property/Models/A_Property.cs
Normal file
123
Property/Models/A_Property.cs
Normal file
@ -0,0 +1,123 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using View_by_Distance.Shared.Models.Methods;
|
||||
|
||||
namespace View_by_Distance.Property.Models;
|
||||
|
||||
/// <summary>
|
||||
// A_Property
|
||||
/// </summary>
|
||||
public class A_Property : Shared.Models.Properties.IProperty, IProperty
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
[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)
|
||||
{
|
||||
_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;
|
||||
}
|
||||
|
||||
#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 override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<DateTime> GetDateTimes() => Stateless.A_Property.GetDateTimes(_CreationTime, _LastWriteTime, _DateTime, _DateTimeDigitized, _DateTimeOriginal, _GPSDateStamp);
|
||||
|
||||
public (bool?, string[]) IsWrongYear(string filteredSourceDirectoryFile, DateTime? minimumDateTime)
|
||||
{
|
||||
string[] results = Array.Empty<string>();
|
||||
bool? result = null;
|
||||
string year;
|
||||
string directoryName;
|
||||
string[] directorySegments;
|
||||
string? check = Path.GetPathRoot(filteredSourceDirectoryFile);
|
||||
string? pathRoot = Path.GetPathRoot(filteredSourceDirectoryFile);
|
||||
if (string.IsNullOrEmpty(pathRoot))
|
||||
throw new Exception();
|
||||
if (minimumDateTime.HasValue)
|
||||
year = minimumDateTime.Value.ToString("yyyy");
|
||||
else
|
||||
{
|
||||
List<DateTime> datetimes = GetDateTimes();
|
||||
year = datetimes.Min().ToString("yyyy");
|
||||
}
|
||||
for (int i = 0; i < int.MaxValue; i++)
|
||||
{
|
||||
check = Path.GetDirectoryName(check);
|
||||
if (string.IsNullOrEmpty(check) || check == pathRoot)
|
||||
break;
|
||||
directoryName = Path.GetFileName(check);
|
||||
directorySegments = directoryName.Split(' ');
|
||||
(result, results) = Stateless.A_Property.IsWrongYear(directorySegments, year);
|
||||
if (result.HasValue)
|
||||
break;
|
||||
}
|
||||
return new(result, results);
|
||||
}
|
||||
|
||||
}
|
48
Property/Models/Binder/Configuration.cs
Normal file
48
Property/Models/Binder/Configuration.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace View_by_Distance.Property.Models.Binder;
|
||||
|
||||
public class Configuration
|
||||
{
|
||||
|
||||
[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; }
|
||||
[Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; }
|
||||
[Display(Name = "Max Images In Directory For Top Level First Pass"), Required] public int? MaxImagesInDirectoryForTopLevelFirstPass { get; set; }
|
||||
[Display(Name = "Pattern"), Required] public string Pattern { get; set; }
|
||||
[Display(Name = "Populate Properties Id"), Required] public bool? PopulatePropertyId { get; set; }
|
||||
[Display(Name = "Properties Changed For Property"), Required] public bool? PropertiesChangedForProperty { get; set; }
|
||||
[Display(Name = "Property Content Collection Files"), Required] public string[] PropertyContentCollectionFiles { get; set; }
|
||||
[Display(Name = "Root Directory"), Required] public string RootDirectory { get; set; }
|
||||
[Display(Name = "Valid Image Format Extensions"), Required] public string[] ValidImageFormatExtensions { get; set; }
|
||||
[Display(Name = "Valid Metadata Extensions"), Required] public string[] ValidMetadataExtensions { get; set; }
|
||||
[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;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
101
Property/Models/Configuration.cs
Normal file
101
Property/Models/Configuration.cs
Normal file
@ -0,0 +1,101 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
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;
|
||||
|
||||
[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)
|
||||
{
|
||||
_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;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Update() => _RootDirectory = Path.GetFullPath(_RootDirectory);
|
||||
|
||||
public static void Verify(Configuration? propertyConfiguration)
|
||||
{
|
||||
if (propertyConfiguration is null)
|
||||
throw new Exception($"{nameof(propertyConfiguration)} must be set!");
|
||||
if (propertyConfiguration.ForcePropertyLastWriteTimeToCreationTime is null)
|
||||
throw new Exception($"{nameof(propertyConfiguration.ForcePropertyLastWriteTimeToCreationTime)} must be set!");
|
||||
if (propertyConfiguration.IgnoreExtensions is null || !propertyConfiguration.IgnoreExtensions.Any())
|
||||
throw new Exception($"{nameof(propertyConfiguration.IgnoreExtensions)} must be set!");
|
||||
if (propertyConfiguration.PopulatePropertyId is null)
|
||||
throw new Exception($"{nameof(propertyConfiguration.PopulatePropertyId)} must be set!");
|
||||
if (propertyConfiguration.PropertiesChangedForProperty is null)
|
||||
throw new Exception($"{nameof(propertyConfiguration.PropertiesChangedForProperty)} must be set!");
|
||||
if (propertyConfiguration.PropertyContentCollectionFiles is null)
|
||||
throw new Exception($"{nameof(propertyConfiguration.PropertyContentCollectionFiles)} must be set!");
|
||||
if (propertyConfiguration.ValidImageFormatExtensions is null || !propertyConfiguration.ValidImageFormatExtensions.Any())
|
||||
throw new Exception($"{nameof(propertyConfiguration.ValidImageFormatExtensions)} must be set!");
|
||||
if (propertyConfiguration.ValidMetadataExtensions is null || !propertyConfiguration.ValidMetadataExtensions.Any())
|
||||
throw new Exception($"{nameof(propertyConfiguration.ValidMetadataExtensions)} must be set!");
|
||||
if (propertyConfiguration.VerifyToSeason is null || !propertyConfiguration.VerifyToSeason.Any())
|
||||
throw new Exception($"{nameof(propertyConfiguration.VerifyToSeason)} must be set!");
|
||||
if (propertyConfiguration.WriteBitmapDataBytes is null)
|
||||
throw new Exception($"{nameof(propertyConfiguration.WriteBitmapDataBytes)} must be set!");
|
||||
if (Path.GetPathRoot(propertyConfiguration.RootDirectory) == propertyConfiguration.RootDirectory)
|
||||
throw new Exception($"{nameof(propertyConfiguration.RootDirectory)} should have at least one level!");
|
||||
if (propertyConfiguration is null)
|
||||
throw new Exception($"{nameof(propertyConfiguration)} must be set!");
|
||||
if (string.IsNullOrEmpty(propertyConfiguration.DateGroup))
|
||||
throw new Exception($"{nameof(propertyConfiguration.DateGroup)} must have a value!");
|
||||
if (string.IsNullOrEmpty(propertyConfiguration.FileNameDirectorySeparator))
|
||||
throw new Exception($"{nameof(propertyConfiguration.FileNameDirectorySeparator)} must have a value!");
|
||||
if (string.IsNullOrEmpty(propertyConfiguration.Pattern))
|
||||
throw new Exception($"{nameof(propertyConfiguration.Pattern)} must have a value!");
|
||||
if (string.IsNullOrEmpty(propertyConfiguration.RootDirectory) || !Directory.Exists(propertyConfiguration.RootDirectory))
|
||||
throw new Exception($"{nameof(propertyConfiguration.RootDirectory)} must have a value and exits!");
|
||||
}
|
||||
|
||||
}
|
32
Property/Models/Group.cs
Normal file
32
Property/Models/Group.cs
Normal file
@ -0,0 +1,32 @@
|
||||
namespace View_by_Distance.Property.Models;
|
||||
|
||||
public class Group
|
||||
{
|
||||
|
||||
protected readonly int _G;
|
||||
protected readonly string _SourceDirectory;
|
||||
protected readonly string[] _FilteredSourceDirectoryFiles;
|
||||
protected readonly int _R;
|
||||
protected readonly bool[] _ValidImageFormatExtentionCollection;
|
||||
protected readonly FileInfo?[] _PropertyFileInfoCollection;
|
||||
protected readonly A_Property?[] _PropertyCollection;
|
||||
public int G => _G;
|
||||
public string SourceDirectory => _SourceDirectory;
|
||||
public string[] FilteredSourceDirectoryFiles => _FilteredSourceDirectoryFiles;
|
||||
public int R => _R;
|
||||
public bool[] ValidImageFormatExtentionCollection => _ValidImageFormatExtentionCollection;
|
||||
public FileInfo?[] PropertyFileInfoCollection => _PropertyFileInfoCollection;
|
||||
public A_Property?[] PropertyCollection => _PropertyCollection;
|
||||
|
||||
public Group(int g, string sourceDirectory, string[] filteredSourceDirectoryFiles, int r)
|
||||
{
|
||||
_G = g;
|
||||
_SourceDirectory = sourceDirectory;
|
||||
_FilteredSourceDirectoryFiles = filteredSourceDirectoryFiles;
|
||||
_R = r;
|
||||
_ValidImageFormatExtentionCollection = Enumerable.Repeat(false, filteredSourceDirectoryFiles.Length).ToArray();
|
||||
_PropertyFileInfoCollection = Enumerable.Repeat<FileInfo?>(null, filteredSourceDirectoryFiles.Length).ToArray();
|
||||
_PropertyCollection = Enumerable.Repeat<A_Property?>(null, filteredSourceDirectoryFiles.Length).ToArray();
|
||||
}
|
||||
|
||||
}
|
780
Property/Models/PropertyLogic.cs
Normal file
780
Property/Models/PropertyLogic.cs
Normal file
@ -0,0 +1,780 @@
|
||||
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.Stateless;
|
||||
|
||||
namespace View_by_Distance.Property.Models;
|
||||
|
||||
public class PropertyLogic
|
||||
{
|
||||
|
||||
protected readonly Dictionary<int, int[]> _IndicesFromNew;
|
||||
protected readonly Dictionary<int, int[]> _IndicesFromOld;
|
||||
|
||||
public List<string> AngleBracketCollection { get; }
|
||||
public Dictionary<int, int[]> IndicesFromNew => _IndicesFromNew;
|
||||
public Dictionary<int, int[]> IndicesFromOld => _IndicesFromOld;
|
||||
|
||||
private readonly Serilog.ILogger? _Log;
|
||||
private readonly string[] _VerifyToSeason;
|
||||
private readonly int _MaxDegreeOfParallelism;
|
||||
private readonly ASCIIEncoding _ASCIIEncoding;
|
||||
private readonly Configuration _Configuration;
|
||||
private readonly List<string> _ExceptionsDirectories;
|
||||
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
|
||||
|
||||
public PropertyLogic(int maxDegreeOfParallelism, Configuration configuration, string[] verifyToSeason)
|
||||
{
|
||||
_Configuration = configuration;
|
||||
_ExceptionsDirectories = new();
|
||||
_VerifyToSeason = verifyToSeason;
|
||||
_ASCIIEncoding = new ASCIIEncoding();
|
||||
AngleBracketCollection = new List<string>();
|
||||
_Log = Serilog.Log.ForContext<A_Property>();
|
||||
_MaxDegreeOfParallelism = maxDegreeOfParallelism;
|
||||
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
|
||||
if (verifyToSeason is null)
|
||||
throw new Exception();
|
||||
string json;
|
||||
string fullPath;
|
||||
Dictionary<int, int[]>? indicesFromOld;
|
||||
List<KeyValuePair<int, int[]>>? collection;
|
||||
Dictionary<int, int[]> indicesFromNew = new();
|
||||
string? rootDirectoryParent = Path.GetDirectoryName(configuration.RootDirectory);
|
||||
if (string.IsNullOrEmpty(rootDirectoryParent))
|
||||
throw new Exception($"{nameof(rootDirectoryParent)} is null!");
|
||||
string keyValuePairsJsonFile = Path.Combine(rootDirectoryParent, "keyValuePairs-637864726339738801.json");
|
||||
if (!File.Exists(keyValuePairsJsonFile))
|
||||
indicesFromOld = new();
|
||||
else
|
||||
{
|
||||
json = File.ReadAllText(keyValuePairsJsonFile);
|
||||
indicesFromOld = JsonSerializer.Deserialize<Dictionary<int, int[]>>(json);
|
||||
if (indicesFromOld is null)
|
||||
throw new Exception($"{nameof(indicesFromOld)} is null!");
|
||||
}
|
||||
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 Exception($"{nameof(collection)} is null!");
|
||||
foreach (KeyValuePair<int, int[]> keyValuePair in collection)
|
||||
{
|
||||
if (indicesFromNew.ContainsKey(keyValuePair.Key))
|
||||
continue;
|
||||
indicesFromNew.Add(keyValuePair.Key, keyValuePair.Value);
|
||||
}
|
||||
}
|
||||
_IndicesFromNew = indicesFromNew;
|
||||
_IndicesFromOld = indicesFromOld;
|
||||
}
|
||||
|
||||
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 Exception($"{nameof(_Log)} is null!");
|
||||
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;
|
||||
}
|
||||
|
||||
#pragma warning disable CA1416
|
||||
|
||||
private A_Property GetImageProperty(string angleBracket, string filteredSourceDirectoryFile, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id, List<int> indices)
|
||||
{
|
||||
A_Property result;
|
||||
if (_Log is null)
|
||||
throw new Exception($"{nameof(_Log)} is null!");
|
||||
if (_Configuration.WriteBitmapDataBytes is null)
|
||||
throw new Exception($"{nameof(_Configuration.WriteBitmapDataBytes)} is null!");
|
||||
long ticks;
|
||||
byte[] bytes;
|
||||
string value;
|
||||
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;
|
||||
FileInfo fileInfo = new(filteredSourceDirectoryFile);
|
||||
long fileInfoLength = fileInfo.Length;
|
||||
DateTime creationTime = fileInfo.CreationTime;
|
||||
DateTime lastWriteTime = fileInfo.LastWriteTime;
|
||||
if (isValidMetadataExtensions)
|
||||
{
|
||||
dateTimeFormat = "ddd MMM dd HH:mm:ss yyyy";
|
||||
List<DateTime> dateTimes = GetMetadataDateTimesByPattern(dateTimeFormat, filteredSourceDirectoryFile);
|
||||
if (dateTimes.Any())
|
||||
dateTimeOriginal = dateTimes.Min();
|
||||
}
|
||||
else if (!isIgnoreExtension && isValidImageFormatExtension)
|
||||
{
|
||||
try
|
||||
{
|
||||
using Image image = Image.FromFile(filteredSourceDirectoryFile);
|
||||
if (populateId && (id is null || !indices.Any()))
|
||||
{
|
||||
using Bitmap bitmap = new(image);
|
||||
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("<>", "()"), Path.GetFileName(filteredSourceDirectoryFile)));
|
||||
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 (!_IndicesFromOld.ContainsKey(encodingHash))
|
||||
indices.Add(encodingHash);
|
||||
else
|
||||
indices.AddRange(_IndicesFromOld[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, " <", filteredSourceDirectoryFile, ">"));
|
||||
}
|
||||
}
|
||||
else
|
||||
dateTimeOriginal = null;
|
||||
result = new(creationTime, dateTime, dateTimeDigitized, dateTimeOriginal, fileInfoLength, gpsDateStamp, height, id, indices.ToArray(), lastWriteTime, make, model, orientation, width);
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning restore CA1416
|
||||
|
||||
private A_Property GetProperty(List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<string> parseExceptions, bool firstPass, string angleBracket, string filteredSourceDirectoryFile, FileInfo fileInfo, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions)
|
||||
{
|
||||
A_Property? result;
|
||||
if (_Configuration.ForcePropertyLastWriteTimeToCreationTime is null)
|
||||
throw new Exception($"{nameof(_Configuration.ForcePropertyLastWriteTimeToCreationTime)} is null!");
|
||||
if (_Configuration.PopulatePropertyId is null)
|
||||
throw new Exception($"{nameof(_Configuration.PopulatePropertyId)} is null!");
|
||||
if (_Configuration.PropertiesChangedForProperty is null)
|
||||
throw new Exception($"{nameof(_Configuration.PropertiesChangedForProperty)} is null!");
|
||||
string json;
|
||||
int? id = null;
|
||||
List<int> indices = new();
|
||||
bool hasWrongYearProperty = false;
|
||||
string[] changesFrom = new string[] { "B_Metadata" };
|
||||
bool populateId = !firstPass && _Configuration.PopulatePropertyId.Value;
|
||||
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 (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
json = File.ReadAllText(fileInfo.FullName);
|
||||
try
|
||||
{
|
||||
bool check = true;
|
||||
A_Property? property = JsonSerializer.Deserialize<A_Property>(json);
|
||||
if (!isIgnoreExtension && isValidImageFormatExtension && ((populateId && property?.Id is null) || property?.Width is null || property?.Height is null))
|
||||
{
|
||||
check = false;
|
||||
id = property?.Id;
|
||||
if (property is not null && property.Indices.Any())
|
||||
indices = property.Indices.ToList();
|
||||
property = GetImageProperty(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
|
||||
}
|
||||
if (!isIgnoreExtension && isValidImageFormatExtension && populateId && property is not null && !property.Indices.Any())
|
||||
{
|
||||
check = false;
|
||||
id = property?.Id;
|
||||
if (property is not null && property.Indices.Any())
|
||||
indices = property.Indices.ToList();
|
||||
property = GetImageProperty(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
|
||||
}
|
||||
if (!isIgnoreExtension && isValidImageFormatExtension && populateId && property is not null && property.LastWriteTime != new FileInfo(filteredSourceDirectoryFile).LastWriteTime)
|
||||
{
|
||||
check = false;
|
||||
id = null;
|
||||
indices.Clear();
|
||||
property = GetImageProperty(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
|
||||
}
|
||||
if (!isIgnoreExtension && isValidImageFormatExtension && property?.Width is not null && property?.Height is not null && property.Width.Value == property.Height.Value && File.Exists(filteredSourceDirectoryFile))
|
||||
{
|
||||
check = false;
|
||||
id = property?.Id;
|
||||
if (property is not null && property.Indices.Any())
|
||||
indices = property.Indices.ToList();
|
||||
property = GetImageProperty(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, 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 (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)
|
||||
{
|
||||
result = GetImageProperty(angleBracket, filteredSourceDirectoryFile, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, indices);
|
||||
json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions);
|
||||
if (populateId && IPath.WriteAllText(fileInfo.FullName, json, 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, 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(Group group)
|
||||
{
|
||||
bool result = false;
|
||||
if (_Log is null)
|
||||
throw new Exception($"{nameof(_Log)} is null!");
|
||||
int season;
|
||||
string[] matches;
|
||||
string deleteFile;
|
||||
bool? isWrongYear;
|
||||
string seasonName;
|
||||
DateTime dateTime;
|
||||
A_Property? property;
|
||||
string destinationFile;
|
||||
DateTime minimumDateTime;
|
||||
FileInfo? propertyFileInfo;
|
||||
string destinationDirectory;
|
||||
string[] sourceDirectorySegments;
|
||||
string filteredSourceDirectoryFile;
|
||||
FileInfo filteredSourceDirectoryFileInfo;
|
||||
DateTime directoryMaximumOfMinimumDateTime = DateTime.MinValue;
|
||||
for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++)
|
||||
{
|
||||
if (!group.ValidImageFormatExtentionCollection[i])
|
||||
continue;
|
||||
property = group.PropertyCollection[i];
|
||||
if (property is null)
|
||||
continue;
|
||||
minimumDateTime = Stateless.A_Property.GetMinimumDateTime(property);
|
||||
if (minimumDateTime > directoryMaximumOfMinimumDateTime)
|
||||
directoryMaximumOfMinimumDateTime = minimumDateTime;
|
||||
filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i];
|
||||
filteredSourceDirectoryFileInfo = new(filteredSourceDirectoryFile);
|
||||
if (minimumDateTime != filteredSourceDirectoryFileInfo.CreationTime)
|
||||
{
|
||||
(isWrongYear, matches) = property.IsWrongYear(filteredSourceDirectoryFile, minimumDateTime);
|
||||
if (isWrongYear is null || !isWrongYear.Value)
|
||||
dateTime = minimumDateTime;
|
||||
else
|
||||
{
|
||||
if (isWrongYear.HasValue && isWrongYear.Value)
|
||||
_Log.Information($"Wrong Year? <{filteredSourceDirectoryFile}>");
|
||||
if (!matches.Any())
|
||||
continue;
|
||||
if (!DateTime.TryParseExact(matches[0], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{ File.SetCreationTime(filteredSourceDirectoryFile, dateTime); }
|
||||
catch (Exception)
|
||||
{ }
|
||||
}
|
||||
if (!_VerifyToSeason.Contains(group.SourceDirectory))
|
||||
continue;
|
||||
propertyFileInfo = group.PropertyFileInfoCollection[i];
|
||||
if (propertyFileInfo is null)
|
||||
continue;
|
||||
sourceDirectorySegments = Path.GetFileName(group.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 == group.SourceDirectory)
|
||||
continue;
|
||||
if (!result)
|
||||
result = true;
|
||||
if (!Directory.Exists(destinationDirectory))
|
||||
_ = Directory.CreateDirectory(destinationDirectory);
|
||||
destinationFile = Path.Combine(destinationDirectory, filteredSourceDirectoryFileInfo.Name);
|
||||
if (File.Exists(destinationFile))
|
||||
{
|
||||
if (destinationFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
|
||||
destinationFile = Path.Combine(destinationDirectory, Path.ChangeExtension(filteredSourceDirectoryFileInfo.Name, ".jpeg"));
|
||||
else if (destinationFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
|
||||
destinationFile = Path.Combine(destinationDirectory, Path.ChangeExtension(filteredSourceDirectoryFileInfo.Name, ".jpg"));
|
||||
}
|
||||
if (File.Exists(destinationFile))
|
||||
{
|
||||
_Log.Information($"*** source <{filteredSourceDirectoryFile}>");
|
||||
_Log.Information($"*** destination <{destinationFile}>");
|
||||
if (propertyFileInfo.Exists)
|
||||
{
|
||||
deleteFile = Path.ChangeExtension(propertyFileInfo.FullName, ".delete");
|
||||
if (File.Exists(deleteFile))
|
||||
File.Delete(deleteFile);
|
||||
File.Move(propertyFileInfo.FullName, deleteFile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
File.Move(filteredSourceDirectoryFile, destinationFile);
|
||||
if (propertyFileInfo.Exists)
|
||||
{
|
||||
deleteFile = Path.ChangeExtension(propertyFileInfo.FullName, ".delete");
|
||||
if (File.Exists(deleteFile))
|
||||
File.Delete(deleteFile);
|
||||
File.Move(propertyFileInfo.FullName, deleteFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (directoryMaximumOfMinimumDateTime != DateTime.MinValue)
|
||||
{
|
||||
DirectoryInfo directoryInfo = new(group.SourceDirectory);
|
||||
if (directoryInfo.LastWriteTime != directoryMaximumOfMinimumDateTime)
|
||||
Directory.SetLastWriteTime(group.SourceDirectory, directoryMaximumOfMinimumDateTime);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void WriteGroup(Group group, string angleBracket)
|
||||
{
|
||||
if (!(from l in @group.PropertyCollection where l?.Width is null select true).Any())
|
||||
{
|
||||
string key;
|
||||
string json;
|
||||
string checkFile;
|
||||
A_Property? property;
|
||||
string checkDirectory;
|
||||
int sourceDirectoryLength = group.SourceDirectory.Length;
|
||||
List<KeyValuePair<string, A_Property>> propertyCollectionKeyValuePairs = new();
|
||||
JsonSerializerOptions writeIndentedJsonSerializerOptions = new() { WriteIndented = false };
|
||||
(int level, List<string> directories) = IPath.Get(_Configuration.RootDirectory, group.SourceDirectory);
|
||||
string fileName = string.Concat(string.Join(_Configuration.FileNameDirectorySeparator, directories), ".json");
|
||||
for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++)
|
||||
{
|
||||
property = group.PropertyCollection[i];
|
||||
if (property is null)
|
||||
continue;
|
||||
key = IPath.GetRelativePath(group.FilteredSourceDirectoryFiles[i], sourceDirectoryLength);
|
||||
propertyCollectionKeyValuePairs.Add(new KeyValuePair<string, A_Property>(key, property));
|
||||
}
|
||||
checkDirectory = IPath.GetDirectory(angleBracket, level, "[{}]");
|
||||
checkFile = Path.Combine(checkDirectory, fileName);
|
||||
if (File.Exists(checkFile))
|
||||
File.Move(checkFile, Path.Combine(checkDirectory, fileName));
|
||||
checkFile = Path.Combine(checkDirectory, fileName);
|
||||
json = JsonSerializer.Serialize(propertyCollectionKeyValuePairs, writeIndentedJsonSerializerOptions);
|
||||
_ = IPath.WriteAllText(checkFile, json, compareBeforeWrite: true);
|
||||
}
|
||||
}
|
||||
|
||||
private (List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, bool isValidImageFormatExtension, FileInfo propertyFileInfo, A_Property property) ParallelForWork(bool firstPass, string angleBracket, string sourceDirectory, string filteredSourceDirectoryFile)
|
||||
{
|
||||
List<string> parseExceptions = new();
|
||||
List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples = new();
|
||||
string extensionLowered = Path.GetExtension(filteredSourceDirectoryFile).ToLower();
|
||||
bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(extensionLowered);
|
||||
bool isValidImageFormatExtension = _Configuration.ValidImageFormatExtensions.Contains(extensionLowered);
|
||||
bool isIgnoreExtension = isValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(extensionLowered);
|
||||
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filteredSourceDirectoryFile);
|
||||
string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{fileNameWithoutExtension}{extensionLowered}");
|
||||
if (isValidImageFormatExtension && filteredSourceDirectoryFile.Length == filteredSourceDirectoryFileExtensionLowered.Length && filteredSourceDirectoryFile != filteredSourceDirectoryFileExtensionLowered)
|
||||
File.Move(filteredSourceDirectoryFile, filteredSourceDirectoryFileExtensionLowered);
|
||||
string without = Path.Combine(angleBracket.Replace("<>", "{}"), $"{fileNameWithoutExtension}.json");
|
||||
FileInfo propertyFileInfo = new(Path.Combine(angleBracket.Replace("<>", "{}"), $"{fileNameWithoutExtension}{extensionLowered}.json"));
|
||||
if (isValidImageFormatExtension && File.Exists(without))
|
||||
{
|
||||
File.Move(without, propertyFileInfo.FullName);
|
||||
propertyFileInfo.Refresh();
|
||||
}
|
||||
A_Property property = GetProperty(filteredSourceDirectoryFileTuples, parseExceptions, firstPass, angleBracket, filteredSourceDirectoryFile, propertyFileInfo, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions);
|
||||
return new(filteredSourceDirectoryFileTuples, isValidImageFormatExtension, propertyFileInfo, property);
|
||||
}
|
||||
|
||||
private int ParallelWork(bool firstPass, object @lock, long ticks, List<Tuple<string, DateTime>> sourceDirectoryChanges, int count, Group group, string angleBracket)
|
||||
{
|
||||
int result = 0;
|
||||
if (_Log is null)
|
||||
throw new Exception($"{nameof(_Log)} is null!");
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _MaxDegreeOfParallelism };
|
||||
int totalSeconds = (int)Math.Truncate(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
using (ProgressBar progressBar = new(group.FilteredSourceDirectoryFiles.Length, $"{group.G}) {group.R + 1:000} / {count:000} - {group.SourceDirectory} - {group.FilteredSourceDirectoryFiles.Length} file(s) - {totalSeconds} total second(s)", options))
|
||||
{
|
||||
_ = Parallel.For(0, group.FilteredSourceDirectoryFiles.Length, parallelOptions, i =>
|
||||
{
|
||||
try
|
||||
{
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
DateTime dateTime = DateTime.Now;
|
||||
(List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, bool isValidImageFormatExtension, FileInfo propertyFileInfo, A_Property property) = ParallelForWork(firstPass, angleBracket, group.SourceDirectory, group.FilteredSourceDirectoryFiles[i]);
|
||||
progressBar.Tick();
|
||||
if (_MaxDegreeOfParallelism < 2)
|
||||
ticks = LogDelta(ticks, nameof(PropertyLogic.ParallelForWork));
|
||||
lock (@lock)
|
||||
{
|
||||
group.PropertyCollection[i] = property;
|
||||
group.PropertyFileInfoCollection[i] = propertyFileInfo;
|
||||
if (isValidImageFormatExtension)
|
||||
group.ValidImageFormatExtentionCollection[i] = isValidImageFormatExtension;
|
||||
sourceDirectoryChanges.AddRange(from l in filteredSourceDirectoryFileTuples where l.Item2 > dateTime select l);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result += 1;
|
||||
_Log.Error(string.Concat(group.SourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex);
|
||||
if (result == group.FilteredSourceDirectoryFiles.Length)
|
||||
throw new Exception(string.Concat("All in [", group.SourceDirectory, "]failed!"));
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private string SetAngleBracketCollectionAndGetZero(Configuration configuration, string sourceDirectory)
|
||||
{
|
||||
string result;
|
||||
AngleBracketCollection.Clear();
|
||||
AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(configuration,
|
||||
sourceDirectory,
|
||||
nameof(A_Property),
|
||||
string.Empty,
|
||||
includeResizeGroup: false,
|
||||
includeModel: false,
|
||||
includePredictorModel: false,
|
||||
contentDescription: string.Empty,
|
||||
singletonDescription: "Properties for each image",
|
||||
collectionDescription: string.Empty));
|
||||
result = AngleBracketCollection[0];
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Group> GetParallelWork(Configuration configuration, List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection, bool firstPass, bool filterOnFirstPass)
|
||||
{
|
||||
List<Group> results = new();
|
||||
if (_Log is null)
|
||||
throw new Exception($"{nameof(_Log)} is null!");
|
||||
if (_Configuration.PopulatePropertyId is null)
|
||||
throw new Exception($"{nameof(_Configuration.PopulatePropertyId)} is null!");
|
||||
Group group;
|
||||
int exceptionCount;
|
||||
string angleBracket;
|
||||
object @lock = new();
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
string[] filteredSourceDirectoryFiles;
|
||||
List<Tuple<string, DateTime>> sourceDirectoryChanges = new();
|
||||
string propertyRoot = IResult.GetResultsGroupDirectory(configuration, nameof(A_Property));
|
||||
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection)
|
||||
{
|
||||
if (!topDirectories.Any())
|
||||
continue;
|
||||
sourceDirectoryChanges.Clear();
|
||||
if (firstPass && !filterOnFirstPass)
|
||||
filteredSourceDirectoryFiles = sourceDirectoryFiles;
|
||||
else
|
||||
filteredSourceDirectoryFiles = (from l in sourceDirectoryFiles where !_Configuration.IgnoreExtensions.Contains(Path.GetExtension(l)) select l).ToArray();
|
||||
if (!filteredSourceDirectoryFiles.Any())
|
||||
continue;
|
||||
group = new(g, sourceDirectory, filteredSourceDirectoryFiles, r);
|
||||
angleBracket = SetAngleBracketCollectionAndGetZero(configuration, sourceDirectory);
|
||||
exceptionCount = ParallelWork(firstPass, @lock, ticks, sourceDirectoryChanges, groupCollection.Count, group, angleBracket);
|
||||
if (exceptionCount != 0)
|
||||
_ExceptionsDirectories.Add(sourceDirectory);
|
||||
else
|
||||
results.Add(group);
|
||||
bool? anyFilesMoved;
|
||||
if (!firstPass || exceptionCount != 0)
|
||||
anyFilesMoved = null;
|
||||
else
|
||||
anyFilesMoved = AnyFilesMoved(group);
|
||||
if (exceptionCount != 0 || (anyFilesMoved is not null && anyFilesMoved.Value))
|
||||
results.Clear();
|
||||
if (exceptionCount == 0 && !firstPass && _Configuration.PopulatePropertyId.Value && (anyFilesMoved is null || !anyFilesMoved.Value))
|
||||
WriteGroup(group, angleBracket);
|
||||
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(". . .");
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<string> DoWork(Configuration configuration, List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection, bool firstPass)
|
||||
{
|
||||
List<string> results = new();
|
||||
_ExceptionsDirectories.Clear();
|
||||
_ = GetParallelWork(configuration, topDirectories, groupCollection, firstPass, filterOnFirstPass: false);
|
||||
results.AddRange(_ExceptionsDirectories);
|
||||
return results;
|
||||
}
|
||||
|
||||
public A_Property GetProperty(string angleBracket, string sourceDirectory, string filteredSourceDirectoryFile, List<Tuple<string, DateTime>> filteredSourceDirectoryFileTuples, List<string> parseExceptions, FileInfo fileInfo)
|
||||
{
|
||||
A_Property result;
|
||||
bool firstPass = false;
|
||||
string extensionLowered = Path.GetExtension(filteredSourceDirectoryFile).ToLower();
|
||||
bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(extensionLowered);
|
||||
bool isValidImageFormatExtension = _Configuration.ValidImageFormatExtensions.Contains(extensionLowered);
|
||||
bool isIgnoreExtension = isValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(extensionLowered);
|
||||
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filteredSourceDirectoryFile);
|
||||
string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{fileNameWithoutExtension}{extensionLowered}");
|
||||
if (isValidImageFormatExtension && filteredSourceDirectoryFile.Length == filteredSourceDirectoryFileExtensionLowered.Length && filteredSourceDirectoryFile != filteredSourceDirectoryFileExtensionLowered)
|
||||
File.Move(filteredSourceDirectoryFile, filteredSourceDirectoryFileExtensionLowered);
|
||||
string without = Path.Combine(angleBracket.Replace("<>", "{}"), $"{fileNameWithoutExtension}.json");
|
||||
FileInfo propertyFileInfo = new(Path.Combine(angleBracket.Replace("<>", "{}"), $"{fileNameWithoutExtension}{extensionLowered}.json"));
|
||||
if (isValidImageFormatExtension && File.Exists(without))
|
||||
{
|
||||
File.Move(without, propertyFileInfo.FullName);
|
||||
propertyFileInfo.Refresh();
|
||||
}
|
||||
result = GetProperty(filteredSourceDirectoryFileTuples, parseExceptions, firstPass, angleBracket, filteredSourceDirectoryFile, fileInfo, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions);
|
||||
return result;
|
||||
}
|
||||
|
||||
public (long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] GetPropertyIds(Configuration configuration, List<Group> groupCollection, bool saveToCollection)
|
||||
{
|
||||
List<(long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)> results = new();
|
||||
int level;
|
||||
string angleBracket;
|
||||
A_Property? property;
|
||||
string checkDirectory;
|
||||
List<string> directories;
|
||||
string propertyDirectory;
|
||||
foreach (Group group in groupCollection)
|
||||
{
|
||||
angleBracket = SetAngleBracketCollectionAndGetZero(configuration, 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.FilteredSourceDirectoryFiles.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();
|
||||
}
|
||||
|
||||
}
|
377
Property/Models/Stateless/A_Property.cs
Normal file
377
Property/Models/Stateless/A_Property.cs
Normal file
@ -0,0 +1,377 @@
|
||||
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<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> GetGroupCollection(string rootDirectory, string searchPattern, List<string> topDirectories, int maxImagesInDirectoryForTopLevelFirstPass = 50, bool reverse = false)
|
||||
{
|
||||
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> results = new();
|
||||
string? parentDirectory;
|
||||
string[] subDirectories;
|
||||
string[] sourceDirectoryFiles;
|
||||
List<string[]> fileCollections = new();
|
||||
if (!topDirectories.Any())
|
||||
{
|
||||
topDirectories.Add(rootDirectory);
|
||||
topDirectories.AddRange(from l in Directory.GetDirectories(rootDirectory, "*", SearchOption.TopDirectoryOnly) select Path.GetFullPath(l));
|
||||
}
|
||||
for (int g = 1; g < 5; g++)
|
||||
{
|
||||
if (g == 4)
|
||||
{
|
||||
for (int i = fileCollections.Count - 1; i > -1; i--)
|
||||
{
|
||||
parentDirectory = Path.GetDirectoryName(fileCollections[i][0]);
|
||||
if (string.IsNullOrEmpty(parentDirectory))
|
||||
continue;
|
||||
results.Add(new(g, parentDirectory, fileCollections[i], results.Count));
|
||||
fileCollections.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
else if (g == 2)
|
||||
{
|
||||
fileCollections = (from l in fileCollections orderby l.Length descending select l).ToList();
|
||||
for (int i = fileCollections.Count - 1; i > -1; i--)
|
||||
{
|
||||
if (fileCollections[i].Length > maxImagesInDirectoryForTopLevelFirstPass * g)
|
||||
break;
|
||||
parentDirectory = Path.GetDirectoryName(fileCollections[i][0]);
|
||||
if (string.IsNullOrEmpty(parentDirectory))
|
||||
continue;
|
||||
results.Add(new(g, parentDirectory, fileCollections[i], results.Count));
|
||||
fileCollections.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
else if (g == 3)
|
||||
{
|
||||
subDirectories = Directory.GetDirectories(rootDirectory, "*", SearchOption.AllDirectories);
|
||||
if (reverse)
|
||||
subDirectories = subDirectories.Reverse().ToArray();
|
||||
foreach (string subDirectory in subDirectories)
|
||||
{
|
||||
sourceDirectoryFiles = Directory.GetFiles(subDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||
if (!topDirectories.Contains(subDirectory))
|
||||
results.Add(new(g, subDirectory, sourceDirectoryFiles, results.Count));
|
||||
}
|
||||
}
|
||||
else if (g == 1)
|
||||
{
|
||||
sourceDirectoryFiles = Directory.GetFiles(rootDirectory, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass)
|
||||
fileCollections.Add(sourceDirectoryFiles);
|
||||
else
|
||||
results.Add(new(g, rootDirectory, sourceDirectoryFiles, results.Count));
|
||||
if (reverse)
|
||||
topDirectories.Reverse();
|
||||
subDirectories = topDirectories.ToArray();
|
||||
foreach (string subDirectory in subDirectories)
|
||||
{
|
||||
sourceDirectoryFiles = Directory.GetFiles(subDirectory, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass)
|
||||
fileCollections.Add(sourceDirectoryFiles);
|
||||
else
|
||||
{
|
||||
if (sourceDirectoryFiles.Any() || Directory.GetDirectories(subDirectory, "*", SearchOption.TopDirectoryOnly).Any())
|
||||
results.Add(new(g, subDirectory, sourceDirectoryFiles, results.Count));
|
||||
else if (searchPattern == "*")
|
||||
{
|
||||
sourceDirectoryFiles = Directory.GetFiles(subDirectory, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
foreach (string subFile in sourceDirectoryFiles)
|
||||
File.Delete(subFile);
|
||||
Directory.Delete(subDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
fileCollections.Reverse();
|
||||
}
|
||||
else
|
||||
throw new Exception();
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public static 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[] GetDirectoryRenameCollection(Models.Configuration configuration, string outputResolution, string bMetadata, string cResizeName)
|
||||
{
|
||||
List<string> results = new();
|
||||
string cResizeContentDirectory;
|
||||
string cResizeSingletonDirectory;
|
||||
string bMetadataSingletonDirectory;
|
||||
string aPropertySingletonDirectory;
|
||||
bMetadataSingletonDirectory = IResult.GetResultsDateGroupDirectory(configuration, bMetadata, "{}");
|
||||
if (Directory.Exists(bMetadataSingletonDirectory))
|
||||
results.Add(bMetadataSingletonDirectory);
|
||||
aPropertySingletonDirectory = IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
|
||||
if (Directory.Exists(aPropertySingletonDirectory))
|
||||
results.Add(aPropertySingletonDirectory);
|
||||
cResizeContentDirectory = Path.Combine(IResult.GetResultsFullGroupDirectory(configuration, cResizeName, outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()");
|
||||
if (Directory.Exists(cResizeContentDirectory))
|
||||
results.Add(cResizeContentDirectory);
|
||||
cResizeSingletonDirectory = Path.Combine(IResult.GetResultsFullGroupDirectory(configuration, cResizeName, outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "{}");
|
||||
if (Directory.Exists(cResizeSingletonDirectory))
|
||||
results.Add(cResizeSingletonDirectory);
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
public static void SearchForAbandonedFilesFull(string argZero, string rootDirectory, bool onlyJson)
|
||||
{
|
||||
bool check;
|
||||
string[] files;
|
||||
string moveFile;
|
||||
string extension;
|
||||
string? directory;
|
||||
const int last = 6;
|
||||
string searchPattern;
|
||||
string searchDirectory;
|
||||
int lessThan = last + 1;
|
||||
string? parentDirectory;
|
||||
DirectoryInfo directoryInfo;
|
||||
string fileNameWithoutExtension;
|
||||
IEnumerator<FileInfo> enumerator;
|
||||
List<string[]> fileMovePaths = new();
|
||||
List<string> toReviewFiles = new();
|
||||
int rootDirectoryLength = rootDirectory.Length;
|
||||
for (int i = 1; i < lessThan; i++)
|
||||
{
|
||||
files = i switch
|
||||
{
|
||||
1 => Directory.GetFiles(rootDirectory, "*.json", SearchOption.AllDirectories),
|
||||
2 => Directory.GetFiles(rootDirectory, "*.nosj", SearchOption.AllDirectories),
|
||||
3 => Directory.GetFiles(rootDirectory, "*.jpeg", SearchOption.AllDirectories),
|
||||
4 => Directory.GetFiles(rootDirectory, "*.tvs", SearchOption.AllDirectories),
|
||||
5 => Directory.GetFiles(rootDirectory, "*.png", SearchOption.AllDirectories),
|
||||
last => Directory.GetFiles(rootDirectory, "*", SearchOption.AllDirectories),
|
||||
_ => Array.Empty<string>()
|
||||
};
|
||||
foreach (string file in files)
|
||||
{
|
||||
extension = Path.GetExtension(file);
|
||||
if (extension == ".delete")
|
||||
continue;
|
||||
directory = Path.GetDirectoryName(file);
|
||||
if (string.IsNullOrEmpty(directory))
|
||||
continue;
|
||||
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
|
||||
if (file.EndsWith(" - R.png"))
|
||||
continue;
|
||||
if (fileNameWithoutExtension.Length < 1)
|
||||
continue;
|
||||
if (fileNameWithoutExtension[1..] != string.Concat(" - ", Path.GetFileNameWithoutExtension(directory)))
|
||||
{
|
||||
searchPattern = string.Concat(fileNameWithoutExtension, '*');
|
||||
searchDirectory = string.Concat(argZero, directory[rootDirectoryLength..]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fileNameWithoutExtension.Length < 4)
|
||||
continue;
|
||||
searchPattern = string.Concat(fileNameWithoutExtension[4..], '*');
|
||||
parentDirectory = Path.GetDirectoryName(directory);
|
||||
if (string.IsNullOrEmpty(parentDirectory))
|
||||
continue;
|
||||
searchDirectory = string.Concat(argZero, parentDirectory[rootDirectoryLength..]);
|
||||
}
|
||||
directoryInfo = new(searchDirectory);
|
||||
if (!directoryInfo.Exists)
|
||||
check = false;
|
||||
else
|
||||
{
|
||||
enumerator = directoryInfo.EnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly).GetEnumerator();
|
||||
check = enumerator.MoveNext();
|
||||
}
|
||||
if (check)
|
||||
continue;
|
||||
toReviewFiles.Add(file);
|
||||
}
|
||||
if (toReviewFiles.Any())
|
||||
throw new Exception("Need to fix property having the extension before .json extension!");
|
||||
foreach (string toReviewFile in toReviewFiles)
|
||||
{
|
||||
extension = Path.GetExtension(toReviewFile);
|
||||
if (extension == ".delete")
|
||||
continue;
|
||||
directory = Path.GetDirectoryName(toReviewFile);
|
||||
if (string.IsNullOrEmpty(directory))
|
||||
continue;
|
||||
moveFile = Path.Combine(directory, Path.ChangeExtension(toReviewFile, ".delete"));
|
||||
if (i == last)
|
||||
fileMovePaths.Add(new string[] { toReviewFile, moveFile });
|
||||
else if (extension is ".nosj")
|
||||
File.Delete(toReviewFile);
|
||||
else
|
||||
{
|
||||
if (File.Exists(moveFile))
|
||||
File.Delete(moveFile);
|
||||
File.Move(toReviewFile, moveFile);
|
||||
}
|
||||
}
|
||||
toReviewFiles.Clear();
|
||||
if (onlyJson)
|
||||
break;
|
||||
}
|
||||
if (fileMovePaths.Any())
|
||||
throw new Exception(string.Join(',', (from l in fileMovePaths select l[0]).ToArray()));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
42
Property/Models/Stateless/Configuration.cs
Normal file
42
Property/Models/Stateless/Configuration.cs
Normal file
@ -0,0 +1,42 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
24
Property/Models/Stateless/IPath.cs
Normal file
24
Property/Models/Stateless/IPath.cs
Normal file
@ -0,0 +1,24 @@
|
||||
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 compareBeforeWrite);
|
||||
static bool WriteAllText(string path, string contents, bool compareBeforeWrite) => XPath.WriteAllText(path, contents, compareBeforeWrite);
|
||||
|
||||
(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);
|
||||
|
||||
}
|
24
Property/Models/Stateless/IResult.cs
Normal file
24
Property/Models/Stateless/IResult.cs
Normal file
@ -0,0 +1,24 @@
|
||||
namespace View_by_Distance.Property.Models.Stateless;
|
||||
|
||||
public interface IResult
|
||||
{
|
||||
|
||||
string TestStatic_GetRelativePath(Models.Configuration configuration, string path);
|
||||
static string GetRelativePath(Models.Configuration configuration, string path) => Result.GetRelativePath(configuration, path);
|
||||
|
||||
string TestStatic_GetResultsGroupDirectory(Models.Configuration configuration, string description);
|
||||
static string GetResultsGroupDirectory(Models.Configuration configuration, string description) => Result.GetResultsGroupDirectory(configuration, description);
|
||||
|
||||
string TestStatic_GetResultsDateGroupDirectory(Models.Configuration configuration, string description);
|
||||
static string GetResultsDateGroupDirectory(Models.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) => Result.GetResultsDateGroupDirectory(configuration, description, jsonGroup);
|
||||
|
||||
string TestStatic_GetResultsFullGroupDirectory(Models.Configuration configuration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel);
|
||||
static string GetResultsFullGroupDirectory(Models.Configuration configuration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) => Result.GetResultsFullGroupDirectory(configuration, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel);
|
||||
|
||||
List<string> TestStatic_GetDirectoryInfoCollection(Models.Configuration configuration, 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, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) => Result.GetDirectoryInfoCollection(configuration, sourceDirectory, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel, contentDescription, singletonDescription, collectionDescription);
|
||||
|
||||
}
|
143
Property/Models/Stateless/Path.cs
Normal file
143
Property/Models/Stateless/Path.cs
Normal file
@ -0,0 +1,143 @@
|
||||
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 compareBeforeWrite)
|
||||
{
|
||||
bool result;
|
||||
string text;
|
||||
if (!compareBeforeWrite)
|
||||
result = true;
|
||||
else
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
text = string.Empty;
|
||||
else
|
||||
text = File.ReadAllText(path);
|
||||
result = text != contents;
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
if (path.Contains("()"))
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("{}") && !path.EndsWith(".json"))
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("[]") && !path.EndsWith(".json"))
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
|
||||
File.WriteAllText(path, contents);
|
||||
else
|
||||
File.WriteAllText(path, contents);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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 Exception($"{nameof(pathRoot)} is null!");
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
98
Property/Models/Stateless/Result.cs
Normal file
98
Property/Models/Stateless/Result.cs
Normal file
@ -0,0 +1,98 @@
|
||||
namespace View_by_Distance.Property.Models.Stateless;
|
||||
|
||||
internal class Result
|
||||
{
|
||||
|
||||
internal static string GetRelativePath(Models.Configuration configuration, string path)
|
||||
{
|
||||
string result = XPath.GetRelativePath(path, configuration.RootDirectory.Length);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string GetResultsGroupDirectory(Models.Configuration configuration, string description)
|
||||
{
|
||||
string result = Path.Combine($"{configuration.RootDirectory} - Results", description.Replace("_", ") "));
|
||||
if (!Directory.Exists(result))
|
||||
_ = Directory.CreateDirectory(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string GetResultsDateGroupDirectory(Models.Configuration configuration, string description)
|
||||
{
|
||||
string result = Path.Combine(GetResultsGroupDirectory(configuration, description), configuration.DateGroup);
|
||||
if (!Directory.Exists(result))
|
||||
_ = Directory.CreateDirectory(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string GetResultsDateGroupDirectory(Models.Configuration configuration, string description, string jsonGroup)
|
||||
{
|
||||
string result = Path.Combine(GetResultsDateGroupDirectory(configuration, description), jsonGroup);
|
||||
if (!Directory.Exists(result))
|
||||
_ = Directory.CreateDirectory(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string GetResultsFullGroupDirectory(Models.Configuration configuration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel)
|
||||
{
|
||||
string result = GetResultsDateGroupDirectory(configuration, description);
|
||||
if (includeResizeGroup)
|
||||
result = Path.Combine(result, outputResolution);
|
||||
if (includeModel && includePredictorModel)
|
||||
{
|
||||
string dateGroupDirectory = string.Concat(outputResolution.Replace(" ", string.Empty), " - ", "_Configuration.ModelName", " - ", "_Configuration.PredictorModelName");
|
||||
result = Path.Combine(result, dateGroupDirectory);
|
||||
}
|
||||
else if (includeModel)
|
||||
throw new Exception();
|
||||
else if (includePredictorModel)
|
||||
throw new Exception();
|
||||
if (!Directory.Exists(result))
|
||||
_ = Directory.CreateDirectory(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<string> GetDirectoryInfoCollection(Models.Configuration configuration, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription)
|
||||
{
|
||||
List<string> results = new();
|
||||
string result = string.Empty;
|
||||
string checkDirectory;
|
||||
string sourceDirectorySegment = GetRelativePath(configuration, sourceDirectory);
|
||||
string dateGroupDirectory = IResult.GetResultsFullGroupDirectory(configuration, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel);
|
||||
if (!string.IsNullOrEmpty(contentDescription))
|
||||
{
|
||||
result = string.Concat(Path.Combine(dateGroupDirectory, "<>"), sourceDirectorySegment);
|
||||
DirectoryInfo contentDirectoryInfo = new(result.Replace("<>", "()"));
|
||||
if (!contentDirectoryInfo.Exists)
|
||||
contentDirectoryInfo.Create();
|
||||
checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("() - ", contentDescription));
|
||||
if (!Directory.Exists(checkDirectory))
|
||||
_ = Directory.CreateDirectory(checkDirectory);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(singletonDescription))
|
||||
{
|
||||
result = string.Concat(Path.Combine(dateGroupDirectory, "<>"), sourceDirectorySegment);
|
||||
DirectoryInfo singletonDirectoryInfo = new(result.Replace("<>", "{}"));
|
||||
if (!singletonDirectoryInfo.Exists)
|
||||
singletonDirectoryInfo.Create();
|
||||
checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("{} - ", singletonDescription));
|
||||
if (!Directory.Exists(checkDirectory))
|
||||
_ = Directory.CreateDirectory(checkDirectory);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(collectionDescription))
|
||||
{
|
||||
result = string.Concat(Path.Combine(dateGroupDirectory, "<>"), sourceDirectorySegment);
|
||||
DirectoryInfo collectionDirectoryInfo = new(result.Replace("<>", "[]"));
|
||||
if (!collectionDirectoryInfo.Exists)
|
||||
collectionDirectoryInfo.Create();
|
||||
checkDirectory = Path.Combine(dateGroupDirectory, string.Concat("[] - ", collectionDescription));
|
||||
if (!Directory.Exists(checkDirectory))
|
||||
_ = Directory.CreateDirectory(checkDirectory);
|
||||
}
|
||||
if (string.IsNullOrEmpty(result))
|
||||
throw new Exception();
|
||||
results.Add(result);
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
10
Property/Models/Stateless/SerilogExtensionMethods.cs
Normal file
10
Property/Models/Stateless/SerilogExtensionMethods.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace View_by_Distance.Property.Models.Stateless;
|
||||
|
||||
internal static class SerilogExtensionMethods
|
||||
{
|
||||
|
||||
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
|
||||
|
||||
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
|
||||
|
||||
}
|
58
Property/Property.csproj
Normal file
58
Property/Property.csproj
Normal file
@ -0,0 +1,58 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>library</OutputType>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PackageId>Phares.View.by.Distance.Property</PackageId>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
<Version>5.0.402.104</Version>
|
||||
<Authors>Mike Phares</Authors>
|
||||
<Company>Phares</Company>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<IsWindows
|
||||
Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">
|
||||
true
|
||||
</IsWindows>
|
||||
<IsOSX
|
||||
Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
|
||||
true
|
||||
</IsOSX>
|
||||
<IsLinux
|
||||
Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">
|
||||
true
|
||||
</IsLinux>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(IsWindows)'=='true'">
|
||||
<DefineConstants>Windows</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(IsOSX)'=='true'">
|
||||
<DefineConstants>OSX</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(IsLinux)'=='true'">
|
||||
<DefineConstants>Linux</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
|
||||
<SupportedPlatform Include="browser" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MetadataExtractor" Version="2.7.1" />
|
||||
<PackageReference Include="ShellProgressBar" Version="5.1.0" />
|
||||
<PackageReference Include="Serilog" Version="2.10.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Reference in New Issue
Block a user