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

View File

@ -5,18 +5,23 @@
"ASPNETCORE", "ASPNETCORE",
"Barrick", "Barrick",
"bcdfghjklmnpqrstvwxyz", "bcdfghjklmnpqrstvwxyz",
"Bday",
"Beichler", "Beichler",
"Bohdi", "Bohdi",
"Cobertura",
"cref", "cref",
"CUDA", "CUDA",
"Dlib", "Dlib",
"DSCN",
"Exif", "Exif",
"Getα", "Getα",
"Greyscale", "Greyscale",
"jfif",
"mmod", "mmod",
"nosj", "nosj",
"paramref", "paramref",
"Phares", "Phares",
"Rects",
"resnet", "resnet",
"Serilog", "Serilog",
"Subfile", "Subfile",
@ -29,4 +34,5 @@
"files.exclude": { "files.exclude": {
"**/.git": false "**/.git": false
}, },
"coverage-gutters.coverageBaseDir": "./.vscode/ReportGenerator/Cobertura/*"
} }

View File

@ -22,7 +22,7 @@ public class Compare
private readonly List<(string Find, string Replace)> _RenameBFindReplace; private readonly List<(string Find, string Replace)> _RenameBFindReplace;
private readonly List<(string Find, string Replace)> _RenameCFindReplace; private readonly List<(string Find, string Replace)> _RenameCFindReplace;
private readonly List<(string Find, string Replace)> _SpellingFindReplace; private readonly List<(string Find, string Replace)> _SpellingFindReplace;
private readonly Dictionary<string, List<Tuple<string, A_Property>>> _FilePropertiesKeyValuePairs; private readonly Dictionary<string, List<Tuple<string, Shared.Models.Property>>> _FilePropertiesKeyValuePairs;
public Compare(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) public Compare(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{ {
@ -41,21 +41,21 @@ public class Compare
_IsEnvironment = isEnvironment; _IsEnvironment = isEnvironment;
_Log = Serilog.Log.ForContext<Compare>(); _Log = Serilog.Log.ForContext<Compare>();
_FileKeyValuePairs = new List<KeyValuePair<string, string>>(); _FileKeyValuePairs = new List<KeyValuePair<string, string>>();
_FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, A_Property>>>(); _FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, Shared.Models.Property>>>();
string searchPattern = "*"; string searchPattern = "*";
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
List<string> topDirectories = new(); List<string> topDirectories = new();
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection; List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection;
Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory); Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
Property.Models.Configuration.Verify(propertyConfiguration); Property.Models.Configuration.Verify(propertyConfiguration);
Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration);
Verify(configuration); Verify(configuration);
bool reverse = false;
Model? model = null; Model? model = null;
bool reverse = false;
string outputExtension = ".jpg";
PredictorModel? predictorModel = null; PredictorModel? predictorModel = null;
PropertyLogic propertyLogic = GetPropertyLogic(reverse, model, predictorModel); Map.Models.MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, propertyConfiguration);
if (propertyConfiguration.PopulatePropertyId is null) A_Property propertyLogic = GetPropertyLogic(reverse, model, outputExtension, predictorModel, mapLogic);
throw new NullReferenceException(nameof(propertyConfiguration.PopulatePropertyId));
foreach (string spelling in configuration.Spelling) foreach (string spelling in configuration.Spelling)
{ {
segments = spelling.Split('|'); segments = spelling.Split('|');
@ -114,7 +114,7 @@ public class Compare
if (PossiblyRename(topDirectories, groupCollection)) if (PossiblyRename(topDirectories, groupCollection))
{ {
topDirectories.Clear(); topDirectories.Clear();
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories); groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories);
if (appSettings.MaxDegreeOfParallelism < 2) if (appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection));
@ -123,7 +123,7 @@ public class Compare
if (PossiblyRenameB(topDirectories, groupCollection)) if (PossiblyRenameB(topDirectories, groupCollection))
{ {
topDirectories.Clear(); topDirectories.Clear();
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories); groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories);
if (appSettings.MaxDegreeOfParallelism < 2) if (appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection));
@ -132,7 +132,7 @@ public class Compare
if (PossiblyRenameC(topDirectories, groupCollection)) if (PossiblyRenameC(topDirectories, groupCollection))
{ {
topDirectories.Clear(); topDirectories.Clear();
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories); groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories);
if (appSettings.MaxDegreeOfParallelism < 2) if (appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection));
@ -141,7 +141,7 @@ public class Compare
if (PossiblyCorrect(topDirectories, groupCollection)) if (PossiblyCorrect(topDirectories, groupCollection))
{ {
topDirectories.Clear(); topDirectories.Clear();
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories); groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories);
if (appSettings.MaxDegreeOfParallelism < 2) if (appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection));
@ -154,14 +154,14 @@ public class Compare
if (dbFiles.Any()) if (dbFiles.Any())
{ {
topDirectories.Clear(); topDirectories.Clear();
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories); groupCollection = Property.Models.Stateless.Container.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories);
if (appSettings.MaxDegreeOfParallelism < 2) if (appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection)); ticks = LogDelta(ticks, nameof(Property.Models.Stateless.Container.GetGroupCollection));
} }
if (_IsEnvironment.Development && propertyConfiguration.PopulatePropertyId.Value && !propertyLogic.KeyValuePairs.Any()) if (_IsEnvironment.Development && propertyConfiguration.PopulatePropertyId && !mapLogic.KeyValuePairs.Any())
throw new Exception("Copy keyValuePairs-####.json file"); throw new Exception("Copy keyValuePairs-####.json file");
List<Container> containers = Property.Models.Stateless.A_Property.Get(propertyConfiguration, propertyLogic); List<Shared.Models.Container> containers = A_Property.Get(propertyConfiguration, propertyLogic);
if (!isSilent) if (!isSilent)
{ {
_Log.Information("First pass completed"); _Log.Information("First pass completed");
@ -203,7 +203,7 @@ public class Compare
_Log.Information(". . ."); _Log.Information(". . .");
} }
string aPropertyContentCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A_Property), "[()]"); string aPropertyContentCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A_Property), "[()]");
ThirdPassToMove(propertyConfiguration, model, predictorModel, propertyLogic, containers, aPropertyContentCollectionDirectory); ThirdPassToMove(propertyConfiguration, model, predictorModel, mapLogic, propertyLogic, containers, aPropertyContentCollectionDirectory);
if (!isSilent) if (!isSilent)
{ {
_Log.Information("Third pass completed"); _Log.Information("Third pass completed");
@ -215,7 +215,7 @@ public class Compare
} }
_Log.Information(". . ."); _Log.Information(". . .");
} }
FourthPassCreateWindowsShortcuts(propertyConfiguration, model, predictorModel, propertyLogic, containers, saveToCollection: false, keepAll: false); FourthPassCreateWindowsShortcuts(propertyConfiguration, model, predictorModel, mapLogic, propertyLogic, containers, saveToCollection: false, keepAll: false);
if (!isSilent) if (!isSilent)
{ {
_Log.Information("Fourth pass completed"); _Log.Information("Fourth pass completed");
@ -262,7 +262,7 @@ public class Compare
directorySegments = pathSegments[^1].Split(' '); directorySegments = pathSegments[^1].Split(' ');
if (!DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) if (!DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
throw new Exception("l"); throw new Exception("l");
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else if (pathSegments.Length == 1) else if (pathSegments.Length == 1)
@ -270,7 +270,7 @@ public class Compare
directorySegments = pathSegments[^1].Split(' '); directorySegments = pathSegments[^1].Split(' ');
if (DateTime.TryParseExact(directorySegments[^1], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) if (DateTime.TryParseExact(directorySegments[^1], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{ {
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else else
@ -284,7 +284,7 @@ public class Compare
directorySegments = pathSegments[0].Split(' '); directorySegments = pathSegments[0].Split(' ');
if (DateTime.TryParseExact(directorySegments[^1], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) if (DateTime.TryParseExact(directorySegments[^1], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{ {
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else else
@ -295,7 +295,7 @@ public class Compare
directorySegments = pathSegments[0].Split(' '); directorySegments = pathSegments[0].Split(' ');
if (DateTime.TryParseExact(directorySegments[^1], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) if (DateTime.TryParseExact(directorySegments[^1], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{ {
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else else
@ -305,22 +305,22 @@ public class Compare
{ {
if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(2)), "MMM yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(2)), "MMM yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{ {
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(2)), "MMM yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(2)), "MMM yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{ {
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else if (DateTime.TryParseExact(string.Concat(directorySegments[0][..3], ' ', directorySegments[1]), "MMM yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) else if (DateTime.TryParseExact(string.Concat(directorySegments[0][..3], ' ', directorySegments[1]), "MMM yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{ {
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(2)), "MMMM yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(2)), "MMMM yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{ {
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else else
@ -330,12 +330,12 @@ public class Compare
{ {
if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM dd yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM dd yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{ {
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM d yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM d yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{ {
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else else
@ -349,12 +349,12 @@ public class Compare
directorySegments = pathSegments[^1].Split(' '); directorySegments = pathSegments[^1].Split(' ');
if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM dd yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM dd yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{ {
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM d yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM d yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{ {
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2))); result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
} }
else else
@ -373,7 +373,7 @@ public class Compare
throw new NullReferenceException(nameof(configuration.Spelling)); throw new NullReferenceException(nameof(configuration.Spelling));
} }
private long LogDelta(long ticks, string methodName) private long LogDelta(long ticks, string? methodName)
{ {
long result; long result;
if (_Log is null) if (_Log is null)
@ -384,12 +384,12 @@ public class Compare
return result; return result;
} }
private PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel) private A_Property GetPropertyLogic(bool reverse, Model? model, string outputExtension, PredictorModel? predictorModel, Map.Models.MapLogic mapLogic)
{ {
PropertyLogic result; A_Property result;
if (_Configuration?.PropertyConfiguration is null) if (_Configuration?.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, reverse, model, predictorModel); result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, outputExtension, reverse, model, predictorModel);
string fromPrepareForOld = "34720-637858334555170379.tsv"; string fromPrepareForOld = "34720-637858334555170379.tsv";
string fromPrepareForOldFile = Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, fromPrepareForOld); string fromPrepareForOldFile = Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, fromPrepareForOld);
if (File.Exists(fromPrepareForOldFile)) if (File.Exists(fromPrepareForOldFile))
@ -400,12 +400,12 @@ public class Compare
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
lines = File.ReadAllLines(fromPrepareForOldFile); lines = File.ReadAllLines(fromPrepareForOldFile);
string resultsDirectory = $"{_Configuration.PropertyConfiguration.RootDirectory} - Results"; string resultsDirectory = $"{_Configuration.PropertyConfiguration.RootDirectory} - Results";
int[]? zeros = (from l in result.IndicesFromNew where l.Value.Any() select l.Value[0]).ToArray(); int[]? zeros = (from l in mapLogic.IndicesFromNew where l.Value.Any() select l.Value[0]).ToArray();
lines = (from l in result.IndicesFromNew select string.Concat(l.Key, '\t', string.Join('\t', l.Value))).ToArray(); lines = (from l in mapLogic.IndicesFromNew select string.Concat(l.Key, '\t', string.Join('\t', l.Value))).ToArray();
if (!Directory.Exists(resultsDirectory)) if (!Directory.Exists(resultsDirectory))
_ = Directory.CreateDirectory(resultsDirectory); _ = Directory.CreateDirectory(resultsDirectory);
File.WriteAllLines(Path.Combine(resultsDirectory, $"{ticks}.tsv"), lines); File.WriteAllLines(Path.Combine(resultsDirectory, $"{ticks}.tsv"), lines);
string json = JsonSerializer.Serialize(result.IndicesFromNew, new JsonSerializerOptions { WriteIndented = true }); string json = JsonSerializer.Serialize(mapLogic.IndicesFromNew, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(Path.Combine(resultsDirectory, $"{ticks}.json"), json); File.WriteAllText(Path.Combine(resultsDirectory, $"{ticks}.json"), json);
foreach (string line in lines) foreach (string line in lines)
{ {
@ -453,7 +453,7 @@ public class Compare
{ {
if (!_Configuration.DiffPropertyDirectory.EndsWith("{}")) if (!_Configuration.DiffPropertyDirectory.EndsWith("{}"))
throw new Exception("Invalid directory should end with {}!"); throw new Exception("Invalid directory should end with {}!");
diffRootDirectory = Property.Models.Stateless.A_Property.GetDiffRootDirectory(_Configuration.DiffPropertyDirectory); diffRootDirectory = Shared.Models.Stateless.Methods.IProperty.GetDiffRootDirectory(_Configuration.DiffPropertyDirectory);
} }
PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory); PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory);
if (string.IsNullOrEmpty(_Configuration.DiffPropertyDirectory) || !Directory.Exists(_Configuration.DiffPropertyDirectory)) if (string.IsNullOrEmpty(_Configuration.DiffPropertyDirectory) || !Directory.Exists(_Configuration.DiffPropertyDirectory))
@ -742,7 +742,7 @@ public class Compare
} }
} }
private void ThirdPassToMove(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, PropertyLogic propertyLogic, List<Container> containers, string aPropertyContentCollectionDirectory) private void ThirdPassToMove(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, Map.Models.MapLogic mapLogic, A_Property propertyLogic, List<Shared.Models.Container> containers, string aPropertyContentCollectionDirectory)
{ {
if (_Log is null) if (_Log is null)
throw new NullReferenceException(nameof(_Log)); throw new NullReferenceException(nameof(_Log));
@ -751,7 +751,7 @@ public class Compare
int stay = 0; int stay = 0;
string fileName; string fileName;
string id = " - Id"; string id = " - Id";
A_Property? property; Shared.Models.Property? property;
string? directoryName; string? directoryName;
ConsoleKey? consoleKey = null; ConsoleKey? consoleKey = null;
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
@ -773,7 +773,7 @@ public class Compare
continue; continue;
filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i]; filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i];
valueCollection.Add(new(property.Id.Value, property.Indices)); valueCollection.Add(new(property.Id.Value, property.Indices));
if (!propertyLogic.IndicesFromNew.ContainsKey(property.Id.Value)) if (!mapLogic.IndicesFromNew.ContainsKey(property.Id.Value))
stay += 1; stay += 1;
else if (!fileMoveCollection.Contains(filteredSourceDirectoryFile)) else if (!fileMoveCollection.Contains(filteredSourceDirectoryFile))
fileMoveCollection.Add(filteredSourceDirectoryFile); fileMoveCollection.Add(filteredSourceDirectoryFile);
@ -816,16 +816,16 @@ public class Compare
File.Move(fileMove, fileName); File.Move(fileMove, fileName);
} }
for (int i = 1; i < 4; i++) for (int i = 1; i < 4; i++)
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory);
} }
} }
private void FourthPassCreateWindowsShortcuts(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, PropertyLogic propertyLogic, List<Container> containers, bool saveToCollection, bool keepAll) private void FourthPassCreateWindowsShortcuts(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, Map.Models.MapLogic mapLogic, A_Property propertyLogic, List<Shared.Models.Container> containers, bool saveToCollection, bool keepAll)
{ {
if (_Log is null) if (_Log is null)
throw new NullReferenceException(nameof(_Log)); throw new NullReferenceException(nameof(_Log));
int stay = 0; int stay = 0;
A_Property? property; Shared.Models.Property? property;
ConsoleKey? consoleKey = null; ConsoleKey? consoleKey = null;
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
string filteredSourceDirectoryFile; string filteredSourceDirectoryFile;
@ -845,7 +845,7 @@ public class Compare
continue; continue;
filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i]; filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i];
valueCollection.Add(new(property.Id.Value, property.Indices)); valueCollection.Add(new(property.Id.Value, property.Indices));
if (!propertyLogic.IndicesFromNew.ContainsKey(property.Id.Value)) if (!mapLogic.IndicesFromNew.ContainsKey(property.Id.Value))
stay += 1; stay += 1;
else else
fileMoveCollection.Add(filteredSourceDirectoryFile); fileMoveCollection.Add(filteredSourceDirectoryFile);

View File

@ -10,7 +10,7 @@
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Compare</PackageId> <PackageId>Phares.View.by.Distance.Compare</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>5.0.402.104</Version> <Version>6.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -52,9 +52,10 @@
<PackageReference Include="System.Text.Json" Version="6.0.0" /> <PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Map\Map.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Property-Compare\Property-Compare.csproj" /> <ProjectReference Include="..\Property-Compare\Property-Compare.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="appsettings.Development.json"> <None Include="appsettings.Development.json">

View File

@ -79,28 +79,28 @@
"/zzz Phares Slides/Slides 2015-06-10/Magazine 01" "/zzz Phares Slides/Slides 2015-06-10/Magazine 01"
], ],
"Configuration": { "Configuration": {
"DateGroup": "2022-08-14", "DateGroup": "2022-08-22",
"DiffPropertyDirectory": "", "DiffPropertyDirectory": "",
"FileNameDirectorySeparator": ".Z.", "FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false, "ForcePropertyLastWriteTimeToCreationTime": false,
"MaxImagesInDirectoryForTopLevelFirstPass": 50, "MaxImagesInDirectoryForTopLevelFirstPass": 10,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": true, "PopulatePropertyId": true,
"PropertiesChangedForProperty": false, "PropertiesChangedForProperty": false,
"RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-08-14 - b756859b616424dc98b7742a64c15a8951632473 - III", "RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-08-22 - b756859b616424dc98b7742a64c15a8951632473 - III",
"WriteBitmapDataBytes": false, "WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF" ".GIF"
], ],
"PropertyContentCollectionFiles": [ "PropertyContentCollectionFiles": [
"/Images 2022-08-14 - b756859b616424dc98b7742a64c15a8951632473 - III - Results/A) Property/2022-08-14/[()]/637869381676042455.json", "/Images 2022-08-22 - b756859b616424dc98b7742a64c15a8951632473 - III - Results/A) Property/2022-08-22/[()]/637869381676042455.json",
"/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-08-14/[()]/637869733124119330.json", "/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-08-22/[()]/637869733124119330.json",
"/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-08-14/[()]/637869734240700328.json", "/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-08-22/[()]/637869734240700328.json",
"/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-08-14/[()]/637869734970730630.json", "/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-08-22/[()]/637869734970730630.json",
"/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-08-14/[()]/637869743752078399.json", "/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-08-22/[()]/637869743752078399.json",
"/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-08-14/[()]/637869744751177715.json", "/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-08-22/[()]/637869744751177715.json",
"/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-08-14/[()]/637869745134124462.json" "/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-08-22/[()]/637869745134124462.json"
], ],
"ValidImageFormatExtensions": [ "ValidImageFormatExtensions": [
".bmp", ".bmp",

View File

@ -50,11 +50,11 @@
"WorkingDirectoryName": "PharesApps", "WorkingDirectoryName": "PharesApps",
"Windows": { "Windows": {
"Configuration": { "Configuration": {
"DateGroup": "2022-08-14", "DateGroup": "2022-08-22",
"DiffPropertyDirectory": "", "DiffPropertyDirectory": "",
"FileNameDirectorySeparator": ".Z.", "FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false, "ForcePropertyLastWriteTimeToCreationTime": false,
"MaxImagesInDirectoryForTopLevelFirstPass": 50, "MaxImagesInDirectoryForTopLevelFirstPass": 10,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": true, "PopulatePropertyId": true,
"PropertiesChangedForProperty": false, "PropertiesChangedForProperty": false,
@ -94,13 +94,13 @@
".GIF" ".GIF"
], ],
"PropertyContentCollectionFiles": [ "PropertyContentCollectionFiles": [
"/Images 2022-08-14 - b756859b616424dc98b7742a64c15a8951632473 - III - Results/A) Property/2022-08-14/[()]/637869381676042455.json", "/Images 2022-08-22 - b756859b616424dc98b7742a64c15a8951632473 - III - Results/A) Property/2022-08-22/[()]/637869381676042455.json",
"/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-08-14/[()]/637869733124119330.json", "/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-08-22/[()]/637869733124119330.json",
"/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-08-14/[()]/637869734240700328.json", "/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-08-22/[()]/637869734240700328.json",
"/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-08-14/[()]/637869734970730630.json", "/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-08-22/[()]/637869734970730630.json",
"/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-08-14/[()]/637869743752078399.json", "/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-08-22/[()]/637869743752078399.json",
"/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-08-14/[()]/637869744751177715.json", "/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-08-22/[()]/637869744751177715.json",
"/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-08-14/[()]/637869745134124462.json" "/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-08-22/[()]/637869745134124462.json"
], ],
"ValidImageFormatExtensions": [ "ValidImageFormatExtensions": [
".bmp", ".bmp",

View File

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

View File

@ -19,7 +19,7 @@ public class DateGroup
private readonly IsEnvironment _IsEnvironment; private readonly IsEnvironment _IsEnvironment;
private readonly Models.Configuration _Configuration; private readonly Models.Configuration _Configuration;
private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs; private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs;
private readonly Dictionary<string, List<Tuple<string, A_Property>>> _FilePropertiesKeyValuePairs; private readonly Dictionary<string, List<Tuple<string, Shared.Models.Property>>> _FilePropertiesKeyValuePairs;
public DateGroup(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) public DateGroup(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{ {
@ -34,35 +34,34 @@ public class DateGroup
_Exceptions = new List<string>(); _Exceptions = new List<string>();
_Log = Serilog.Log.ForContext<DateGroup>(); _Log = Serilog.Log.ForContext<DateGroup>();
_FileKeyValuePairs = new List<KeyValuePair<string, string>>(); _FileKeyValuePairs = new List<KeyValuePair<string, string>>();
_FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, A_Property>>>(); _FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, Shared.Models.Property>>>();
Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory); Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
Property.Models.Configuration.Verify(propertyConfiguration); Property.Models.Configuration.Verify(propertyConfiguration);
Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration);
Verify(configuration); Verify(configuration);
bool reverse = false; bool reverse = false;
Model? model = null; Model? model = null;
PredictorModel? predictorModel = null;
_Configuration = configuration; _Configuration = configuration;
string outputExtension = ".jpg";
PredictorModel? predictorModel = null;
if (configuration.ByHash is null) if (configuration.ByHash is null)
throw new NullReferenceException(nameof(configuration.ByHash)); throw new NullReferenceException(nameof(configuration.ByHash));
if (configuration.ByCreateDateShortcut is null) if (configuration.ByCreateDateShortcut is null)
throw new NullReferenceException(nameof(configuration.ByCreateDateShortcut)); throw new NullReferenceException(nameof(configuration.ByCreateDateShortcut));
if (propertyConfiguration.PopulatePropertyId is null)
throw new NullReferenceException(nameof(propertyConfiguration.PopulatePropertyId));
if (!_IsEnvironment.Development) if (!_IsEnvironment.Development)
throw new Exception("This program only allows development environments!"); throw new Exception("This program only allows development environments!");
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
PropertyLogic propertyLogic = GetPropertyLogic(reverse, model, predictorModel); A_Property propertyLogic = GetPropertyLogic(reverse, model, outputExtension, predictorModel);
string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories); string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories);
foreach (string dbFile in dbFiles) foreach (string dbFile in dbFiles)
File.Delete(dbFile); File.Delete(dbFile);
if (true || appSettings.MaxDegreeOfParallelism < 2) if (true || appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(File.Delete)); ticks = LogDelta(ticks, nameof(File.Delete));
for (int i = 1; i < 10; i++) for (int i = 1; i < 10; i++)
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
if (true || appSettings.MaxDegreeOfParallelism < 2) if (true || appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.IPath.DeleteEmptyDirectories)); ticks = LogDelta(ticks, nameof(Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories));
List<Container> containers = Property.Models.Stateless.A_Property.Get(propertyConfiguration, propertyLogic); List<Shared.Models.Container> containers = A_Property.Get(propertyConfiguration, propertyLogic);
if (configuration.ByCreateDateShortcut.HasValue && configuration.ByCreateDateShortcut.Value) if (configuration.ByCreateDateShortcut.HasValue && configuration.ByCreateDateShortcut.Value)
CreateDateShortcut(propertyConfiguration, containers); CreateDateShortcut(propertyConfiguration, containers);
else else
@ -71,15 +70,15 @@ public class DateGroup
List<Property.Models.DirectoryInfo> directoryInfoCollection = new(); List<Property.Models.DirectoryInfo> directoryInfoCollection = new();
propertyLogic.ParallelWork(ticks, containers, firstPass: true); propertyLogic.ParallelWork(ticks, containers, firstPass: true);
if (appSettings.MaxDegreeOfParallelism < 2) if (appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(PropertyLogic.ParallelWork)); ticks = LogDelta(ticks, nameof(A_Property.ParallelWork));
if (propertyLogic.ExceptionsDirectories.Any()) if (propertyLogic.ExceptionsDirectories.Any())
throw new Exception(); throw new Exception();
if (propertyConfiguration.PopulatePropertyId.Value && (configuration.ByCreateDateShortcut.Value || configuration.ByHash.Value)) if (propertyConfiguration.PopulatePropertyId && (configuration.ByCreateDateShortcut.Value || configuration.ByHash.Value))
{ {
if (Property.Models.Stateless.A_Property.Any(containers)) if (Shared.Models.Stateless.Methods.IProperty.Any(containers))
propertyLogic.ParallelWork(ticks, containers, firstPass: false); propertyLogic.ParallelWork(ticks, containers, firstPass: false);
if (appSettings.MaxDegreeOfParallelism < 2) if (appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(PropertyLogic.ParallelWork)); ticks = LogDelta(ticks, nameof(A_Property.ParallelWork));
if (propertyLogic.ExceptionsDirectories.Any()) if (propertyLogic.ExceptionsDirectories.Any())
throw new Exception(); throw new Exception();
} }
@ -107,9 +106,9 @@ public class DateGroup
throw new NullReferenceException(nameof(configuration.KeepFullPath)); throw new NullReferenceException(nameof(configuration.KeepFullPath));
if (configuration?.PropertyConfiguration?.PopulatePropertyId is null) if (configuration?.PropertyConfiguration?.PopulatePropertyId is null)
throw new NullReferenceException(nameof(configuration.PropertyConfiguration.PopulatePropertyId)); throw new NullReferenceException(nameof(configuration.PropertyConfiguration.PopulatePropertyId));
if (configuration.PropertyConfiguration.PopulatePropertyId.Value && !configuration.ByCreateDateShortcut.Value && !configuration.ByHash.Value) if (configuration.PropertyConfiguration.PopulatePropertyId && !configuration.ByCreateDateShortcut.Value && !configuration.ByHash.Value)
throw new Exception("Change configuration!"); throw new Exception("Change configuration!");
if (!configuration.PropertyConfiguration.PopulatePropertyId.Value && configuration.ByHash.Value) if (!configuration.PropertyConfiguration.PopulatePropertyId && configuration.ByHash.Value)
throw new Exception("Change configuration!"); throw new Exception("Change configuration!");
if (configuration.ByCreateDateShortcut.Value && configuration.ByDay.Value && configuration.ByWeek.Value && configuration.BySeason.Value && configuration.ByHash.Value) if (configuration.ByCreateDateShortcut.Value && configuration.ByDay.Value && configuration.ByWeek.Value && configuration.BySeason.Value && configuration.ByHash.Value)
throw new Exception("Change configuration!"); throw new Exception("Change configuration!");
@ -147,7 +146,7 @@ public class DateGroup
return result; return result;
} }
private long LogDelta(long ticks, string methodName) private long LogDelta(long ticks, string? methodName)
{ {
long result; long result;
if (_Log is null) if (_Log is null)
@ -185,19 +184,19 @@ public class DateGroup
string weekOfYear; string weekOfYear;
string? directory; string? directory;
string seasonValue; string seasonValue;
A_Property? property;
string directoryName; string directoryName;
bool? propertyWrongYear; bool? propertyWrongYear;
string topDirectoryName; string topDirectoryName;
string[]? matches = null; string[]? matches = null;
string[] directorySegments; string[] directorySegments;
Shared.Models.Property? property;
DateTime? minimumDateTime = null; DateTime? minimumDateTime = null;
List<string> destinationCollection; List<string> destinationCollection;
List<string> directoryNames = new(); List<string> directoryNames = new();
FileHolder filteredSourceDirectoryFileHolder;
List<string> topDirectorySegments = new(); List<string> topDirectorySegments = new();
StringBuilder destinationDirectoryName = new(); StringBuilder destinationDirectoryName = new();
Calendar calendar = new CultureInfo("en-US").Calendar; Calendar calendar = new CultureInfo("en-US").Calendar;
Shared.Models.FileHolder filteredSourceDirectoryFileHolder;
for (int z = 1; z < 3; z++) for (int z = 1; z < 3; z++)
{ {
if (z == 1) if (z == 1)
@ -222,7 +221,7 @@ public class DateGroup
directoryName = Path.GetFileName(check); directoryName = Path.GetFileName(check);
directorySegments = directoryName.Split(' '); directorySegments = directoryName.Split(' ');
topDirectorySegments.AddRange(directorySegments); topDirectorySegments.AddRange(directorySegments);
(_, matches) = Property.Models.Stateless.A_Property.IsWrongYear(directorySegments, string.Empty); (_, matches) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(directorySegments, string.Empty);
if (matches.Any()) if (matches.Any())
break; break;
} }
@ -240,7 +239,7 @@ public class DateGroup
if (property is null) if (property is null)
continue; continue;
filteredSourceDirectoryFileHolder = group.SourceDirectoryFileHolderCollection[i]; filteredSourceDirectoryFileHolder = group.SourceDirectoryFileHolderCollection[i];
minimumDateTime = Property.Models.Stateless.A_Property.GetMinimumDateTime(property); minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
directory = filteredSourceDirectoryFileHolder.DirectoryName; directory = filteredSourceDirectoryFileHolder.DirectoryName;
if (string.IsNullOrEmpty(directory)) if (string.IsNullOrEmpty(directory))
continue; continue;
@ -261,7 +260,7 @@ public class DateGroup
flag = '='; flag = '=';
} }
} }
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(minimumDateTime.Value.DayOfYear); (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(minimumDateTime.Value.DayOfYear);
if ((from l in topDirectorySegments where l == "Christmas" select true).Any()) if ((from l in topDirectorySegments where l == "Christmas" select true).Any())
seasonValue = string.Empty; seasonValue = string.Empty;
else else
@ -326,12 +325,12 @@ public class DateGroup
return results; return results;
} }
private PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel) private A_Property GetPropertyLogic(bool reverse, Model? model, string outputExtension, PredictorModel? predictorModel)
{ {
PropertyLogic result; A_Property result;
if (_Configuration?.PropertyConfiguration is null) if (_Configuration?.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, reverse, model, predictorModel); result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, outputExtension, reverse, model, predictorModel);
return result; return result;
} }
@ -427,17 +426,17 @@ public class DateGroup
} }
_Log.Information($"Done moving back {moved} file(s)"); _Log.Information($"Done moving back {moved} file(s)");
for (int i = 1; i < 10; i++) for (int i = 1; i < 10; i++)
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory);
} }
private static void CreateDateShortcut(Property.Models.Configuration configuration, List<Container> containers) private static void CreateDateShortcut(Property.Models.Configuration configuration, List<Shared.Models.Container> containers)
{ {
string path; string path;
string fileName; string fileName;
string directory; string directory;
int selectedTotal; int selectedTotal;
const int minimum = 3; const int minimum = 3;
List<Item> selectedItems; List<Shared.Models.Item> selectedItems;
List<DateTime> dateTimes; List<DateTime> dateTimes;
DateTime? minimumDateTime; DateTime? minimumDateTime;
const int maximumHours = 24; const int maximumHours = 24;
@ -445,26 +444,26 @@ public class DateGroup
WindowsShortcut windowsShortcut; WindowsShortcut windowsShortcut;
TimeSpan threeStandardDeviationHigh; TimeSpan threeStandardDeviationHigh;
string aPropertyContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "()"); string aPropertyContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "()");
foreach (Container container in containers) foreach (Shared.Models.Container container in containers)
{ {
if (!container.Items.Any()) if (!container.Items.Any())
continue; continue;
selectedTotal = 0; selectedTotal = 0;
threeStandardDeviationHigh = Property.Models.Stateless.A_Property.GetThreeStandardDeviationHigh(minimum, container); threeStandardDeviationHigh = Shared.Models.Stateless.Methods.IProperty.GetThreeStandardDeviationHigh(minimum, container);
if (threeStandardDeviationHigh.TotalHours > maximumHours) if (threeStandardDeviationHigh.TotalHours > maximumHours)
threeStandardDeviationHigh = new(maximumHours, 0, 0); threeStandardDeviationHigh = new(maximumHours, 0, 0);
for (int i = 0; i < container.Items.Count; i++) for (int i = 0; i < container.Items.Count; i++)
{ {
(i, dateTimes, selectedItems) = Property.Models.Stateless.A_Property.Get(container, threeStandardDeviationHigh, i); (i, dateTimes, selectedItems) = Shared.Models.Stateless.Methods.IProperty.Get(container, threeStandardDeviationHigh, i);
selectedTotal += selectedItems.Count; selectedTotal += selectedItems.Count;
foreach (Item item in selectedItems) foreach (Shared.Models.Item item in selectedItems)
{ {
if (item.Property is null) if (item.Property is null)
continue; continue;
relativePathDirectory = Path.GetDirectoryName(item.RelativePath); relativePathDirectory = Path.GetDirectoryName(item.RelativePath);
if (string.IsNullOrEmpty(relativePathDirectory)) if (string.IsNullOrEmpty(relativePathDirectory))
continue; continue;
minimumDateTime = Property.Models.Stateless.A_Property.GetMinimumDateTime(item.Property); minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
if (minimumDateTime is null) if (minimumDateTime is null)
continue; continue;
path = Path.GetFullPath($"{configuration.RootDirectory}{item.RelativePath[..^5]}"); path = Path.GetFullPath($"{configuration.RootDirectory}{item.RelativePath[..^5]}");

View File

@ -39,41 +39,41 @@ public class Program
if (args is null) if (args is null)
throw new Exception("args is null!"); throw new Exception("args is null!");
#nullable disable #nullable disable
if (Property.Models.Stateless.A_Property.IsWrongYear("-".Split(' '), "2021").Item1.HasValue) if (IProperty.IsWrongYear("-".Split(' '), "2021").Item1.HasValue)
throw new Exception("-"); throw new Exception("-");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass".Split(' '), "2021").Item1.HasValue) if (IProperty.IsWrongYear("Christmass".Split(' '), "2021").Item1.HasValue)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass 2021".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Christmass 2021".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Christmass ~2021".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021.4".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Christmass ~2021.4".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass 2021".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Christmass 2021".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Christmass ~2021".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021.4".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Christmass ~2021.4".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("England 2017".Split(' '), "2017").Item1.Value) if (IProperty.IsWrongYear("England 2017".Split(' '), "2017").Item1.Value)
throw new Exception("England"); throw new Exception("England");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael".Split(' '), "2021").Item1.HasValue) if (IProperty.IsWrongYear("Logan Michael".Split(' '), "2021").Item1.HasValue)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael 2021".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Logan Michael 2021".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Logan Michael ~2021".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael 2021".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Logan Michael 2021".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Logan Michael ~2021".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item2[0] != "~2021.4") if (IProperty.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item2[0] != "~2021.4")
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Chelsea's 2nd Birthday =2014".Split(' '), "2014").Item1.Value) if (IProperty.IsWrongYear("Chelsea's 2nd Birthday =2014".Split(' '), "2014").Item1.Value)
throw new Exception("Chelsea"); throw new Exception("Chelsea");
#nullable restore #nullable restore
Shared.Models.Console console = new(); Shared.Models.Console console = new();

View File

@ -55,15 +55,15 @@
"ByHash": false, "ByHash": false,
"BySeason": false, "BySeason": false,
"ByWeek": false, "ByWeek": false,
"DateGroup": "2022-08-14", "DateGroup": "2022-08-22",
"FileNameDirectorySeparator": ".Z.", "FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false, "ForcePropertyLastWriteTimeToCreationTime": false,
"KeepFullPath": false, "KeepFullPath": false,
"MaxImagesInDirectoryForTopLevelFirstPass": 50, "MaxImagesInDirectoryForTopLevelFirstPass": 10,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": true, "PopulatePropertyId": true,
"PropertiesChangedForProperty": false, "PropertiesChangedForProperty": false,
"RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-08-14 - b756859b616424dc98b7742a64c15a8951632473 - III", "RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-08-22 - b756859b616424dc98b7742a64c15a8951632473 - III",
"WriteBitmapDataBytes": false, "WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -26,14 +26,14 @@ public class DlibDotNet
private readonly B_Metadata _Metadata; private readonly B_Metadata _Metadata;
private readonly E_Distance _Distance; private readonly E_Distance _Distance;
private readonly Serilog.ILogger? _Log; private readonly Serilog.ILogger? _Log;
private readonly D2_FaceParts _FaceParts;
private readonly AppSettings _AppSettings; private readonly AppSettings _AppSettings;
private readonly List<string> _Exceptions; private readonly List<string> _Exceptions;
private readonly IsEnvironment _IsEnvironment; private readonly IsEnvironment _IsEnvironment;
private readonly D2_FaceLandmarks _FaceLandmarks;
private readonly Models.Configuration _Configuration; private readonly Models.Configuration _Configuration;
private readonly bool _ArgZeroIsConfigurationRootDirectory; private readonly bool _ArgZeroIsConfigurationRootDirectory;
private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs; private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs;
private readonly Dictionary<string, List<Tuple<string, A_Property>>> _FilePropertiesKeyValuePairs; private readonly Dictionary<string, List<Tuple<string, Shared.Models.Property>>> _FilePropertiesKeyValuePairs;
public DlibDotNet(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) public DlibDotNet(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{ {
@ -44,8 +44,8 @@ public class DlibDotNet
_Exceptions = new List<string>(); _Exceptions = new List<string>();
_Log = Serilog.Log.ForContext<DlibDotNet>(); _Log = Serilog.Log.ForContext<DlibDotNet>();
_FileKeyValuePairs = new List<KeyValuePair<string, string>>(); _FileKeyValuePairs = new List<KeyValuePair<string, string>>();
_FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, A_Property>>>(); _FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, Shared.Models.Property>>>();
Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory); Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
_Log.Information(propertyConfiguration.RootDirectory); _Log.Information(propertyConfiguration.RootDirectory);
Property.Models.Configuration.Verify(propertyConfiguration); Property.Models.Configuration.Verify(propertyConfiguration);
Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration);
@ -57,7 +57,6 @@ public class DlibDotNet
_People = new A2_People(configuration); _People = new A2_People(configuration);
_Rename = new E3_Rename(configuration); _Rename = new E3_Rename(configuration);
_Distance = new E_Distance(configuration); _Distance = new E_Distance(configuration);
_FaceLandmarks = new D2_FaceLandmarks(configuration);
if (configuration.IgnoreExtensions is null) if (configuration.IgnoreExtensions is null)
throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
_Metadata = new(configuration.ForceMetadataLastWriteTimeToCreationTime, configuration.PropertiesChangedForMetadata); _Metadata = new(configuration.ForceMetadataLastWriteTimeToCreationTime, configuration.PropertiesChangedForMetadata);
@ -66,11 +65,8 @@ public class DlibDotNet
else else
argZero = Path.GetFullPath(propertyConfiguration.RootDirectory); argZero = Path.GetFullPath(propertyConfiguration.RootDirectory);
_ArgZeroIsConfigurationRootDirectory = propertyConfiguration.RootDirectory == argZero; _ArgZeroIsConfigurationRootDirectory = propertyConfiguration.RootDirectory == argZero;
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters) = C_Resize.GetTuple(configuration.OutputExtension, configuration.OutputQuality);
_Resize = new C_Resize(configuration.ForceResizeLastWriteTimeToCreationTime, configuration.OverrideForResizeImages, configuration.PropertiesChangedForResize, configuration.ValidResolutions, imageCodecInfo, encoderParameters);
_Log.Information(configuration.ModelDirectory); _Log.Information(configuration.ModelDirectory);
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(configuration); (Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(configuration);
_Faces = new D_Face(configuration, argZero, model, modelParameter, predictorModel);
if (!_ArgZeroIsConfigurationRootDirectory) if (!_ArgZeroIsConfigurationRootDirectory)
people = Array.Empty<Person>(); people = Array.Empty<Person>();
else else
@ -81,6 +77,18 @@ public class DlibDotNet
e2Navigate.Navigate(propertyConfiguration, model, predictorModel, configuration.OutputResolutions[0]); e2Navigate.Navigate(propertyConfiguration, model, predictorModel, configuration.OutputResolutions[0]);
_Log.Information(propertyConfiguration.RootDirectory); _Log.Information(propertyConfiguration.RootDirectory);
} }
{
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetGifLowQuality();
_FaceParts = new D2_FaceParts(configuration, imageCodecInfo, encoderParameters, filenameExtension);
}
{
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetPngLowQuality();
_Faces = new D_Face(configuration, argZero, model, modelParameter, predictorModel, imageCodecInfo, encoderParameters, filenameExtension);
}
{
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(configuration.OutputExtension, configuration.OutputQuality);
_Resize = new C_Resize(configuration.ForceResizeLastWriteTimeToCreationTime, configuration.OverrideForResizeImages, configuration.PropertiesChangedForResize, configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension);
}
if (!configuration.SkipSearch) if (!configuration.SkipSearch)
Search(propertyConfiguration, configuration.Reverse, model, predictorModel, argZero, people, isSilent); Search(propertyConfiguration, configuration.Reverse, model, predictorModel, argZero, people, isSilent);
if (_Exceptions.Count == 0 && _ArgZeroIsConfigurationRootDirectory) if (_Exceptions.Count == 0 && _ArgZeroIsConfigurationRootDirectory)
@ -90,13 +98,13 @@ public class DlibDotNet
foreach (string[] directoryCollection in directoryCollections) foreach (string[] directoryCollection in directoryCollections)
{ {
_Log.Information(string.Concat("Cleaning <", directoryCollection[0], ">")); _Log.Information(string.Concat("Cleaning <", directoryCollection[0], ">"));
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(directoryCollection[0]); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(directoryCollection[0]);
} }
string d2FaceLandmarksRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(D2_FaceLandmarks)); string d2FacePartsRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(D2_FaceParts));
_Log.Information(string.Concat("Cleaning <", d2FaceLandmarksRootDirectory, ">")); _Log.Information(string.Concat("Cleaning <", d2FacePartsRootDirectory, ">"));
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(d2FaceLandmarksRootDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(d2FacePartsRootDirectory);
if (appSettings.MaxDegreeOfParallelism < 2) if (appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.IPath.DeleteEmptyDirectories)); ticks = LogDelta(ticks, nameof(Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories));
} }
string message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}"; string message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}";
_Log.Information(message); _Log.Information(message);
@ -112,7 +120,7 @@ public class DlibDotNet
} }
} }
private long LogDelta(long ticks, string methodName) private long LogDelta(long ticks, string? methodName)
{ {
long result; long result;
if (_Log is null) if (_Log is null)
@ -245,16 +253,12 @@ public class DlibDotNet
throw new Exception("Input directory should be the source and not a resized directory!"); throw new Exception("Input directory should be the source and not a resized directory!");
} }
private void FullParallelForWork(PropertyLogic propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<A_Property> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<D_Face>> imageFaceCollections, string sourceDirectory, int index, Item item) private void FullParallelForWork(A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>> imageFaceCollections, string sourceDirectory, int index, Item item)
{ {
if (item.ImageFileHolder is null) if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder)); throw new NullReferenceException(nameof(item.ImageFileHolder));
if (_Configuration?.PropertyConfiguration is null) Shared.Models.Property property;
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); List<Face> faceCollection;
if (_Configuration.PropertyConfiguration.WriteBitmapDataBytes is null)
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration.WriteBitmapDataBytes));
A_Property property;
List<D_Face> faceCollection;
string original = "Original"; string original = "Original";
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
DateTime dateTime = DateTime.Now; DateTime dateTime = DateTime.Now;
@ -282,7 +286,7 @@ public class DlibDotNet
if (_AppSettings.MaxDegreeOfParallelism < 2) if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection)); ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection));
FileHolder resizedFileHolder = new(Path.Combine(_Resize.AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(item.ImageFileHolder.FullName))); FileHolder resizedFileHolder = new(Path.Combine(_Resize.AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(item.ImageFileHolder.FullName)));
item.SetResizedFileHolder(resizedFileHolder); item.SetResizedFileHolder(_Resize.FilenameExtension, resizedFileHolder);
imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, item); imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, item);
if (_AppSettings.MaxDegreeOfParallelism < 2) if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(C_Resize.GetResizeKeyValuePairs)); ticks = LogDelta(ticks, nameof(C_Resize.GetResizeKeyValuePairs));
@ -291,7 +295,7 @@ public class DlibDotNet
_Resize.SaveResizedSubfile(outputResolution, cResultsFullGroupDirectory, subFileTuples, item, original, imageResizeKeyValuePairs); _Resize.SaveResizedSubfile(outputResolution, cResultsFullGroupDirectory, subFileTuples, item, original, imageResizeKeyValuePairs);
if (_AppSettings.MaxDegreeOfParallelism < 2) if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(C_Resize.SaveResizedSubfile)); ticks = LogDelta(ticks, nameof(C_Resize.SaveResizedSubfile));
item.SetResizedFileHolder(FileHolder.Refresh(resizedFileHolder)); item.SetResizedFileHolder(_Resize.FilenameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(resizedFileHolder));
} }
else if (outputResolution == _Configuration.OutputResolutions[0] && false) else if (outputResolution == _Configuration.OutputResolutions[0] && false)
{ {
@ -315,11 +319,14 @@ public class DlibDotNet
_Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, item, faceCollection); _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, item, faceCollection);
if (_AppSettings.MaxDegreeOfParallelism < 2) if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(D_Face.SaveFaces)); ticks = LogDelta(ticks, nameof(D_Face.SaveFaces));
if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) int?[] normalizedPixelPercentageCollection = Shared.Models.Stateless.Methods.IFace.GetInts(faceCollection);
int normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count();
if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length || _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
{ {
_FaceLandmarks.SaveFaceLandmarkImages(d2ResultsFullGroupDirectory, sourceDirectory, subFileTuples, parseExceptions, item, faceCollection); bool saveRotated = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution);
_FaceParts.SaveFaceLandmarkImages(d2ResultsFullGroupDirectory, sourceDirectory, subFileTuples, parseExceptions, item, faceCollection, saveRotated);
if (_AppSettings.MaxDegreeOfParallelism < 2) if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(D2_FaceLandmarks.SaveFaceLandmarkImages)); ticks = LogDelta(ticks, nameof(D2_FaceParts.SaveFaceLandmarkImages));
} }
} }
lock (sourceDirectoryChanges) lock (sourceDirectoryChanges)
@ -333,7 +340,7 @@ public class DlibDotNet
} }
} }
private int FullParallelWork(long ticks, PropertyLogic propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<A_Property> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<D_Face>> faceCollections, int containersCount, Container container, Item[] filteredItems) private int FullParallelWork(long ticks, A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>> faceCollections, int containersCount, Container container, Item[] filteredItems)
{ {
int result = 0; int result = 0;
if (_Log is null) if (_Log is null)
@ -345,9 +352,9 @@ public class DlibDotNet
for (int i = 0; i < filteredItems.Length; i++) for (int i = 0; i < filteredItems.Length; i++)
{ {
faceCollections.Add(new()); faceCollections.Add(new());
propertyCollection.Add(null);
metadataCollection.Add(new()); metadataCollection.Add(new());
resizeKeyValuePairs.Add(new()); resizeKeyValuePairs.Add(new());
propertyCollection.Add(new());
propertyFileHolderCollection.Add(null); propertyFileHolderCollection.Add(null);
} }
} }
@ -401,7 +408,7 @@ public class DlibDotNet
if (metadataIdLines.Any()) if (metadataIdLines.Any())
{ {
text = string.Join(Environment.NewLine, from l in metadataIdLines orderby l.Id select l.Line); text = string.Join(Environment.NewLine, from l in metadataIdLines orderby l.Id select l.Line);
_ = Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, text, updateDateWhenMatches: true, compareBeforeWrite: true); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, text, updateDateWhenMatches: true, compareBeforeWrite: true);
} }
else else
{ {
@ -410,25 +417,23 @@ public class DlibDotNet
} }
} }
private void WriteGroup(Property.Models.Configuration configuration, PropertyLogic propertyLogic, List<A_Property> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<List<D_Face>> faceCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, string sourceDirectory, string outputResolution, Item[] filteredItems) private void WriteGroup(Property.Models.Configuration configuration, A_Property propertyLogic, Shared.Models.Property[] propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<List<Face>> faceCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, string sourceDirectory, string outputResolution, Item[] filteredItems)
{ {
if (configuration.PropertiesChangedForProperty is null)
throw new NullReferenceException(nameof(configuration.PropertiesChangedForProperty));
Item item; Item item;
string key; string key;
string json; string json;
string checkFile; string checkFile;
int sourceDirectoryLength = sourceDirectory.Length; int sourceDirectoryLength = sourceDirectory.Length;
_FilePropertiesKeyValuePairs.Add(sourceDirectory, new List<Tuple<string, A_Property>>()); _FilePropertiesKeyValuePairs.Add(sourceDirectory, new List<Tuple<string, Shared.Models.Property>>());
JsonSerializerOptions writeIndentedJsonSerializerOptions = new() { WriteIndented = false }; JsonSerializerOptions writeIndentedJsonSerializerOptions = new() { WriteIndented = false };
if (!(from l in propertyCollection where l?.Width is null select true).Any()) if (!(from l in propertyCollection where l?.Width is null select true).Any())
{ {
string checkDirectory; string checkDirectory;
List<KeyValuePair<string, List<D_Face>>> faceCollectionsKeyValuePairs = new(); List<KeyValuePair<string, List<Face>>> faceCollectionsKeyValuePairs = new();
List<KeyValuePair<string, A_Property>> propertyCollectionKeyValuePairs = new(); List<KeyValuePair<string, Shared.Models.Property>> propertyCollectionKeyValuePairs = new();
List<KeyValuePair<string, Dictionary<string, int[]>>> resizeKeyValuePairsCollections = new(); List<KeyValuePair<string, Dictionary<string, int[]>>> resizeKeyValuePairsCollections = new();
List<KeyValuePair<string, List<KeyValuePair<string, string>>>> metadataCollectionKeyValuePairs = new(); List<KeyValuePair<string, List<KeyValuePair<string, string>>>> metadataCollectionKeyValuePairs = new();
(int level, List<string> directories) = Property.Models.Stateless.IPath.Get(configuration.RootDirectory, sourceDirectory); (int level, List<string> directories) = Shared.Models.Stateless.Methods.IPath.Get(configuration.RootDirectory, sourceDirectory);
string fileName = string.Concat(string.Join(configuration.FileNameDirectorySeparator, directories), ".json"); string fileName = string.Concat(string.Join(configuration.FileNameDirectorySeparator, directories), ".json");
for (int i = 0; i < filteredItems.Length; i++) for (int i = 0; i < filteredItems.Length; i++)
{ {
@ -437,53 +442,53 @@ public class DlibDotNet
continue; continue;
if (item.ImageFileHolder is null) if (item.ImageFileHolder is null)
continue; continue;
key = Property.Models.Stateless.IPath.GetRelativePath(item.ImageFileHolder.FullName, sourceDirectoryLength); key = Shared.Models.Stateless.Methods.IPath.GetRelativePath(item.ImageFileHolder.FullName, sourceDirectoryLength);
_FileKeyValuePairs.Add(new KeyValuePair<string, string>(sourceDirectory, key)); _FileKeyValuePairs.Add(new KeyValuePair<string, string>(sourceDirectory, key));
_FilePropertiesKeyValuePairs[sourceDirectory].Add(new Tuple<string, A_Property>(key, propertyCollection[i])); _FilePropertiesKeyValuePairs[sourceDirectory].Add(new Tuple<string, Shared.Models.Property>(key, propertyCollection[i]));
faceCollectionsKeyValuePairs.Add(new KeyValuePair<string, List<D_Face>>(key, faceCollections[i])); faceCollectionsKeyValuePairs.Add(new KeyValuePair<string, List<Face>>(key, faceCollections[i]));
propertyCollectionKeyValuePairs.Add(new KeyValuePair<string, A_Property>(key, propertyCollection[i])); propertyCollectionKeyValuePairs.Add(new KeyValuePair<string, Shared.Models.Property>(key, propertyCollection[i]));
resizeKeyValuePairsCollections.Add(new KeyValuePair<string, Dictionary<string, int[]>>(key, resizeKeyValuePairs[i])); resizeKeyValuePairsCollections.Add(new KeyValuePair<string, Dictionary<string, int[]>>(key, resizeKeyValuePairs[i]));
metadataCollectionKeyValuePairs.Add(new KeyValuePair<string, List<KeyValuePair<string, string>>>(key, metadataCollection[i])); metadataCollectionKeyValuePairs.Add(new KeyValuePair<string, List<KeyValuePair<string, string>>>(key, metadataCollection[i]));
} }
if (propertyLogic.AngleBracketCollection.Any()) if (propertyLogic.AngleBracketCollection.Any())
{ {
checkDirectory = Property.Models.Stateless.IPath.GetDirectory(propertyLogic.AngleBracketCollection[0], level, "[{}]"); checkDirectory = Shared.Models.Stateless.Methods.IPath.GetDirectory(propertyLogic.AngleBracketCollection[0], level, "[{}]");
checkFile = Path.Combine(checkDirectory, fileName); checkFile = Path.Combine(checkDirectory, fileName);
if (File.Exists(checkFile)) if (File.Exists(checkFile))
File.Move(checkFile, Path.Combine(checkDirectory, fileName)); File.Move(checkFile, Path.Combine(checkDirectory, fileName));
checkFile = Path.Combine(checkDirectory, fileName); checkFile = Path.Combine(checkDirectory, fileName);
json = JsonSerializer.Serialize(propertyCollectionKeyValuePairs, writeIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(propertyCollectionKeyValuePairs, writeIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true);
} }
if (_Metadata.AngleBracketCollection.Any()) if (_Metadata.AngleBracketCollection.Any())
{ {
checkDirectory = Property.Models.Stateless.IPath.GetDirectory(_Metadata.AngleBracketCollection[0], level, "[{}]"); checkDirectory = Shared.Models.Stateless.Methods.IPath.GetDirectory(_Metadata.AngleBracketCollection[0], level, "[{}]");
checkFile = Path.Combine(checkDirectory, fileName); checkFile = Path.Combine(checkDirectory, fileName);
if (File.Exists(checkFile)) if (File.Exists(checkFile))
File.Move(checkFile, Path.Combine(checkDirectory, fileName)); File.Move(checkFile, Path.Combine(checkDirectory, fileName));
checkFile = Path.Combine(checkDirectory, fileName); checkFile = Path.Combine(checkDirectory, fileName);
json = JsonSerializer.Serialize(metadataCollectionKeyValuePairs, writeIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(metadataCollectionKeyValuePairs, writeIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true);
} }
if (_Resize.AngleBracketCollection.Any()) if (_Resize.AngleBracketCollection.Any())
{ {
checkDirectory = Property.Models.Stateless.IPath.GetDirectory(_Resize.AngleBracketCollection[0], level, "[{}]"); checkDirectory = Shared.Models.Stateless.Methods.IPath.GetDirectory(_Resize.AngleBracketCollection[0], level, "[{}]");
checkFile = Path.Combine(checkDirectory, fileName); checkFile = Path.Combine(checkDirectory, fileName);
if (File.Exists(checkFile)) if (File.Exists(checkFile))
File.Move(checkFile, Path.Combine(checkDirectory, fileName)); File.Move(checkFile, Path.Combine(checkDirectory, fileName));
checkFile = Path.Combine(checkDirectory, fileName); checkFile = Path.Combine(checkDirectory, fileName);
json = JsonSerializer.Serialize(resizeKeyValuePairsCollections, writeIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(resizeKeyValuePairsCollections, writeIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true);
} }
if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution) && _Faces.AngleBracketCollection.Any()) if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution) && _Faces.AngleBracketCollection.Any())
{ {
checkDirectory = Property.Models.Stateless.IPath.GetDirectory(_Faces.AngleBracketCollection[0], level, "[{}]"); checkDirectory = Shared.Models.Stateless.Methods.IPath.GetDirectory(_Faces.AngleBracketCollection[0], level, "[{}]");
checkFile = Path.Combine(checkDirectory, fileName); checkFile = Path.Combine(checkDirectory, fileName);
if (File.Exists(checkFile)) if (File.Exists(checkFile))
File.Move(checkFile, Path.Combine(checkDirectory, fileName)); File.Move(checkFile, Path.Combine(checkDirectory, fileName));
checkFile = Path.Combine(checkDirectory, fileName); checkFile = Path.Combine(checkDirectory, fileName);
json = JsonSerializer.Serialize(faceCollectionsKeyValuePairs, writeIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(faceCollectionsKeyValuePairs, writeIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true);
} }
} }
} }
@ -499,7 +504,7 @@ public class DlibDotNet
string dResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( string dResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
configuration, model, predictorModel, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); configuration, model, predictorModel, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true);
string d2ResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( string d2ResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
configuration, model, predictorModel, nameof(D2_FaceLandmarks), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); configuration, model, predictorModel, nameof(D2_FaceParts), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true);
string eResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( string eResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true);
string zResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( string zResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
@ -507,7 +512,7 @@ public class DlibDotNet
return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory, zResultsFullGroupDirectory); return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory, zResultsFullGroupDirectory);
} }
private void SetAngleBracketCollections(Property.Models.Configuration configuration, PropertyLogic propertyLogic, string outputResolution, Container container, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory) private void SetAngleBracketCollections(Property.Models.Configuration configuration, A_Property propertyLogic, string outputResolution, Container container, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory)
{ {
_Faces.AngleBracketCollection.Clear(); _Faces.AngleBracketCollection.Clear();
_Resize.AngleBracketCollection.Clear(); _Resize.AngleBracketCollection.Clear();
@ -544,7 +549,7 @@ public class DlibDotNet
converted: true)); converted: true));
} }
private void FullDoWork(bool isSilent, string argZero, Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, long ticks, Dictionary<string, List<Person>> peopleCollection, PropertyLogic propertyLogic, List<Container> containers) private void FullDoWork(string argZero, Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, long ticks, Map.Models.MapLogic mapLogic, A_Property propertyLogic, List<Container> containers)
{ {
if (_Log is null) if (_Log is null)
throw new NullReferenceException(nameof(_Log)); throw new NullReferenceException(nameof(_Log));
@ -559,11 +564,12 @@ public class DlibDotNet
string eResultsFullGroupDirectory; string eResultsFullGroupDirectory;
string zResultsFullGroupDirectory; string zResultsFullGroupDirectory;
string d2ResultsFullGroupDirectory; string d2ResultsFullGroupDirectory;
List<List<D_Face>> faceCollections = new(); List<List<Face>> faceCollections = new();
List<A_Property> propertyCollection = new(); Shared.Models.Property[] propertyCollection;
List<FileHolder?> propertyFileHolderCollection = new(); List<FileHolder?> propertyFileHolderCollection = new();
List<Dictionary<string, int[]>> resizeKeyValuePairs = new(); List<Dictionary<string, int[]>> resizeKeyValuePairs = new();
List<Tuple<string, DateTime>> sourceDirectoryChanges = new(); List<Tuple<string, DateTime>> sourceDirectoryChanges = new();
List<Shared.Models.Property?> nullablePropertyCollection = new();
List<List<KeyValuePair<string, string>>> metadataCollection = new(); List<List<KeyValuePair<string, string>>> metadataCollection = new();
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, nameof(A_Property)); string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, nameof(A_Property));
@ -583,28 +589,29 @@ public class DlibDotNet
continue; continue;
faceCollections.Clear(); faceCollections.Clear();
metadataCollection.Clear(); metadataCollection.Clear();
propertyCollection.Clear();
resizeKeyValuePairs.Clear(); resizeKeyValuePairs.Clear();
sourceDirectoryChanges.Clear(); sourceDirectoryChanges.Clear();
nullablePropertyCollection.Clear();
propertyFileHolderCollection.Clear(); propertyFileHolderCollection.Clear();
SetAngleBracketCollections(configuration, propertyLogic, outputResolution, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory); SetAngleBracketCollections(configuration, propertyLogic, outputResolution, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory);
exceptionCount = FullParallelWork(ticks, propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, faceCollections, containers.Count, container, filteredItems); exceptionCount = FullParallelWork(ticks, propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, nullablePropertyCollection, metadataCollection, resizeKeyValuePairs, faceCollections, containers.Count, container, filteredItems);
#pragma warning disable #pragma warning disable
ids = (from l in filteredItems where l.Property?.Id is not null select l.Property.Id.Value).ToArray(); ids = (from l in filteredItems where l.Property?.Id is not null select l.Property.Id.Value).ToArray();
#pragma warning restore #pragma warning restore
distinctCount = ids.Distinct().Count(); distinctCount = ids.Distinct().Count();
if (ids.Length != distinctCount) if (ids.Length != distinctCount)
_Log.Information($"{ids.Length} != {distinctCount} <{container.SourceDirectory}>"); _Log.Information($"{ids.Length} != {distinctCount} <{container.SourceDirectory}>");
if (metadataCollection.Count != filteredItems.Length || propertyCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || faceCollections.Count != filteredItems.Length) if (metadataCollection.Count != filteredItems.Length || nullablePropertyCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || faceCollections.Count != filteredItems.Length)
throw new Exception("Counts don't match!"); throw new Exception("Counts don't match!");
if (exceptionCount != 0) if (exceptionCount != 0)
_Exceptions.Add(container.SourceDirectory); _Exceptions.Add(container.SourceDirectory);
for (int i = 0; i < faceCollections.Count; i++) for (int i = 0; i < faceCollections.Count; i++)
filteredItems[i].Faces.AddRange(from l in faceCollections[i] select l); filteredItems[i].Faces.AddRange(from l in faceCollections[i] select l);
propertyCollection = (from l in nullablePropertyCollection where l is not null select l).ToArray();
if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0) if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0)
WriteGroup(configuration, propertyLogic, propertyCollection, metadataCollection, faceCollections, resizeKeyValuePairs, container.SourceDirectory, outputResolution, filteredItems); WriteGroup(configuration, propertyLogic, propertyCollection, metadataCollection, faceCollections, resizeKeyValuePairs, container.SourceDirectory, outputResolution, filteredItems);
if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0 && outputResolution == _Configuration.OutputResolutions[0]) if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0 && outputResolution == _Configuration.OutputResolutions[0])
propertyLogic.AddToPropertyLogicAllCollection(filteredItems); mapLogic.AddToMapLogicAllCollection(filteredItems);
if (exceptionCount == 0 && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) if (exceptionCount == 0 && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution))
_Distance.LoadOrCreateThenSaveDistanceResults(configuration, eResultsFullGroupDirectory, container.SourceDirectory, outputResolution, sourceDirectoryChanges, filteredItems); _Distance.LoadOrCreateThenSaveDistanceResults(configuration, eResultsFullGroupDirectory, container.SourceDirectory, outputResolution, sourceDirectoryChanges, filteredItems);
if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any()) if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any())
@ -633,15 +640,6 @@ public class DlibDotNet
} }
} }
private PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel)
{
PropertyLogic result;
if (_Configuration?.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, reverse, model, predictorModel);
return result;
}
private void Search(Property.Models.Configuration configuration, bool reverse, Model? model, PredictorModel? predictorModel, string argZero, Person[] people, bool isSilent) private void Search(Property.Models.Configuration configuration, bool reverse, Model? model, PredictorModel? predictorModel, string argZero, Person[] people, bool isSilent)
{ {
if (_Log is null) if (_Log is null)
@ -656,26 +654,27 @@ public class DlibDotNet
string zResultsFullGroupDirectory; string zResultsFullGroupDirectory;
string d2ResultsFullGroupDirectory; string d2ResultsFullGroupDirectory;
Dictionary<string, List<Person>> peopleCollection = A2_People.Convert(people); Dictionary<string, List<Person>> peopleCollection = A2_People.Convert(people);
PropertyLogic propertyLogic = GetPropertyLogic(reverse, model, predictorModel); Map.Models.MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration);
A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, reverse, model, predictorModel, mapLogic.IndicesFromNew, mapLogic.KeyValuePairs);
if (string.IsNullOrEmpty(configuration.RootDirectory)) if (string.IsNullOrEmpty(configuration.RootDirectory))
containers = Property.Models.Stateless.A_Property.Get(configuration, propertyLogic); containers = A_Property.Get(configuration, propertyLogic);
else else
containers = Property.Models.Stateless.Container.GetContainers(configuration, propertyLogic); containers = Property.Models.Stateless.Container.GetContainers(configuration, propertyLogic);
FullDoWork(isSilent, argZero, configuration, model, predictorModel, ticks, peopleCollection, propertyLogic, containers); FullDoWork(argZero, configuration, model, predictorModel, ticks, mapLogic, propertyLogic, containers);
foreach (string outputResolution in _Configuration.OutputResolutions) foreach (string outputResolution in _Configuration.OutputResolutions)
{ {
(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory, zResultsFullGroupDirectory) = GetResultsFullGroupDirectories(configuration, model, predictorModel, outputResolution); (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory, zResultsFullGroupDirectory) = GetResultsFullGroupDirectories(configuration, model, predictorModel, outputResolution);
if (_ArgZeroIsConfigurationRootDirectory && _Exceptions.Count == 0 && outputResolution == _Configuration.OutputResolutions[0] && (propertyLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs.Any() || propertyLogic.NamedDeterministicHashCodeKeyValuePairs.Any())) if (_ArgZeroIsConfigurationRootDirectory && _Exceptions.Count == 0 && outputResolution == _Configuration.OutputResolutions[0] && (mapLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs.Any() || mapLogic.NamedDeterministicHashCodeKeyValuePairs.Any()))
{ {
if (!string.IsNullOrEmpty(propertyLogic.DeterministicHashCodeRootDirectory) && !propertyLogic.IncorrectDeterministicHashCodeKeyValuePairs.Any()) if (!string.IsNullOrEmpty(mapLogic.DeterministicHashCodeRootDirectory) && !mapLogic.IncorrectDeterministicHashCodeKeyValuePairs.Any())
propertyLogic.UpdateKeyValuePairs(containers); mapLogic.UpdateKeyValuePairs(containers);
foreach (Container container in containers) foreach (Container container in containers)
{ {
Item.AddToNamed(propertyLogic, container.Items); Map.Models.MapLogic.AddToNamed(mapLogic, container.Items);
if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution))
D_Face.SaveShortcuts(_Configuration.JuliePhares, dResultsFullGroupDirectory, ticks, peopleCollection, propertyLogic, container.Items); D_Face.SaveShortcuts(_Configuration.JuliePhares, dResultsFullGroupDirectory, ticks, peopleCollection, mapLogic, container.Items);
} }
propertyLogic.SaveAllCollection(); mapLogic.SaveAllCollection();
if (_Configuration.SaveResizedSubfiles) if (_Configuration.SaveResizedSubfiles)
{ {
string dFacesContentDirectory; string dFacesContentDirectory;
@ -687,13 +686,13 @@ public class DlibDotNet
zPropertyHolderSingletonDirectory = Path.Combine(zResultsFullGroupDirectory, "{}"); zPropertyHolderSingletonDirectory = Path.Combine(zResultsFullGroupDirectory, "{}");
eDistanceCollectionDirectory = Path.Combine(eResultsFullGroupDirectory, $"[{ticks}]"); eDistanceCollectionDirectory = Path.Combine(eResultsFullGroupDirectory, $"[{ticks}]");
List<(DateTime, bool?, PersonBirthday, FaceRecognitionDotNet.FaceEncoding[])> collection; List<(DateTime, bool?, PersonBirthday, FaceRecognitionDotNet.FaceEncoding[])> collection;
collection = E_Distance.ParallelWork(_AppSettings.MaxDegreeOfParallelism, argZero, propertyLogic, containers); collection = E_Distance.ParallelWork(_AppSettings.MaxDegreeOfParallelism, argZero, mapLogic, containers);
_ = LogDeltaInSeconds(ticks, nameof(E_Distance.ParallelWork)); _ = LogDeltaInSeconds(ticks, nameof(E_Distance.ParallelWork));
E_Distance.SavePropertyHolders(argZero, containers, zPropertyHolderSingletonDirectory); E_Distance.SavePropertyHolders(argZero, containers, zPropertyHolderSingletonDirectory);
_ = LogDeltaInSeconds(ticks, nameof(E_Distance.SavePropertyHolders)); _ = LogDeltaInSeconds(ticks, nameof(E_Distance.SavePropertyHolders));
E_Distance.SaveThreeSigmaFaceEncodings(collection, peopleCollection, eDistanceCollectionDirectory); E_Distance.SaveThreeSigmaFaceEncodings(collection, peopleCollection, eDistanceCollectionDirectory);
_ = LogDeltaInSeconds(ticks, nameof(E_Distance.SaveThreeSigmaFaceEncodings)); _ = LogDeltaInSeconds(ticks, nameof(E_Distance.SaveThreeSigmaFaceEncodings));
E_Distance.SaveClosest(argZero, containers, peopleCollection, eDistanceContentDirectory, dFacesContentDirectory); E_Distance.SaveClosest(argZero, containers, peopleCollection, dFacesContentDirectory, d2ResultsFullGroupDirectory, eDistanceContentDirectory);
_ = LogDeltaInMinutes(ticks, nameof(E_Distance.SaveClosest)); _ = LogDeltaInMinutes(ticks, nameof(E_Distance.SaveClosest));
} }
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any()) if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any())
@ -709,17 +708,17 @@ public class DlibDotNet
if (_Configuration.LoadOrCreateThenSaveIndex && _FilePropertiesKeyValuePairs.Any()) if (_Configuration.LoadOrCreateThenSaveIndex && _FilePropertiesKeyValuePairs.Any())
_Index.SetIndex(configuration, model, predictorModel, _Configuration.OutputResolutions[0], _FilePropertiesKeyValuePairs); _Index.SetIndex(configuration, model, predictorModel, _Configuration.OutputResolutions[0], _FilePropertiesKeyValuePairs);
} }
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(aResultsFullGroupDirectory, "{}")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(aResultsFullGroupDirectory, "{}"));
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(bResultsFullGroupDirectory, "{}")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(bResultsFullGroupDirectory, "{}"));
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(cResultsFullGroupDirectory, "{}")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(cResultsFullGroupDirectory, "{}"));
if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution))
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(dResultsFullGroupDirectory, "[]")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(dResultsFullGroupDirectory, "[]"));
if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution))
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]"));
if (_Configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions.Contains(outputResolution)) if (_Configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions.Contains(outputResolution))
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]"));
if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(Path.Combine(d2ResultsFullGroupDirectory, "[]")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(d2ResultsFullGroupDirectory, "[]"));
} }
} }

View File

@ -10,7 +10,7 @@
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.View.by.Distance.Instance</PackageId> <PackageId>Phares.View.by.Distance.Instance</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>5.0.402.104</Version> <Version>6.0.100.1</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<Company>Phares</Company> <Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
@ -53,12 +53,13 @@
<PackageReference Include="WindowsShortcutFactory" Version="1.0.1" /> <PackageReference Include="WindowsShortcutFactory" Version="1.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Resize\Resize.csproj" />
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" /> <ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />
<ProjectReference Include="..\Map\Map.csproj" />
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property-Compare\Property-Compare.csproj" /> <ProjectReference Include="..\Property-Compare\Property-Compare.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Resize\Resize.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="appsettings.json"> <None Include="appsettings.json">

View File

@ -1,5 +1,4 @@
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
namespace View_by_Distance.Instance.Models; namespace View_by_Distance.Instance.Models;
@ -37,7 +36,7 @@ internal class A2_People
string directoryFullName; string directoryFullName;
Dictionary<string, List<G2_Identify>> keyValuePairs = new(); Dictionary<string, List<G2_Identify>> keyValuePairs = new();
string hPeopleCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A2_People), "[]"); string hPeopleCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A2_People), "[]");
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(Property.Models.A_Property), "{}");
foreach (G2_Identify identified in identifiedCollection) foreach (G2_Identify identified in identifiedCollection)
{ {
fileInfo = new FileInfo(string.Concat(aPropertySingletonDirectory, identified.RelativePath)); fileInfo = new FileInfo(string.Concat(aPropertySingletonDirectory, identified.RelativePath));
@ -56,7 +55,7 @@ internal class A2_People
_ = Directory.CreateDirectory(directoryFullName); _ = Directory.CreateDirectory(directoryFullName);
jsonFile = Path.Combine(directoryFullName, $"{segments[1]}.json"); jsonFile = Path.Combine(directoryFullName, $"{segments[1]}.json");
json = JsonSerializer.Serialize(keyValuePair.Value, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(keyValuePair.Value, _WriteIndentedJsonSerializerOptions);
if (!Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: true, compareBeforeWrite: true)) if (!Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: true, compareBeforeWrite: true))
continue; continue;
} }
} }
@ -64,8 +63,6 @@ internal class A2_People
internal Person[] GetPeople(Property.Models.Configuration configuration) internal Person[] GetPeople(Property.Models.Configuration configuration)
{ {
Person[] results; Person[] results;
if (_Configuration?.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
string rootDirectory = _Configuration.PropertyConfiguration.RootDirectory; string rootDirectory = _Configuration.PropertyConfiguration.RootDirectory;
string peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A2_People)); string peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A2_People));
string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory)); string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory));

View File

@ -1,8 +1,9 @@
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging;
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Metadata.Models; using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models; using View_by_Distance.Resize.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
@ -11,16 +12,22 @@ namespace View_by_Distance.Instance.Models;
/// <summary> /// <summary>
// *.png // *.png
/// </summary> /// </summary>
internal class D2_FaceLandmarks internal class D2_FaceParts
{ {
private readonly Serilog.ILogger? _Log; private readonly Serilog.ILogger? _Log;
private readonly string _FilenameExtension;
private readonly Configuration _Configuration; private readonly Configuration _Configuration;
private readonly ImageCodecInfo _ImageCodecInfo;
private readonly EncoderParameters _EncoderParameters;
internal D2_FaceLandmarks(Configuration configuration) internal D2_FaceParts(Configuration configuration, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension)
{ {
_Configuration = configuration; _Configuration = configuration;
_Log = Serilog.Log.ForContext<D2_FaceLandmarks>(); _ImageCodecInfo = imageCodecInfo;
_EncoderParameters = encoderParameters;
_FilenameExtension = filenameExtension;
_Log = Serilog.Log.ForContext<D2_FaceParts>();
} }
public override string ToString() public override string ToString()
@ -41,60 +48,64 @@ internal class D2_FaceLandmarks
return result; return result;
} }
private static void SaveFaceLandmarkImages(List<D_Face> faceCollections, List<string[]> imageFiles, int pointSize, FileHolder resizedFileHolder) private void SaveFaceParts(int pointSize, IFileHolder resizedFileHolder, bool saveRotated, List<(Face, string, string)> collection)
{ {
int x; int x;
int y; int y;
double? α;
int width; int width;
int height; int height;
D_Face face;
string imageFileFullName;
Bitmap rotated; Bitmap rotated;
string rotatedImageFileFullName; foreach ((Face face, string fileName, string rotatedFileName) in collection)
Shared.Models.FacePoint[] facePoints;
for (int i = 0; i < faceCollections.Count; i++)
{ {
if (!faceCollections[i].Populated) if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue; continue;
face = faceCollections[i];
imageFileFullName = imageFiles[i][0];
rotatedImageFileFullName = imageFiles[i][1];
try try
{ {
using (Image image = Image.FromFile(resizedFileHolder.FullName)) using (Image image = Image.FromFile(resizedFileHolder.FullName))
{ {
using Graphics graphic = Graphics.FromImage(image); using Graphics graphic = Graphics.FromImage(image);
if (face.FaceLandmarks is null || !face.FaceLandmarks.Any()) if (face.FaceParts is null || !face.FaceParts.Any())
{ {
if (face.Location is null)
continue;
width = face.Location.Right - face.Location.Left; width = face.Location.Right - face.Location.Left;
height = face.Location.Bottom - face.Location.Top; height = face.Location.Bottom - face.Location.Top;
graphic.DrawEllipse(Pens.Red, face.Location.Left, face.Location.Top, width, height); graphic.DrawEllipse(Pens.Red, face.Location.Left, face.Location.Top, width, height);
} }
else else
{ {
foreach (KeyValuePair<string, Shared.Models.FacePoint[]> keyValuePair in face.FaceLandmarks) foreach ((FacePart facePart, FacePoint[] facePoints) in face.FaceParts)
{ {
facePoints = keyValuePair.Value.ToArray(); foreach (FacePoint facePoint in facePoints)
foreach (Shared.Models.FacePoint facePoint in facePoints) {
if (face.Location is null)
continue;
graphic.DrawEllipse(Pens.GreenYellow, face.Location.Left + facePoint.X - pointSize, face.Location.Top + facePoint.Y - pointSize, pointSize * 2, pointSize * 2); graphic.DrawEllipse(Pens.GreenYellow, face.Location.Left + facePoint.X - pointSize, face.Location.Top + facePoint.Y - pointSize, pointSize * 2, pointSize * 2);
if (keyValuePair.Key == FacePart.Chin.ToString()) }
if (facePart == FacePart.Chin)
continue; continue;
if (facePoints.Length < 3) if (facePoints.Length < 3)
continue; continue;
x = (int)(from l in facePoints select l.X).Average(); x = (int)(from l in facePoints select l.X).Average();
y = (int)(from l in facePoints select l.Y).Average(); y = (int)(from l in facePoints select l.Y).Average();
if (face.Location is null)
continue;
graphic.DrawEllipse(Pens.Purple, face.Location.Left + x - pointSize, face.Location.Top + y - pointSize, pointSize * 2, pointSize * 2); graphic.DrawEllipse(Pens.Purple, face.Location.Left + x - pointSize, face.Location.Top + y - pointSize, pointSize * 2, pointSize * 2);
} }
} }
image.Save(imageFileFullName, System.Drawing.Imaging.ImageFormat.Png); image.Save(fileName, _ImageCodecInfo, _EncoderParameters);
} }
if (face.α.HasValue) if (saveRotated && face.FaceParts is not null)
{ {
α = Shared.Models.Stateless.Methods.IFace.Getα(face.FaceParts);
if (α is null)
continue;
using Image image = Image.FromFile(resizedFileHolder.FullName); using Image image = Image.FromFile(resizedFileHolder.FullName);
rotated = RotateBitmap(image, (float)face.α.Value); rotated = RotateBitmap(image, (float)α.Value);
if (rotated is not null) if (rotated is not null)
{ {
rotated.Save(rotatedImageFileFullName, System.Drawing.Imaging.ImageFormat.Png); rotated.Save(rotatedFileName, _ImageCodecInfo, _EncoderParameters);
rotated.Dispose(); rotated.Dispose();
} }
} }
@ -105,10 +116,8 @@ internal class D2_FaceLandmarks
#pragma warning restore CA1416 #pragma warning restore CA1416
internal void SaveFaceLandmarkImages(string d2ResultsFullGroupDirectory, string sourceDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<D_Face> faceCollection) internal void SaveFaceLandmarkImages(string d2ResultsFullGroupDirectory, string sourceDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection, bool saveRotated)
{ {
if (_Configuration.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
if (item.ImageFileHolder is null) if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder)); throw new NullReferenceException(nameof(item.ImageFileHolder));
if (item.ResizedFileHolder is null) if (item.ResizedFileHolder is null)
@ -121,31 +130,31 @@ internal class D2_FaceLandmarks
DateTime? dateTime = null; DateTime? dateTime = null;
double deterministicHashCodeKey; double deterministicHashCodeKey;
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
List<string[]> imageFiles = new();
bool updateDateWhenMatches = false; bool updateDateWhenMatches = false;
List<string> angleBracketCollection = new(); List<string> angleBracketCollection = new();
List<(Face, string, string)> collection = new();
angleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection( angleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(
_Configuration.PropertyConfiguration, _Configuration.PropertyConfiguration,
sourceDirectory, sourceDirectory,
d2ResultsFullGroupDirectory, d2ResultsFullGroupDirectory,
contentDescription: "n x 2 png file(s) for each face found", contentDescription: "n x 2 gif file(s) for each face found",
singletonDescription: string.Empty, singletonDescription: string.Empty,
collectionDescription: string.Empty, collectionDescription: string.Empty,
converted: false)); converted: false));
string facesDirectory = Path.Combine(angleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); string facesDirectory = Path.Combine(angleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension);
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) };
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
if (!Directory.Exists(facesDirectory)) if (!Directory.Exists(facesDirectory))
_ = Directory.CreateDirectory(facesDirectory); _ = Directory.CreateDirectory(facesDirectory);
foreach (IFace face in faceCollection) foreach (Face face in faceCollection)
{ {
if (!face.Populated || face.Location?.NormalizedPixelPercentage is null) if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
{ {
imageFiles.Add(Array.Empty<string>()); collection.Add(new(face, string.Empty, string.Empty));
continue; continue;
} }
deterministicHashCodeKey = Named.GetDeterministicHashCodeKey(item, face); deterministicHashCodeKey = Shared.Models.Stateless.Methods.INamed.GetDeterministicHashCodeKey(item, face);
fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}.png")); fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}"));
if (!fileInfo.Exists) if (!fileInfo.Exists)
{ {
if (fileInfo.Directory?.Parent is null) if (fileInfo.Directory?.Parent is null)
@ -156,15 +165,15 @@ internal class D2_FaceLandmarks
} }
if (string.IsNullOrEmpty(fileInfo.DirectoryName)) if (string.IsNullOrEmpty(fileInfo.DirectoryName))
continue; continue;
rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKey} - R{item.ImageFileHolder.ExtensionLowered}")); rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKey} - R{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}"));
imageFiles.Add(new string[] { fileInfo.FullName, rotatedFileInfo.FullName }); collection.Add(new(face, fileInfo.FullName, rotatedFileInfo.FullName));
if (check) if (check)
continue; continue;
else if (_Configuration.OverrideForFaceLandmarkImages) else if (_Configuration.OverrideForFaceLandmarkImages)
check = true; check = true;
else if (!fileInfo.Exists) else if (!fileInfo.Exists)
check = true; check = true;
else if (!rotatedFileInfo.Exists) else if (saveRotated && !rotatedFileInfo.Exists)
check = true; check = true;
else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime) else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
check = true; check = true;
@ -175,7 +184,7 @@ internal class D2_FaceLandmarks
} }
} }
if (check) if (check)
SaveFaceLandmarkImages(faceCollection, imageFiles, pointSize, item.ResizedFileHolder); SaveFaceParts(pointSize, item.ResizedFileHolder, saveRotated, collection);
} }
} }

View File

@ -1,14 +1,13 @@
using System.Drawing; using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using View_by_Distance.FaceRecognitionDotNet; using View_by_Distance.FaceRecognitionDotNet;
using View_by_Distance.Metadata.Models; using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models; using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models; using View_by_Distance.Resize.Models;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
using WindowsShortcutFactory; using WindowsShortcutFactory;
@ -17,7 +16,7 @@ namespace View_by_Distance.Instance.Models;
/// <summary> /// <summary>
// List<D_Faces> // List<D_Faces>
/// </summary> /// </summary>
public class D_Face : IFace, Shared.Models.Methods.IFace public class D_Face
{ {
internal List<string> AngleBracketCollection { get; } internal List<string> AngleBracketCollection { get; }
@ -25,112 +24,29 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
private readonly Model _Model; private readonly Model _Model;
private readonly string _ArgZero; private readonly string _ArgZero;
private readonly Serilog.ILogger? _Log; private readonly Serilog.ILogger? _Log;
private readonly string _FilenameExtension;
private readonly Configuration _Configuration; private readonly Configuration _Configuration;
private readonly ModelParameter _ModelParameter; private readonly ModelParameter _ModelParameter;
private readonly PredictorModel _PredictorModel; private readonly PredictorModel _PredictorModel;
private readonly ImageCodecInfo _ImageCodecInfo;
private readonly EncoderParameters _EncoderParameters;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
protected double? _Α; internal D_Face(Configuration configuration, string argZero, Model model, ModelParameter modelParameter, PredictorModel predictorModel, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension)
protected DateTime _DateTime;
protected Shared.Models.FaceEncoding _FaceEncoding;
protected Dictionary<string, FacePoint[]> _FaceLandmarks;
protected Location _Location;
protected int? _LocationIndex;
protected OutputResolution _OutputResolution;
protected bool _Populated;
protected string _RelativePath;
public double? α => _Α;
public DateTime DateTime => _DateTime;
public Shared.Models.FaceEncoding FaceEncoding => _FaceEncoding;
public Dictionary<string, FacePoint[]> FaceLandmarks => _FaceLandmarks;
public OutputResolution OutputResolution => _OutputResolution;
public Location Location => _Location;
public int? LocationIndex => _LocationIndex;
public bool Populated => _Populated;
public string RelativePath => _RelativePath;
#nullable disable
[JsonConstructor]
public D_Face(double? α, DateTime dateTime, Shared.Models.FaceEncoding faceEncoding, Dictionary<string, FacePoint[]> faceLandmarks, Location location, int? locationIndex, OutputResolution outputResolution, bool populated, string relativePath)
{
_Α = α;
_DateTime = dateTime;
_FaceEncoding = faceEncoding;
_FaceLandmarks = faceLandmarks;
_Location = location;
_LocationIndex = locationIndex;
_OutputResolution = outputResolution;
_Populated = populated;
_RelativePath = relativePath;
}
internal D_Face(Configuration configuration, string argZero, Model model, ModelParameter modelParameter, PredictorModel predictorModel)
{ {
_Model = model; _Model = model;
_ArgZero = argZero; _ArgZero = argZero;
_Configuration = configuration; _Configuration = configuration;
_ModelParameter = modelParameter; _ModelParameter = modelParameter;
_PredictorModel = predictorModel; _PredictorModel = predictorModel;
_ImageCodecInfo = imageCodecInfo;
_EncoderParameters = encoderParameters;
_FilenameExtension = filenameExtension;
AngleBracketCollection = new List<string>(); AngleBracketCollection = new List<string>();
_Log = Serilog.Log.ForContext<D_Face>(); _Log = Serilog.Log.ForContext<D_Face>();
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
} }
private D_Face(Location location)
{
_Α = α;
_DateTime = DateTime.MinValue;
_FaceEncoding = null;
_FaceLandmarks = null;
_OutputResolution = null;
_Location = location;
_LocationIndex = null;
_Populated = false;
_RelativePath = string.Empty;
}
private D_Face()
{
_Α = α;
_DateTime = DateTime.MinValue;
_FaceEncoding = null;
_FaceLandmarks = null;
_OutputResolution = null;
_Location = null;
_LocationIndex = null;
_Populated = false;
_RelativePath = string.Empty;
}
private D_Face(A_Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string relativePath, int? i, Location location)
{
DateTime?[] dateTimes;
dateTimes = new DateTime?[] { property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeOriginal, property.GPSDateStamp };
_DateTime = (from l in dateTimes where l.HasValue select l.Value).Min();
_FaceLandmarks = new Dictionary<string, FacePoint[]>();
_OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth);
_Location = location;
_LocationIndex = i;
_Populated = false;
_RelativePath = relativePath;
}
private D_Face(int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, IFace face)
{
_Α = face.α;
_DateTime = face.DateTime;
_FaceEncoding = face.FaceEncoding;
_FaceLandmarks = face.FaceLandmarks;
_OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth);
_Location = face.Location;
_LocationIndex = face.LocationIndex;
_Populated = face.Populated;
_RelativePath = face.RelativePath;
}
#nullable restore
private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum) private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum)
{ {
xMinimum = points[0].X; xMinimum = points[0].X;
@ -219,26 +135,22 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
return result; return result;
} }
private static void SaveFaces(List<D_Face> faceCollection, FileHolder resizedFileHolder, List<string> imageFiles) private void SaveFaces(FileHolder resizedFileHolder, List<(Face, string)> collection)
{ {
int width; int width;
int height; int height;
Graphics graphics; Graphics graphics;
Location location; Location? location;
Bitmap preRotated; Bitmap preRotated;
Rectangle rectangle; Rectangle rectangle;
using Bitmap source = new(resizedFileHolder.FullName); using Bitmap source = new(resizedFileHolder.FullName);
for (int i = 0; i < faceCollection.Count; i++) foreach ((Face face, string fileName) in collection)
{ {
if (!faceCollection[i].Populated || faceCollection[i]?.Location is null) if (face.FaceEncoding is null || face?.Location is null)
continue;
location = Shared.Models.Stateless.Methods.ILocation.GetLocation(face.Location, source.Height, source.Width, collection.Count);
if (location is null)
continue; continue;
location = new Location(faceCollection[i].Location.Confidence,
faceCollection[i].Location.Bottom,
faceCollection[i].Location.Left,
faceCollection[i].Location.Right,
faceCollection[i].Location.Top,
source.Width,
source.Height);
width = location.Right - location.Left; width = location.Right - location.Left;
height = location.Bottom - location.Top; height = location.Bottom - location.Top;
rectangle = new Rectangle(location.Left, location.Top, width, height); rectangle = new Rectangle(location.Left, location.Top, width, height);
@ -246,149 +158,54 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
{ {
using (graphics = Graphics.FromImage(preRotated)) using (graphics = Graphics.FromImage(preRotated))
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel); graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
preRotated.Save(imageFiles[i], System.Drawing.Imaging.ImageFormat.Png); preRotated.Save(fileName, _ImageCodecInfo, _EncoderParameters);
} }
} }
} }
private List<D_Face> GetFaces(FileHolder resizedFileHolder, Item item, A_Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string facesDirectory) private List<Face> GetFaces(FileHolder resizedFileHolder, Item item, Shared.Models.Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation)
{ {
List<D_Face> results = new(); List<Face> results = new();
if (item.ImageFileHolder is null) if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder)); throw new NullReferenceException(nameof(item.ImageFileHolder));
List<Location> locations; FaceRecognitionDotNet.Image? unknownImage;
FaceRecognitionDotNet.Image? unknownImage = null; if (!resizedFileHolder.Exists)
if (resizedFileHolder.Exists) unknownImage = null;
else
{ {
try try
{ unknownImage = FaceRecognition.LoadImageFile(resizedFileHolder.FullName); } { unknownImage = FaceRecognition.LoadImageFile(resizedFileHolder.FullName); }
catch (Exception) { } catch (Exception)
{ unknownImage = null; }
} }
if (unknownImage is null) if (unknownImage is null)
results.Add(new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, i: null, location: null)); results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, i: null, location: null));
else else
{ {
FaceRecognition faceRecognition = FaceRecognition.Create(_ModelParameter); List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
locations = faceRecognition.FaceLocations(_Model, unknownImage, _Configuration.NumberOfTimesToUpsample, sortByNormalizedPixelPercentage: true); FaceRecognition faceRecognition = new(_Configuration.NumberOfTimesToUpsample, _Configuration.NumberOfJitters, _PredictorModel, _Model, _ModelParameter);
if (!locations.Any()) collection = faceRecognition.GetCollection(unknownImage, includeFaceEncoding: true, includeFaceParts: true, sortByNormalizedPixelPercentage: true);
results.Add(new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, i: null, location: null)); if (!collection.Any())
results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, i: null, location: null));
else else
{ {
double? α; int i = 0;
int width; Face face;
int height;
int padding;
int? leftEyeX;
int? leftEyeY;
int? rightEyeX;
int? rightEyeY;
Bitmap rotated;
string faceFile;
Location location;
Bitmap preRotated;
Graphics graphics;
D_Face? face = null;
Rectangle rectangle;
double[] rawEncoding; double[] rawEncoding;
double deterministicHashCodeKey; Shared.Models.FaceEncoding convertedFaceEncoding;
Shared.Models.FaceEncoding faceEncoding; foreach ((Location location, FaceRecognitionDotNet.FaceEncoding? faceEncoding, Dictionary<FacePart, FacePoint[]>? faceParts) in collection)
FaceRecognitionDotNet.Image? knownImage;
FaceRecognitionDotNet.Image? rotatedImage;
List<(FacePart, FacePoint[])[]> facesLandmarks;
List<FaceRecognitionDotNet.FaceEncoding> faceEncodings;
using Bitmap source = unknownImage.ToBitmap();
padding = (int)((source.Width + source.Height) / 2 * .01);
for (int i = 0; i < locations.Count; i++)
{ {
for (int p = 0; p <= _Configuration.PaddingLoops; p++)
{
location = new(locations[i].Confidence,
locations[i].Bottom + (padding * p),
locations[i].Left - (padding * p),
locations[i].Right + (padding * p),
locations[i].Top - (padding * p),
source.Width,
source.Height);
face = new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, i, location); face = new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, i, location);
width = location.Right - location.Left; if (faceEncoding is not null)
height = location.Bottom - location.Top;
rectangle = new Rectangle(location.Left, location.Top, width, height);
using (preRotated = new Bitmap(width, height))
{ {
leftEyeX = null; rawEncoding = faceEncoding.GetRawEncoding();
leftEyeY = null; convertedFaceEncoding = new(rawEncoding, faceEncoding.Size);
rightEyeX = null; face.SetFaceEncoding(convertedFaceEncoding);
rightEyeY = null;
using (graphics = Graphics.FromImage(preRotated))
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
// source.Save(Path.Combine(_Configuration.RootDirectory, "source.jpg"));
// preRotated.Save(Path.Combine(_Configuration.RootDirectory, $"{p} - preRotated.jpg"));
using (knownImage = FaceRecognition.LoadImage(preRotated))
{
if (knownImage is null || knownImage.IsDisposed)
throw new NullReferenceException(nameof(knownImage));
facesLandmarks = faceRecognition.GetFaceLandmarkCollection(knownImage, _Configuration.NumberOfTimesToUpsample, faceLocations: null, _PredictorModel, _Model);
} }
if (facesLandmarks.Count == 0 && p < _Configuration.PaddingLoops) if (faceParts is not null)
continue; face.SetFaceParts(faceParts);
else if (facesLandmarks.Count != 1)
continue;
foreach ((FacePart facePart, FacePoint[] facePoints) in facesLandmarks[0])
{
face.FaceLandmarks.Add(facePart.ToString(), facePoints);
if (facePart is not FacePart.LeftEye and not FacePart.RightEye)
continue;
if (facePart is FacePart.LeftEye)
{
leftEyeX = (int)(from l in facePoints select l.X).Average();
leftEyeY = (int)(from l in facePoints select l.Y).Average();
}
if (facePart is FacePart.RightEye)
{
rightEyeX = (int)(from l in facePoints select l.X).Average();
rightEyeY = (int)(from l in facePoints select l.Y).Average();
}
}
if (rightEyeX is null || leftEyeX is null || rightEyeY is null || leftEyeY is null)
continue;
α = Shared.Models.Stateless.Methods.IFace.Getα(rightEyeX.Value, leftEyeX.Value, rightEyeY.Value, leftEyeY.Value);
using (rotated = RotateBitmap(preRotated, (float)α.Value))
{
// rotated.Save(Path.Combine(_Configuration.RootDirectory, $"{p} - rotated.jpg"));
using (rotatedImage = FaceRecognition.LoadImage(rotated))
{
if (rotatedImage is null || rotatedImage.IsDisposed)
throw new NullReferenceException(nameof(rotatedImage));
faceEncodings = faceRecognition.FaceEncodings(rotatedImage, _Configuration.NumberOfTimesToUpsample, knownFaceLocation: null, _Configuration.NumberOfJitters, _PredictorModel, _Model);
}
if (faceEncodings.Count == 0 && p < _Configuration.PaddingLoops)
continue;
else if (faceEncodings.Count != 1)
continue;
rawEncoding = faceEncodings[0].GetRawEncoding();
faceEncoding = new(rawEncoding, faceEncodings[0].Size);
face.Update(α, faceEncoding, populated: true);
}
deterministicHashCodeKey = Named.GetDeterministicHashCodeKey(item, face);
faceFile = Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}.png");
preRotated.Save(faceFile, System.Drawing.Imaging.ImageFormat.Png);
results.Add(face); results.Add(face);
} i += 1;
if (face.Populated)
break;
}
if (face is null || !face.Populated)
{
location = new(locations[i].Confidence,
locations[i].Bottom,
locations[i].Left,
locations[i].Right,
locations[i].Top,
source.Width,
source.Height);
face = new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, i, location);
results.Add(face);
}
} }
} }
unknownImage.Dispose(); unknownImage.Dispose();
@ -401,16 +218,9 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
#pragma warning restore CA1416 #pragma warning restore CA1416
private void Update(double? α, Shared.Models.FaceEncoding faceEncoding, bool populated) internal List<Face> GetFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, Shared.Models.Property property, FileHolder resizedFileHolder, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation)
{ {
_Α = α; List<Face>? results;
_FaceEncoding = faceEncoding;
_Populated = populated;
}
internal List<D_Face> GetFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, A_Property property, FileHolder resizedFileHolder, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation)
{
List<D_Face>? results;
if (item.Property?.Id is null) if (item.Property?.Id is null)
throw new NullReferenceException(nameof(item.Property.Id)); throw new NullReferenceException(nameof(item.Property.Id));
if (item.ImageFileHolder is null) if (item.ImageFileHolder is null)
@ -418,9 +228,10 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
if (string.IsNullOrEmpty(dResultsFullGroupDirectory)) if (string.IsNullOrEmpty(dResultsFullGroupDirectory))
throw new NullReferenceException(nameof(dResultsFullGroupDirectory)); throw new NullReferenceException(nameof(dResultsFullGroupDirectory));
string json; string json;
int?[] normalizedPixelPercentageCollection;
int normalizedPixelPercentageDistinctCount;
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) };
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension);
string usingRelativePath = Path.Combine(AngleBracketCollection[0].Replace("<>", "[]"), $"{item.ImageFileHolder.NameWithoutExtension}.json"); string usingRelativePath = Path.Combine(AngleBracketCollection[0].Replace("<>", "[]"), $"{item.ImageFileHolder.NameWithoutExtension}.json");
string dCollectionFile = Path.Combine(dResultsFullGroupDirectory, "[]", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}.json"); string dCollectionFile = Path.Combine(dResultsFullGroupDirectory, "[]", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}.json");
FileInfo fileInfo = new(dCollectionFile); FileInfo fileInfo = new(dCollectionFile);
@ -443,8 +254,6 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
} }
} }
} }
if (!Directory.Exists(facesDirectory))
_ = Directory.CreateDirectory(facesDirectory);
if (_Configuration.ForceFaceLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) if (_Configuration.ForceFaceLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
{ {
File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName);
@ -466,9 +275,18 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
json = Shared.Models.Stateless.Methods.IFace.GetJson(fileInfo.FullName); json = Shared.Models.Stateless.Methods.IFace.GetJson(fileInfo.FullName);
try try
{ {
results = JsonSerializer.Deserialize<List<D_Face>>(json); results = JsonSerializer.Deserialize<List<Face>>(json);
if (results is null) if (results is null)
throw new NullReferenceException(nameof(results)); throw new NullReferenceException(nameof(results));
if (!_Configuration.ForceFaceLastWriteTimeToCreationTime)
{
normalizedPixelPercentageCollection = Shared.Models.Stateless.Methods.IFace.GetInts(results);
if (normalizedPixelPercentageCollection.Contains(3))
throw new Exception($"Not allowed! <{fileInfo.FullName}>");
normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count();
if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length)
throw new Exception($"Not distinct! <{fileInfo.FullName}>");
}
subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), fileInfo.LastWriteTime)); subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), fileInfo.LastWriteTime));
} }
catch (Exception) catch (Exception)
@ -479,19 +297,24 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
} }
if (results is null) if (results is null)
{ {
results = GetFaces(resizedFileHolder, item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, facesDirectory); results = GetFaces(resizedFileHolder, item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation);
json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions);
bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime;
DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), DateTime.Now)); subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), DateTime.Now));
} }
if (_Configuration.ForceFaceLastWriteTimeToCreationTime) if (_Configuration.ForceFaceLastWriteTimeToCreationTime)
{ {
results = (from l in results select new Face(results.Count, l)).ToList();
normalizedPixelPercentageCollection = Shared.Models.Stateless.Methods.IFace.GetInts(results);
normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count();
if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length)
throw new Exception($"Not distinct! <{fileInfo.FullName}>");
json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions);
bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime;
DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime))
{ {
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
fileInfo.Refresh(); fileInfo.Refresh();
@ -501,7 +324,7 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
return results; return results;
} }
internal void SaveFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<D_Face> faceCollection) internal void SaveFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection)
{ {
if (item.ImageFileHolder is null) if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder)); throw new NullReferenceException(nameof(item.ImageFileHolder));
@ -511,22 +334,22 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
bool check = false; bool check = false;
string parentCheck; string parentCheck;
double deterministicHashCodeKey; double deterministicHashCodeKey;
List<string> imageFiles = new(); List<(Face, string)> collection = new();
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) };
string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension);
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
bool facesDirectoryExisted = Directory.Exists(facesDirectory); bool facesDirectoryExisted = Directory.Exists(facesDirectory);
if (!facesDirectoryExisted) if (!facesDirectoryExisted)
_ = Directory.CreateDirectory(facesDirectory); _ = Directory.CreateDirectory(facesDirectory);
foreach (IFace face in faceCollection) foreach (Face face in faceCollection)
{ {
if (!face.Populated || face.Location?.NormalizedPixelPercentage is null) if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
{ {
imageFiles.Add(string.Empty); collection.Add(new(face, string.Empty));
continue; continue;
} }
deterministicHashCodeKey = Named.GetDeterministicHashCodeKey(item, face); deterministicHashCodeKey = Shared.Models.Stateless.Methods.INamed.GetDeterministicHashCodeKey(item, face);
fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}.png")); fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}"));
if (!fileInfo.Exists) if (!fileInfo.Exists)
{ {
if (fileInfo.Directory?.Parent is null) if (fileInfo.Directory?.Parent is null)
@ -535,7 +358,7 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
if (File.Exists(parentCheck)) if (File.Exists(parentCheck))
File.Delete(parentCheck); File.Delete(parentCheck);
} }
imageFiles.Add(fileInfo.FullName); collection.Add(new(face, fileInfo.FullName));
if (_Configuration.OverrideForFaceImages) if (_Configuration.OverrideForFaceImages)
check = true; check = true;
else if (!fileInfo.Exists) else if (!fileInfo.Exists)
@ -544,10 +367,10 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
check = true; check = true;
} }
if (check) if (check)
SaveFaces(faceCollection, item.ResizedFileHolder, imageFiles); SaveFaces(item.ResizedFileHolder, collection);
} }
internal static void SaveShortcuts(string[] juliePhares, string dResultsFullGroupDirectory, long ticks, Dictionary<string, List<Person>> peopleCollection, PropertyLogic propertyLogic, List<Item> items) internal static void SaveShortcuts(string[] juliePhares, string dResultsFullGroupDirectory, long ticks, Dictionary<string, List<Person>> peopleCollection, Map.Models.MapLogic mapLogic, List<Item> items)
{ {
Person person; Person person;
string fileName; string fileName;
@ -556,18 +379,18 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
WindowsShortcut windowsShortcut; WindowsShortcut windowsShortcut;
const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]"; const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]";
string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, $"({ticks})"); string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, $"({ticks})");
List<(Item, (string, IFace?, (string, string, string, string))[])> collections = Item.GetCollection(propertyLogic, items, dFacesContentDirectory); List<(Item, (string, Face?, (string, string, string, string))[])> collections = Map.Models.MapLogic.GetCollection(mapLogic, items, dFacesContentDirectory);
foreach ((Item item, (string personKey, IFace? _, (string, string, string, string))[] collection) in collections) foreach ((Item item, (string personKey, Face? _, (string, string, string, string))[] collection) in collections)
{ {
if (collection.Length != 1) if (collection.Length != 1)
continue; continue;
foreach ((string personKey, IFace? _, (string directory, string copyDirectory, string copyFileName, string shortcutFileName)) in collection) foreach ((string personKey, Face? _, (string directory, string copyDirectory, string copyFileName, string shortcutFileName)) in collection)
{ {
if (string.IsNullOrEmpty(personKey)) if (string.IsNullOrEmpty(personKey))
continue; continue;
if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null) if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null)
continue; continue;
minimumDateTime = Property.Models.Stateless.A_Property.GetMinimumDateTime(item.Property); minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
if (minimumDateTime is null) if (minimumDateTime is null)
continue; continue;
if (!Directory.Exists(directory)) if (!Directory.Exists(directory))
@ -601,24 +424,16 @@ public class D_Face : IFace, Shared.Models.Methods.IFace
} }
} }
double Shared.Models.Stateless.Methods.IFace.TestStatic_Getα(int x1, int x2, int y1, int y2) => throw new NotImplementedException(); private static bool HasLeftAndRight(Dictionary<string, FacePoint[]> faceParts)
string Shared.Models.Stateless.Methods.IFace.TestStatic_GetJson(string jsonFileFullName) => throw new NotImplementedException();
Face Shared.Models.Stateless.Methods.IFace.TestStatic_GetFace(string jsonFileFullName) => throw new NotImplementedException();
Face[] Shared.Models.Stateless.Methods.IFace.TestStatic_GetFaces(string jsonFileFullName) => throw new NotImplementedException();
private static bool HasLeftAndRight(Dictionary<string, FacePoint[]> faceLandmarks)
{ {
bool result = true; bool result = true;
if (!faceLandmarks.ContainsKey(FacePart.LeftEye.ToString())) if (!faceParts.ContainsKey(FacePart.LeftEye.ToString()))
result = false; result = false;
else if (!faceLandmarks.ContainsKey(FacePart.RightEye.ToString())) else if (!faceParts.ContainsKey(FacePart.RightEye.ToString()))
result = false; result = false;
else if (!faceLandmarks.ContainsKey(FacePart.LeftEyebrow.ToString())) else if (!faceParts.ContainsKey(FacePart.LeftEyebrow.ToString()))
result = false; result = false;
else if (!faceLandmarks.ContainsKey(FacePart.RightEyebrow.ToString())) else if (!faceParts.ContainsKey(FacePart.RightEyebrow.ToString()))
result = false; result = false;
return result; return result;
} }

View File

@ -96,8 +96,6 @@ internal class E2_Navigate
string result; string result;
if (_Log is null) if (_Log is null)
throw new NullReferenceException(nameof(_Log)); throw new NullReferenceException(nameof(_Log));
if (_Configuration?.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
_Log.Warn(string.Concat("What is the new name for [", Path.GetFileName(subSourceDirectory), "]<", subSourceDirectory, ">?")); _Log.Warn(string.Concat("What is the new name for [", Path.GetFileName(subSourceDirectory), "]<", subSourceDirectory, ">?"));
string? newDirectoryName = _Console.ReadLine(); string? newDirectoryName = _Console.ReadLine();
_Log.Warn("Are you sure y[es] || n[o]?"); _Log.Warn("Are you sure y[es] || n[o]?");
@ -111,7 +109,7 @@ internal class E2_Navigate
{ {
_Log.Warn(string.Empty); _Log.Warn(string.Empty);
string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
string relativePath = Property.Models.Stateless.IPath.GetRelativePath(subSourceDirectory, eDistanceCollectionDirectory.Length); string relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(subSourceDirectory, eDistanceCollectionDirectory.Length);
if (relativePath.Length == 1) if (relativePath.Length == 1)
throw new Exception(); throw new Exception();
if (Directory.Exists(Path.Combine(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName))) if (Directory.Exists(Path.Combine(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName)))

View File

@ -1,6 +1,5 @@
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Metadata.Models; using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models; using View_by_Distance.Resize.Models;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
@ -40,10 +39,10 @@ internal class E3_Rename
string cResizeSingletonDirectory; string cResizeSingletonDirectory;
string eDistanceContentDirectory; string eDistanceContentDirectory;
string aPropertySingletonDirectory; string aPropertySingletonDirectory;
string d2FacePartsContentDirectory;
string bMetadataSingletonDirectory; string bMetadataSingletonDirectory;
string eDistanceCollectionDirectory; string eDistanceCollectionDirectory;
string g2IdentifyCollectionDirectory; string g2IdentifyCollectionDirectory;
string d2FaceLandmarksContentDirectory;
add = Directory.Exists(string.Concat(Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(C_Resize), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"), relativePath)); add = Directory.Exists(string.Concat(Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(C_Resize), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"), relativePath));
bMetadataSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(B_Metadata), "{}"); bMetadataSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(B_Metadata), "{}");
if (Directory.Exists(bMetadataSingletonDirectory)) if (Directory.Exists(bMetadataSingletonDirectory))
@ -51,7 +50,7 @@ internal class E3_Rename
to = Path.Combine(string.Concat(bMetadataSingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); to = Path.Combine(string.Concat(bMetadataSingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to); results.Add(to);
} }
aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(Property.Models.A_Property), "{}");
if (Directory.Exists(aPropertySingletonDirectory)) if (Directory.Exists(aPropertySingletonDirectory))
{ {
to = Path.Combine(string.Concat(aPropertySingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); to = Path.Combine(string.Concat(aPropertySingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
@ -83,10 +82,10 @@ internal class E3_Rename
to = Path.Combine(string.Concat(dFacesCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); to = Path.Combine(string.Concat(dFacesCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to); results.Add(to);
} }
d2FaceLandmarksContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(D2_FaceLandmarks), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); d2FacePartsContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(D2_FaceParts), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
if (add && _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution) && Directory.Exists(d2FaceLandmarksContentDirectory)) if (add && _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution) && Directory.Exists(d2FacePartsContentDirectory))
{ {
to = Path.Combine(string.Concat(d2FaceLandmarksContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); to = Path.Combine(string.Concat(d2FacePartsContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to); results.Add(to);
} }
eDistanceContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); eDistanceContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
@ -114,8 +113,6 @@ internal class E3_Rename
internal List<string[]> GetDirectoryRenameCollections(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny) internal List<string[]> GetDirectoryRenameCollections(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny)
{ {
List<string[]> results = new(); List<string[]> results = new();
if (_Configuration?.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
bool add; bool add;
string to; string to;
bool exists; bool exists;
@ -127,9 +124,9 @@ internal class E3_Rename
string eDistanceContentDirectory; string eDistanceContentDirectory;
string bMetadataSingletonDirectory; string bMetadataSingletonDirectory;
string aPropertySingletonDirectory; string aPropertySingletonDirectory;
string d2FacePartsContentDirectory;
string eDistanceCollectionDirectory; string eDistanceCollectionDirectory;
string g2IdentifyCollectionDirectory; string g2IdentifyCollectionDirectory;
string d2FaceLandmarksContentDirectory;
if (!string.IsNullOrEmpty(relativePath)) if (!string.IsNullOrEmpty(relativePath))
{ {
from = string.Concat(_Configuration.PropertyConfiguration.RootDirectory, relativePath); from = string.Concat(_Configuration.PropertyConfiguration.RootDirectory, relativePath);
@ -147,7 +144,7 @@ internal class E3_Rename
to = Path.Combine(string.Concat(bMetadataSingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); to = Path.Combine(string.Concat(bMetadataSingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to }); results.Add(new string[] { from, to });
} }
aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(Property.Models.A_Property), "{}");
from = string.Concat(aPropertySingletonDirectory, relativePath); from = string.Concat(aPropertySingletonDirectory, relativePath);
exists = Directory.Exists(aPropertySingletonDirectory); exists = Directory.Exists(aPropertySingletonDirectory);
if (exists) if (exists)
@ -187,14 +184,14 @@ internal class E3_Rename
to = Path.Combine(string.Concat(dFacesCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); to = Path.Combine(string.Concat(dFacesCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to }); results.Add(new string[] { from, to });
} }
d2FaceLandmarksContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(D2_FaceLandmarks), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); d2FacePartsContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(D2_FaceParts), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
from = string.Concat(d2FaceLandmarksContentDirectory, relativePath); from = string.Concat(d2FacePartsContentDirectory, relativePath);
exists = Directory.Exists(d2FaceLandmarksContentDirectory); exists = Directory.Exists(d2FacePartsContentDirectory);
if (!exists && add && _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) if (!exists && add && _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
results.Add(new string[] { from }); results.Add(new string[] { from });
else if (exists) else if (exists)
{ {
to = Path.Combine(string.Concat(d2FaceLandmarksContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName); to = Path.Combine(string.Concat(d2FacePartsContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to }); results.Add(new string[] { from, to });
} }
eDistanceContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()"); eDistanceContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
@ -229,15 +226,13 @@ internal class E3_Rename
internal void DirectoryRename(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string relativePath, string newDirectoryName) internal void DirectoryRename(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string relativePath, string newDirectoryName)
{ {
if (_Configuration?.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
string json; string json;
FileInfo current; FileInfo current;
FileInfo fileInfo; FileInfo fileInfo;
string error = "Error"; string error = "Error";
string target = "Target"; string target = "Target";
string pending = "Pending"; string pending = "Pending";
System.IO.DirectoryInfo directoryInfo; DirectoryInfo directoryInfo;
IEnumerator<FileInfo> fileInfoCollection; IEnumerator<FileInfo> fileInfoCollection;
string oldValue = string.Concat("\"", relativePath); string oldValue = string.Concat("\"", relativePath);
string oldDirectoryName = Path.GetFileName(relativePath); string oldDirectoryName = Path.GetFileName(relativePath);
@ -249,7 +244,7 @@ internal class E3_Rename
string newValue = string.Concat("\"", Path.Combine(relativePathParent, newDirectoryName)); string newValue = string.Concat("\"", Path.Combine(relativePathParent, newDirectoryName));
string e3RenameContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(E3_Rename), "()"); string e3RenameContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(E3_Rename), "()");
string jsonRootDirectory = Path.Combine(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, " - Copied"), string.Concat(directoryName, " - 4) Info"), _Configuration.PropertyConfiguration.DateGroup, "[]"); string jsonRootDirectory = Path.Combine(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, " - Copied"), string.Concat(directoryName, " - 4) Info"), _Configuration.PropertyConfiguration.DateGroup, "[]");
directoryInfo = new System.IO.DirectoryInfo(jsonRootDirectory); directoryInfo = new DirectoryInfo(jsonRootDirectory);
if (!directoryInfo.Exists) if (!directoryInfo.Exists)
directoryInfo.Create(); directoryInfo.Create();
IEnumerator<FileInfo> fileInfoCollection4 = directoryInfo.EnumerateFiles("*.json", SearchOption.AllDirectories).GetEnumerator(); IEnumerator<FileInfo> fileInfoCollection4 = directoryInfo.EnumerateFiles("*.json", SearchOption.AllDirectories).GetEnumerator();
@ -278,7 +273,7 @@ internal class E3_Rename
{ {
foreach (string[] directoryCollection in directoryCollections) foreach (string[] directoryCollection in directoryCollections)
{ {
directoryInfo = new System.IO.DirectoryInfo(directoryCollection[0]); directoryInfo = new DirectoryInfo(directoryCollection[0]);
if (!directoryInfo.Exists) if (!directoryInfo.Exists)
continue; continue;
fileInfoCollection = directoryInfo.EnumerateFiles("*.json", SearchOption.AllDirectories).GetEnumerator(); fileInfoCollection = directoryInfo.EnumerateFiles("*.json", SearchOption.AllDirectories).GetEnumerator();
@ -299,7 +294,7 @@ internal class E3_Rename
if (json.Contains(oldValue)) if (json.Contains(oldValue))
{ {
json = json.Replace(oldValue, newValue); json = json.Replace(oldValue, newValue);
if (!Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true)) if (!Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true))
continue; continue;
File.SetLastWriteTime(fileInfo.FullName, fileInfo.LastWriteTime); File.SetLastWriteTime(fileInfo.FullName, fileInfo.LastWriteTime);
} }

View File

@ -4,6 +4,7 @@ using View_by_Distance.FaceRecognitionDotNet;
using View_by_Distance.Metadata.Models; using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models; using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models; using View_by_Distance.Resize.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
using WindowsShortcutFactory; using WindowsShortcutFactory;
@ -30,14 +31,14 @@ internal class E_Distance
return result; return result;
} }
private static List<DistanceHolder> GetDistanceHolder(Item[] items, List<(string JSONDirectory, string TSVDirectory)> directories) private static List<(DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)> GetDistanceHolder(Item[] items, List<(string JSONDirectory, string TSVDirectory)> directories)
{ {
List<DistanceHolder> results = new(); List<(DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)> results = new();
Item item; Item item;
const int zero = 0; const int zero = 0;
string tsvDirectory; string tsvDirectory;
string jsonDirectory; string jsonDirectory;
FaceEncoding? faceEncoding; FaceRecognitionDotNet.FaceEncoding? faceEncoding;
if (items.Length != directories.Count) if (items.Length != directories.Count)
throw new Exception(); throw new Exception();
for (int i = 0; i < items.Length; i++) for (int i = 0; i < items.Length; i++)
@ -48,38 +49,19 @@ internal class E_Distance
continue; continue;
tsvDirectory = directories[i].TSVDirectory; tsvDirectory = directories[i].TSVDirectory;
jsonDirectory = directories[i].JSONDirectory; jsonDirectory = directories[i].JSONDirectory;
foreach (IFace face in item.Faces) foreach (Face face in item.Faces)
{ {
if (!face.Populated) if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue; continue;
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
results.Add(new(face, faceEncoding, item.ImageFileHolder, item.Property.Id.Value, jsonDirectory, item.Faces[zero].Location, tsvDirectory)); results.Add(new(new(face, item.ImageFileHolder, item.Property.Id.Value, jsonDirectory, item.Faces[zero].Location, tsvDirectory), faceEncoding));
} }
if (faceEncoding is null) if (faceEncoding is null)
results.Add(new(item.Faces[zero], null, item.ImageFileHolder, item.Property.Id.Value, jsonDirectory, item.Faces[zero].Location, tsvDirectory)); results.Add(new(new(item.Faces[zero], item.ImageFileHolder, item.Property.Id.Value, jsonDirectory, item.Faces[zero].Location, tsvDirectory), null));
} }
return results; return results;
} }
private List<Tuple<IFace, string>> GetOrderedNoFaceCollection(List<List<IFace>> faceCollections, int i, IFace face)
{
List<Tuple<IFace, string>> results = new() { new(face, string.Empty) };
for (int n = 0; n < faceCollections.Count; n++)
{
if (i == n)
continue;
for (int j = 0; j < faceCollections[n].Count; j++)
{
if (!faceCollections[n][j].Populated)
continue;
results.Add(new(faceCollections[n][j], string.Empty));
}
}
for (int r = results.Count - 1; r > _Configuration.MaxItemsInDistanceCollection; r--)
results.RemoveAt(r);
return results;
}
private void WriteNoFaceCollection(bool updateDateWhenMatches, DateTime? updateToWhenMatches, List<Tuple<string, DateTime>> subFileTuples, List<DistanceHolder> distanceHolders) private void WriteNoFaceCollection(bool updateDateWhenMatches, DateTime? updateToWhenMatches, List<Tuple<string, DateTime>> subFileTuples, List<DistanceHolder> distanceHolders)
{ {
string json; string json;
@ -87,7 +69,7 @@ internal class E_Distance
string jsonFile; string jsonFile;
const int zero = 0; const int zero = 0;
DistanceHolder distanceHolder; DistanceHolder distanceHolder;
List<Tuple<IFace, string>> tupleCollection; List<Tuple<Face, string>> tupleCollection;
for (int i = 0; i < distanceHolders.Count; i++) for (int i = 0; i < distanceHolders.Count; i++)
{ {
distanceHolder = distanceHolders[i]; distanceHolder = distanceHolders[i];
@ -108,24 +90,24 @@ internal class E_Distance
break; break;
} }
json = JsonSerializer.Serialize(tupleCollection, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(tupleCollection, _WriteIndentedJsonSerializerOptions);
if (Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: updateToWhenMatches)) if (Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: updateToWhenMatches))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), DateTime.Now)); subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), DateTime.Now));
} }
} }
private static List<FaceEncoding> GetFaceEncodings(List<DistanceHolder> distanceHolders) private static List<FaceRecognitionDotNet.FaceEncoding> GetFaceEncodings((DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)[] distanceHoldersAfterSort)
{ {
List<FaceEncoding> results = new(); List<FaceRecognitionDotNet.FaceEncoding> results = new();
foreach (DistanceHolder distanceHolder in distanceHolders) foreach ((DistanceHolder distanceHolder, FaceRecognitionDotNet.FaceEncoding? faceEncoding) in distanceHoldersAfterSort)
{ {
if (!distanceHolder.Face.Populated || distanceHolder.FaceEncoding is null) if (distanceHolder.Face.FaceEncoding is null || distanceHolder.Face.Location?.NormalizedPixelPercentage is null || faceEncoding is null)
continue; continue;
results.Add(distanceHolder.FaceEncoding); results.Add(faceEncoding);
} }
return results; return results;
} }
private void SaveDistanceResults(bool updateDateWhenMatches, DateTime? updateToWhenMatches, List<Tuple<string, DateTime>> subFileTuples, List<DistanceHolder> distanceHolders) private void SaveDistanceResults(bool updateDateWhenMatches, DateTime? updateToWhenMatches, List<Tuple<string, DateTime>> subFileTuples, List<(DistanceHolder DistanceHolder, FaceRecognitionDotNet.FaceEncoding? _)> distanceHolders)
{ {
string json; string json;
string check; string check;
@ -135,13 +117,16 @@ internal class E_Distance
DistanceHolder distanceHolder; DistanceHolder distanceHolder;
int normalizedPixelPercentage; int normalizedPixelPercentage;
DistanceHolder[] sortedDistanceHolders; DistanceHolder[] sortedDistanceHolders;
List<Tuple<IFace, string>> tupleCollection; List<Tuple<Face, string>> tupleCollection;
List<(int Index, double Distance)> collection; List<(int Index, double Distance)> collection;
distanceHolders = distanceHolders.OrderByDescending(l => l.Face.Populated).ToList(); FaceRecognitionDotNet.FaceEncoding? faceEncoding;
List<FaceEncoding> faceEncodings = GetFaceEncodings(distanceHolders); (DistanceHolder DistanceHolder, FaceRecognitionDotNet.FaceEncoding? FaceEncoding)[] distanceHoldersAfterSort =
for (int i = 0; i < distanceHolders.Count; i++) distanceHolders.OrderByDescending(l => l.DistanceHolder.Face.FaceEncoding is not null && l.DistanceHolder.Face.Location?.NormalizedPixelPercentage is not null).ToArray();
List<FaceRecognitionDotNet.FaceEncoding> faceEncodings = GetFaceEncodings(distanceHoldersAfterSort);
for (int i = 0; i < distanceHoldersAfterSort.Length; i++)
{ {
distanceHolder = distanceHolders[i]; faceEncoding = distanceHoldersAfterSort[i].FaceEncoding;
distanceHolder = distanceHoldersAfterSort[i].DistanceHolder;
collection = new(); collection = new();
tupleCollection = new(); tupleCollection = new();
distanceHolder.Sort = 0d; distanceHolder.Sort = 0d;
@ -149,7 +134,7 @@ internal class E_Distance
locationIndex = 0; locationIndex = 0;
else else
locationIndex = distanceHolder.Face.LocationIndex.Value; locationIndex = distanceHolder.Face.LocationIndex.Value;
if (!distanceHolder.Face.Populated || distanceHolder.Face.Location?.NormalizedPixelPercentage is null) if (distanceHolder.Face.FaceEncoding is null || distanceHolder.Face.Location?.NormalizedPixelPercentage is null)
normalizedPixelPercentage = 0; normalizedPixelPercentage = 0;
else else
normalizedPixelPercentage = distanceHolder.Face.Location.NormalizedPixelPercentage.Value; normalizedPixelPercentage = distanceHolder.Face.Location.NormalizedPixelPercentage.Value;
@ -161,27 +146,32 @@ internal class E_Distance
File.Move(check, jsonFile); File.Move(check, jsonFile);
if (faceEncodings.Count == 1) if (faceEncodings.Count == 1)
faceDistances = new() { 0d }; faceDistances = new() { 0d };
else if (distanceHolder.FaceEncoding is null) else if (faceEncoding is null)
faceDistances = Enumerable.Repeat(9d, faceEncodings.Count).ToList(); faceDistances = Enumerable.Repeat(9d, faceEncodings.Count).ToList();
else else
faceDistances = FaceRecognition.FaceDistances(faceEncodings, distanceHolder.FaceEncoding); faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncoding);
if (distanceHolder.Face.Populated && distanceHolder.FaceEncoding is not null && faceDistances[i] != 0d) if (distanceHolder.Face.FaceEncoding is not null && faceEncoding is not null && faceDistances[i] != 0d)
faceDistances[i] = 0d; faceDistances[i] = 0d;
for (int d = 0; d < faceDistances.Count; d++) for (int d = 0; d < faceDistances.Count; d++)
collection.Add(new(d, faceDistances[d])); collection.Add(new(d, faceDistances[d]));
collection = collection.OrderBy(l => l.Distance).ToList(); collection = collection.OrderBy(l => l.Distance).ToList();
foreach ((int index, double distance) in collection) foreach ((int index, double distance) in collection)
distanceHolders[index].Sort = ((distance * _Configuration.DistanceFactor) + (distanceHolders[index].Location.Confidence * _Configuration.LocationConfidenceFactor)) / 10; {
sortedDistanceHolders = distanceHolders.OrderBy(l => l.Sort).ToArray(); distanceHolder = distanceHoldersAfterSort[index].DistanceHolder;
if (distanceHolder.Location is null)
continue;
distanceHolder.Sort = ((distance * _Configuration.DistanceFactor) + (distanceHolder.Location.Confidence * _Configuration.LocationConfidenceFactor)) / 10;
}
sortedDistanceHolders = (from l in distanceHoldersAfterSort orderby l.DistanceHolder.Sort select l.DistanceHolder).ToArray();
for (int j = 0; j < sortedDistanceHolders.Length; j++) for (int j = 0; j < sortedDistanceHolders.Length; j++)
{ {
distanceHolder = sortedDistanceHolders[j]; distanceHolder = sortedDistanceHolders[j];
tupleCollection.Add(new(distanceHolders[j].Face, string.Empty)); tupleCollection.Add(new(distanceHoldersAfterSort[j].DistanceHolder.Face, string.Empty));
if (tupleCollection.Count > _Configuration.MaxItemsInDistanceCollection) if (tupleCollection.Count > _Configuration.MaxItemsInDistanceCollection)
break; break;
} }
json = JsonSerializer.Serialize(tupleCollection, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(tupleCollection, _WriteIndentedJsonSerializerOptions);
if (Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: updateToWhenMatches)) if (Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: updateToWhenMatches))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), DateTime.Now)); subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), DateTime.Now));
} }
} }
@ -196,10 +186,12 @@ internal class E_Distance
string usingRelativePath; string usingRelativePath;
DateTime? dateTime = null; DateTime? dateTime = null;
string dCollectionDirectory; string dCollectionDirectory;
FileInfo[] fileInfoCollection;
bool updateDateWhenMatches = false; bool updateDateWhenMatches = false;
System.IO.DirectoryInfo directoryInfo; System.IO.DirectoryInfo directoryInfo;
System.IO.DirectoryInfo tvsDirectoryInfo; System.IO.DirectoryInfo tvsDirectoryInfo;
IEnumerator<FileInfo> fileInfoCollection; int?[] normalizedPixelPercentageCollection;
int normalizedPixelPercentageDistinctCount;
List<(string, string)> directories = new(); List<(string, string)> directories = new();
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) };
List<DateTime> dateTimes = (from l in sourceDirectoryChanges where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in sourceDirectoryChanges where changesFrom.Contains(l.Item1) select l.Item2).ToList();
@ -216,7 +208,7 @@ internal class E_Distance
item = filteredItems[i]; item = filteredItems[i];
if (item.ImageFileHolder is null || item.Property?.Id is null) if (item.ImageFileHolder is null || item.Property?.Id is null)
continue; continue;
hasPopulatedFace = (from l in item.Faces where l.Populated select true).Any(); hasPopulatedFace = (from l in item.Faces where l.FaceEncoding is not null && l.Location?.NormalizedPixelPercentage is not null select true).Any();
usingRelativePath = Path.Combine(directoryInfoCollection[0].Replace("<>", "[]"), item.ImageFileHolder.NameWithoutExtension); usingRelativePath = Path.Combine(directoryInfoCollection[0].Replace("<>", "[]"), item.ImageFileHolder.NameWithoutExtension);
dCollectionDirectory = Path.Combine(eResultsFullGroupDirectory, "[]", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}"); dCollectionDirectory = Path.Combine(eResultsFullGroupDirectory, "[]", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}");
directoryInfo = new System.IO.DirectoryInfo(dCollectionDirectory); directoryInfo = new System.IO.DirectoryInfo(dCollectionDirectory);
@ -242,16 +234,22 @@ internal class E_Distance
} }
tvsDirectoryInfo = new System.IO.DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension)); tvsDirectoryInfo = new System.IO.DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension));
directories.Add(new(directoryInfo.FullName, tvsDirectoryInfo.FullName)); directories.Add(new(directoryInfo.FullName, tvsDirectoryInfo.FullName));
if (_Configuration.CheckJsonForDistanceResults && directoryInfo.Exists) if (directoryInfo.Exists && (!check || _Configuration.CheckJsonForDistanceResults))
{ {
json = string.Empty; json = string.Empty;
fileInfoCollection = directoryInfo.EnumerateFiles("*.json", SearchOption.AllDirectories).GetEnumerator(); normalizedPixelPercentageCollection = Shared.Models.Stateless.Methods.IFace.GetInts(item.Faces);
for (int j = 0; j < int.MaxValue; j++) normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count();
if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length)
check = true;
fileInfoCollection = directoryInfo.GetFiles($"{item.Property.Id.Value}*.json", SearchOption.TopDirectoryOnly);
if (fileInfoCollection.Length < normalizedPixelPercentageDistinctCount)
check = true;
if (!check && _Configuration.CheckJsonForDistanceResults)
{ {
if (!fileInfoCollection.MoveNext()) for (int j = 0; j < fileInfoCollection.Length; j++)
break; {
json = Shared.Models.Stateless.Methods.IIndex.GetJson(fileInfoCollection.Current.FullName, fileInfoCollection.Current); json = Shared.Models.Stateless.Methods.IIndex.GetJson(fileInfoCollection[j].FullName, fileInfoCollection[j]);
if (!_Configuration.PropertiesChangedForDistance && Shared.Models.Stateless.Methods.IFace.GetFace(fileInfoCollection.Current.FullName) is null) if (!_Configuration.PropertiesChangedForDistance && Shared.Models.Stateless.Methods.IFace.GetFace(fileInfoCollection[j].FullName) is null)
{ {
check = true; check = true;
break; break;
@ -260,6 +258,7 @@ internal class E_Distance
if (!check && string.IsNullOrEmpty(json)) if (!check && string.IsNullOrEmpty(json))
check = true; check = true;
} }
}
if (check) if (check)
continue; continue;
if (_Configuration.PropertiesChangedForDistance) if (_Configuration.PropertiesChangedForDistance)
@ -278,23 +277,23 @@ internal class E_Distance
{ {
DateTime? updateToWhenMatches = dateTime; DateTime? updateToWhenMatches = dateTime;
List<Tuple<string, DateTime>> subFileTuples = new(); List<Tuple<string, DateTime>> subFileTuples = new();
List<DistanceHolder> distanceHolders = GetDistanceHolder(filteredItems, directories); List<(DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)> distanceHolders = GetDistanceHolder(filteredItems, directories);
SaveDistanceResults(updateDateWhenMatches, updateToWhenMatches, subFileTuples, distanceHolders); SaveDistanceResults(updateDateWhenMatches, updateToWhenMatches, subFileTuples, distanceHolders);
} }
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(directoryInfoCollection[0].Replace("<>", "()")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(directoryInfoCollection[0].Replace("<>", "()"));
} }
private List<(string, List<KeyValuePair<string, Shared.Models.Face[]>>)> GetFiles(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution) private List<(string, List<KeyValuePair<string, Face[]>>)> GetFiles(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution)
{ {
string json; string json;
List<KeyValuePair<string, Shared.Models.Face[]>>? facesKeyValuePairCollection; List<KeyValuePair<string, Face[]>>? facesKeyValuePairCollection;
List<(string, List<KeyValuePair<string, Shared.Models.Face[]>>)> results = new(); List<(string, List<KeyValuePair<string, Face[]>>)> results = new();
string dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[[]]"); string dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[[]]");
string[] dFacesCollectionFiles = Directory.GetFiles(dFacesCollectionDirectory, "*.json", SearchOption.TopDirectoryOnly); string[] dFacesCollectionFiles = Directory.GetFiles(dFacesCollectionDirectory, "*.json", SearchOption.TopDirectoryOnly);
foreach (string dFacesCollectionFile in dFacesCollectionFiles) foreach (string dFacesCollectionFile in dFacesCollectionFiles)
{ {
json = File.ReadAllText(dFacesCollectionFile); json = File.ReadAllText(dFacesCollectionFile);
facesKeyValuePairCollection = JsonSerializer.Deserialize<List<KeyValuePair<string, Shared.Models.Face[]>>>(json); facesKeyValuePairCollection = JsonSerializer.Deserialize<List<KeyValuePair<string, Face[]>>>(json);
if (facesKeyValuePairCollection is null) if (facesKeyValuePairCollection is null)
continue; continue;
results.Add(new(dFacesCollectionFile, facesKeyValuePairCollection)); results.Add(new(dFacesCollectionFile, facesKeyValuePairCollection));
@ -302,21 +301,21 @@ internal class E_Distance
return results; return results;
} }
private static List<(string, List<Shared.Models.Face>, List<FaceEncoding>)> GetMatches(List<(string, List<KeyValuePair<string, Shared.Models.Face[]>>)> files) private static List<(string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>)> GetMatches(List<(string, List<KeyValuePair<string, Face[]>>)> files)
{ {
List<(string, List<Shared.Models.Face>, List<FaceEncoding>)> results = new(); List<(string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>)> results = new();
FaceEncoding faceEncoding; FaceRecognitionDotNet.FaceEncoding faceEncoding;
List<Shared.Models.Face> faces; List<Face> faces;
List<FaceEncoding> faceEncodings; List<FaceRecognitionDotNet.FaceEncoding> faceEncodings;
foreach ((string, List<KeyValuePair<string, Shared.Models.Face[]>>) file in files) foreach ((string, List<KeyValuePair<string, Face[]>>) file in files)
{ {
faces = new(); faces = new();
faceEncodings = new(); faceEncodings = new();
foreach (KeyValuePair<string, Shared.Models.Face[]> keyValuePair in file.Item2) foreach (KeyValuePair<string, Face[]> keyValuePair in file.Item2)
{ {
foreach (Shared.Models.Face face in keyValuePair.Value) foreach (Face face in keyValuePair.Value)
{ {
if (!face.Populated) if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue; continue;
faces.Add(face); faces.Add(face);
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
@ -339,7 +338,7 @@ internal class E_Distance
return result; return result;
} }
private void Save(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, string eDistanceCollectionDirectory, int k, string relativePath, Shared.Models.Face face, List<Tuple<Shared.Models.Face, string>> faceAndFaceDistanceCollection) private void Save(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, string eDistanceCollectionDirectory, int k, string relativePath, Face face, List<Tuple<Face, string>> faceAndFaceDistanceCollection)
{ {
if (string.IsNullOrEmpty(eDistanceCollectionDirectory)) if (string.IsNullOrEmpty(eDistanceCollectionDirectory))
eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
@ -349,12 +348,12 @@ internal class E_Distance
_ = Directory.CreateDirectory(jsonDirectory); _ = Directory.CreateDirectory(jsonDirectory);
string json = JsonSerializer.Serialize(faceAndFaceDistanceCollection, _WriteIndentedJsonSerializerOptions); string json = JsonSerializer.Serialize(faceAndFaceDistanceCollection, _WriteIndentedJsonSerializerOptions);
string jsonFile = Path.Combine(jsonDirectory, $"{k} - {fileNameWithoutExtension}.nosj"); string jsonFile = Path.Combine(jsonDirectory, $"{k} - {fileNameWithoutExtension}.nosj");
_ = Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: true, compareBeforeWrite: true); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: true, compareBeforeWrite: true);
} }
private static Tuple<Shared.Models.Face, double> Get(FaceEncoding faceEncoding, (string, List<Shared.Models.Face>, List<FaceEncoding>) match) private static Tuple<Face, double> Get(FaceRecognitionDotNet.FaceEncoding faceEncoding, (string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>) match)
{ {
Tuple<Shared.Models.Face, double> result; Tuple<Face, double> result;
double[] faceDistances = FaceRecognition.FaceDistances(match.Item3, faceEncoding).ToArray(); double[] faceDistances = FaceRecognition.FaceDistances(match.Item3, faceEncoding).ToArray();
int index = GetIndex(faceDistances); int index = GetIndex(faceDistances);
result = new(match.Item2[index], faceDistances[index]); result = new(match.Item2[index], faceDistances[index]);
@ -366,14 +365,14 @@ internal class E_Distance
if (_Log is null) if (_Log is null)
throw new NullReferenceException(nameof(_Log)); throw new NullReferenceException(nameof(_Log));
string? relativePath; string? relativePath;
Shared.Models.Face face; Face face;
ParallelOptions parallelOptions = new(); ParallelOptions parallelOptions = new();
FaceEncoding faceEncoding; FaceRecognitionDotNet.FaceEncoding faceEncoding;
string eDistanceCollectionDirectory = string.Empty; string eDistanceCollectionDirectory = string.Empty;
Tuple<Shared.Models.Face, double> faceAndFaceDistance; Tuple<Face, double> faceAndFaceDistance;
List<Tuple<Shared.Models.Face, string>> faceAndFaceDistanceCollection; List<Tuple<Face, string>> faceAndFaceDistanceCollection;
List<(string, List<KeyValuePair<string, Shared.Models.Face[]>>)> files = GetFiles(configuration, model, predictorModel, outputResolution); List<(string, List<KeyValuePair<string, Face[]>>)> files = GetFiles(configuration, model, predictorModel, outputResolution);
List<(string, List<Shared.Models.Face>, List<FaceEncoding>)> matches = GetMatches(files); List<(string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>)> matches = GetMatches(files);
if (files.Count != matches.Count) if (files.Count != matches.Count)
throw new Exception(); throw new Exception();
int filesCount = files.Count; int filesCount = files.Count;
@ -386,13 +385,15 @@ internal class E_Distance
continue; continue;
for (int k = 0; k < files[i].Item2[j].Value.Length; k++) for (int k = 0; k < files[i].Item2[j].Value.Length; k++)
{ {
if (!files[i].Item2[j].Value[k].Populated)
continue;
face = files[i].Item2[j].Value[k]; face = files[i].Item2[j].Value[k];
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue;
faceAndFaceDistanceCollection = new(matches.Count); faceAndFaceDistanceCollection = new(matches.Count);
relativePath = Path.GetDirectoryName(face.RelativePath); relativePath = Path.GetDirectoryName(face.RelativePath);
if (string.IsNullOrEmpty(relativePath)) if (string.IsNullOrEmpty(relativePath))
continue; continue;
if (face.FaceEncoding is null)
continue;
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
_ = Parallel.For(0, matches.Count, parallelOptions, z => _ = Parallel.For(0, matches.Count, parallelOptions, z =>
{ {
@ -423,32 +424,32 @@ internal class E_Distance
return result; return result;
} }
private static FaceEncoding? GetFaceEncoding(IFace face) private static FaceRecognitionDotNet.FaceEncoding? GetFaceEncoding(Face face)
{ {
FaceEncoding? result; FaceRecognitionDotNet.FaceEncoding? result;
if (!face.Populated) if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
result = null; result = null;
else else
result = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); result = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
return result; return result;
} }
private static (int index, double sum) GetIndexAndSum(int i, List<FaceEncoding> results) private static (int index, double sum) GetIndexAndSum(int i, List<FaceRecognitionDotNet.FaceEncoding> results)
{ {
List<double> faceDistances = FaceRecognition.FaceDistances(results, results[i]); List<double> faceDistances = FaceRecognition.FaceDistances(results, results[i]);
return new(i, faceDistances.Sum()); return new(i, faceDistances.Sum());
} }
private static List<FaceEncoding> GetFaceEncodings(int maxDegreeOfParallelism, List<(DateTime MinimumDateTime, bool? IsWrongYear, Shared.Models.PersonBirthday PersonBirthday, IFace Face)> collection) private static List<FaceRecognitionDotNet.FaceEncoding> GetFaceEncodings(int maxDegreeOfParallelism, List<(DateTime MinimumDateTime, bool? IsWrongYear, PersonBirthday PersonBirthday, Face Face)> collection)
{ {
List<FaceEncoding> results; List<FaceRecognitionDotNet.FaceEncoding> results;
if (maxDegreeOfParallelism == 1) if (maxDegreeOfParallelism == 1)
{ {
results = new(); results = new();
FaceEncoding faceEncoding; FaceRecognitionDotNet.FaceEncoding faceEncoding;
foreach ((DateTime _, bool? _, Shared.Models.PersonBirthday _, IFace face) in collection) foreach ((DateTime _, bool? _, PersonBirthday _, Face face) in collection)
{ {
if (!face.Populated) if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue; continue;
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
results.Add(faceEncoding); results.Add(faceEncoding);
@ -460,7 +461,7 @@ internal class E_Distance
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
_ = Parallel.For(0, collection.Count, parallelOptions, i => _ = Parallel.For(0, collection.Count, parallelOptions, i =>
{ {
FaceEncoding? faceEncoding = GetFaceEncoding(collection[i].Face); FaceRecognitionDotNet.FaceEncoding? faceEncoding = GetFaceEncoding(collection[i].Face);
if (faceEncoding is not null) if (faceEncoding is not null)
{ {
lock (results) lock (results)
@ -518,12 +519,12 @@ internal class E_Distance
return results; return results;
} }
private static List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> GetThreeSigmaFaceEncodings(int maxDegreeOfParallelism, Dictionary<string, List<(DateTime, bool?, Shared.Models.PersonBirthday, IFace)>> keyValuePairs) private static List<(DateTime, bool?, PersonBirthday, FaceRecognitionDotNet.FaceEncoding[])> GetThreeSigmaFaceEncodings(int maxDegreeOfParallelism, Dictionary<string, List<(DateTime, bool?, PersonBirthday, Face)>> keyValuePairs)
{ {
List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> results = new(); List<(DateTime, bool?, PersonBirthday, FaceRecognitionDotNet.FaceEncoding[])> results = new();
const int zero = 0; const int zero = 0;
List<FaceEncoding> faceEncodings; List<FaceRecognitionDotNet.FaceEncoding> faceEncodings;
foreach (KeyValuePair<string, List<(DateTime MinimumDateTime, bool? IsWrongYear, Shared.Models.PersonBirthday PersonBirthday, IFace _)>> keyValuePair in keyValuePairs) foreach (KeyValuePair<string, List<(DateTime MinimumDateTime, bool? IsWrongYear, PersonBirthday PersonBirthday, Face _)>> keyValuePair in keyValuePairs)
{ {
faceEncodings = GetFaceEncodings(maxDegreeOfParallelism, keyValuePair.Value); faceEncodings = GetFaceEncodings(maxDegreeOfParallelism, keyValuePair.Value);
results.Add(new(keyValuePair.Value[zero].MinimumDateTime, keyValuePair.Value[zero].IsWrongYear, keyValuePair.Value[zero].PersonBirthday, faceEncodings.ToArray())); results.Add(new(keyValuePair.Value[zero].MinimumDateTime, keyValuePair.Value[zero].IsWrongYear, keyValuePair.Value[zero].PersonBirthday, faceEncodings.ToArray()));
@ -531,7 +532,7 @@ internal class E_Distance
return results; return results;
} }
private static Closest? GetClosestParallelFor(DateTime minimumDateTime, bool? isWrongYear, IFace face, FaceEncoding faceEncoding, (DateTime MinimumDateTime, bool? IsWrongYear, Shared.Models.PersonBirthday PersonBirthday, FaceEncoding[] FaceEncodings) tuple) private static Closest? GetClosestParallelFor(DateTime minimumDateTime, bool? isWrongYear, Face face, FaceRecognitionDotNet.FaceEncoding faceEncoding, (DateTime MinimumDateTime, bool? IsWrongYear, PersonBirthday PersonBirthday, FaceRecognitionDotNet.FaceEncoding[] FaceEncodings) tuple)
{ {
Closest? result; Closest? result;
if (isWrongYear.HasValue && !isWrongYear.Value && minimumDateTime < tuple.PersonBirthday.Value) if (isWrongYear.HasValue && !isWrongYear.Value && minimumDateTime < tuple.PersonBirthday.Value)
@ -540,29 +541,31 @@ internal class E_Distance
{ {
List<double> faceDistances = FaceRecognition.FaceDistances(tuple.FaceEncodings, faceEncoding); List<double> faceDistances = FaceRecognition.FaceDistances(tuple.FaceEncodings, faceEncoding);
result = new(face.Location?.NormalizedPixelPercentage, tuple.MinimumDateTime, tuple.IsWrongYear, tuple.PersonBirthday, faceDistances); result = new(face.Location?.NormalizedPixelPercentage, tuple.MinimumDateTime, tuple.IsWrongYear, tuple.PersonBirthday, faceDistances);
if (result.Minimum > Closest.MaximumMinimum) if (result.Minimum > Shared.Models.Stateless.Methods.IClosest.MaximumMinimum)
result = null; result = null;
} }
return result; return result;
} }
private static Closest[] GetClosestCollection(int maxDegreeOfParallelism, List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> collection, DateTime itemMinimumDateTime, bool? itemIsWrongYear, IFace face) private static Closest[] GetClosestCollection(int maxDegreeOfParallelism, List<(DateTime, bool?, PersonBirthday, FaceRecognitionDotNet.FaceEncoding[])> collection, DateTime itemMinimumDateTime, bool? itemIsWrongYear, Face face)
{ {
Closest[] results; Closest[] results;
List<Closest> closestCollection; List<Closest> closestCollection;
FaceEncoding faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); if (face.FaceEncoding is null)
throw new NullReferenceException(nameof(face.FaceEncoding));
FaceRecognitionDotNet.FaceEncoding faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
if (maxDegreeOfParallelism == 1) if (maxDegreeOfParallelism == 1)
{ {
closestCollection = new(); closestCollection = new();
Closest closest; Closest closest;
List<double> faceDistances; List<double> faceDistances;
foreach ((DateTime minimumDateTime, bool? isWrongYear, Shared.Models.PersonBirthday personBirthday, FaceEncoding[] faceEncodings) in collection) foreach ((DateTime minimumDateTime, bool? isWrongYear, PersonBirthday personBirthday, FaceRecognitionDotNet.FaceEncoding[] faceEncodings) in collection)
{ {
if (itemIsWrongYear.HasValue && !itemIsWrongYear.Value && itemMinimumDateTime < personBirthday.Value) if (itemIsWrongYear.HasValue && !itemIsWrongYear.Value && itemMinimumDateTime < personBirthday.Value)
continue; continue;
faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncoding); faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncoding);
closest = new(face.Location?.NormalizedPixelPercentage, minimumDateTime, isWrongYear, personBirthday, faceDistances); closest = new(face.Location?.NormalizedPixelPercentage, minimumDateTime, isWrongYear, personBirthday, faceDistances);
if (closest.Minimum > Closest.MaximumMinimum) if (closest.Minimum > Shared.Models.Stateless.Methods.IClosest.MaximumMinimum)
continue; continue;
closestCollection.Add(closest); closestCollection.Add(closest);
} }
@ -581,14 +584,14 @@ internal class E_Distance
} }
}); });
} }
results = Closest.Get(closestCollection); results = Shared.Models.Stateless.Methods.IClosest.Get(closestCollection);
return results; return results;
} }
private static void AddClosest(int maxDegreeOfParallelism, string argZero, PropertyLogic propertyLogic, List<Container> containers, List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> collection) private static void AddClosest(int maxDegreeOfParallelism, string argZero, Map.Models.MapLogic mapLogic, List<Container> containers, List<(DateTime, bool?, PersonBirthday, FaceRecognitionDotNet.FaceEncoding[])> collection)
{ {
string key; string key;
IFace face; Face face;
Closest closest; Closest closest;
string personKey; string personKey;
bool? itemIsWrongYear; bool? itemIsWrongYear;
@ -606,11 +609,11 @@ internal class E_Distance
{ {
if (item.ImageFileHolder is null || item.Property is null || item.Named.Any()) if (item.ImageFileHolder is null || item.Property is null || item.Named.Any())
continue; continue;
itemMinimumDateTime = Property.Models.Stateless.A_Property.GetMinimumDateTime(item.Property); itemMinimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
if (itemMinimumDateTime is null) if (itemMinimumDateTime is null)
continue; continue;
(itemIsWrongYear, _) = item.IsWrongYear(); (itemIsWrongYear, _) = Map.Models.MapLogic.IsWrongYear(item);
if (Closest.SkipIsWrongYear && itemIsWrongYear.HasValue && itemIsWrongYear.Value) if (Shared.Models.Stateless.Methods.IClosest.SkipIsWrongYear && itemIsWrongYear.HasValue && itemIsWrongYear.Value)
continue; continue;
item.Closest.Clear(); item.Closest.Clear();
for (int i = 0; i < item.Faces.Count; i++) for (int i = 0; i < item.Faces.Count; i++)
@ -618,9 +621,9 @@ internal class E_Distance
face = item.Faces[i]; face = item.Faces[i];
closest = new(face.Location?.NormalizedPixelPercentage, itemMinimumDateTime.Value, itemIsWrongYear); closest = new(face.Location?.NormalizedPixelPercentage, itemMinimumDateTime.Value, itemIsWrongYear);
item.Closest.Add(closest); item.Closest.Add(closest);
if (!face.Populated) if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue; continue;
deterministicHashCodeKey = Named.GetDeterministicHashCodeKey(item, face); deterministicHashCodeKey = Shared.Models.Stateless.Methods.INamed.GetDeterministicHashCodeKey(item, face);
closestCollection = GetClosestCollection(maxDegreeOfParallelism, collection, itemMinimumDateTime.Value, itemIsWrongYear, face); closestCollection = GetClosestCollection(maxDegreeOfParallelism, collection, itemMinimumDateTime.Value, itemIsWrongYear, face);
for (int j = 0; j < closestCollection.Length; j++) for (int j = 0; j < closestCollection.Length; j++)
{ {
@ -628,12 +631,12 @@ internal class E_Distance
if (closest.PersonBirthday is null) if (closest.PersonBirthday is null)
continue; continue;
personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(closest.PersonBirthday); personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(closest.PersonBirthday);
if (propertyLogic.IncorrectDeterministicHashCodeKeyValuePairs.ContainsKey(deterministicHashCodeKey) && propertyLogic.IncorrectDeterministicHashCodeKeyValuePairs[deterministicHashCodeKey].Contains(personKey)) if (mapLogic.IncorrectDeterministicHashCodeKeyValuePairs.ContainsKey(deterministicHashCodeKey) && mapLogic.IncorrectDeterministicHashCodeKeyValuePairs[deterministicHashCodeKey].Contains(personKey))
continue; continue;
key = Item.GetKey(closest.MinimumDateTime, closest.IsWrongYear, closest.PersonBirthday); key = Map.Models.MapLogic.GetKey(closest.MinimumDateTime, closest.IsWrongYear, closest.PersonBirthday);
if (!results.ContainsKey(key)) if (!results.ContainsKey(key))
results.Add(key, 0); results.Add(key, 0);
else if (results[key] > Closest.MaximumPer) else if (results[key] > Shared.Models.Stateless.Methods.IClosest.MaximumPer)
continue; continue;
results[key] += 1; results[key] += 1;
item.Closest[0] = closest; item.Closest[0] = closest;
@ -644,12 +647,12 @@ internal class E_Distance
} }
} }
internal static List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> ParallelWork(int maxDegreeOfParallelism, string argZero, PropertyLogic propertyLogic, List<Container> containers) internal static List<(DateTime, bool?, PersonBirthday, FaceRecognitionDotNet.FaceEncoding[])> ParallelWork(int maxDegreeOfParallelism, string argZero, Map.Models.MapLogic mapLogic, List<Container> containers)
{ {
List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> results; List<(DateTime, bool?, PersonBirthday, FaceRecognitionDotNet.FaceEncoding[])> results;
Dictionary<string, List<(DateTime, bool?, Shared.Models.PersonBirthday, IFace)>> keyValuePairs = Item.GetKeyValuePairs(argZero, containers); Dictionary<string, List<(DateTime, bool?, PersonBirthday, Face)>> keyValuePairs = Map.Models.MapLogic.GetKeyValuePairs(argZero, containers);
results = GetThreeSigmaFaceEncodings(maxDegreeOfParallelism, keyValuePairs); results = GetThreeSigmaFaceEncodings(maxDegreeOfParallelism, keyValuePairs);
AddClosest(maxDegreeOfParallelism, argZero, propertyLogic, containers, results); AddClosest(maxDegreeOfParallelism, argZero, mapLogic, containers, results);
return results; return results;
} }
@ -677,27 +680,27 @@ internal class E_Distance
continue; continue;
if (!fileInfo.Directory.Exists) if (!fileInfo.Directory.Exists)
fileInfo.Directory.Create(); fileInfo.Directory.Create();
_ = Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true);
} }
} }
} }
internal static void SaveThreeSigmaFaceEncodings(List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> collection, Dictionary<string, List<Shared.Models.Person>> peopleCollection, string eDistanceCollectionDirectory) internal static void SaveThreeSigmaFaceEncodings(List<(DateTime, bool?, PersonBirthday, FaceRecognitionDotNet.FaceEncoding[])> collection, Dictionary<string, List<Person>> peopleCollection, string eDistanceCollectionDirectory)
{ {
string json; string json;
string checkFile; string checkFile;
string personKey; string personKey;
string directory; string directory;
List<double[]> rawEncodings; List<double[]> rawEncodings;
Shared.Models.Person person; Person person;
const string facePopulatedKey = "ThreeSigma"; const string facePopulatedKey = "ThreeSigma";
const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]"; const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]";
foreach ((DateTime minimumDateTime, bool? isWrongYear, Shared.Models.PersonBirthday personBirthday, FaceEncoding[] faceEncodings) in collection) foreach ((DateTime minimumDateTime, bool? isWrongYear, PersonBirthday personBirthday, FaceRecognitionDotNet.FaceEncoding[] faceEncodings) in collection)
{ {
rawEncodings = new(); rawEncodings = new();
checkFile = string.Empty; checkFile = string.Empty;
personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthday); personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthday);
directory = Item.GetDirectory(eDistanceCollectionDirectory, facePopulatedKey, minimumDateTime, isWrongYear, personBirthday, personKey); directory = Map.Models.MapLogic.GetDirectory(eDistanceCollectionDirectory, facePopulatedKey, minimumDateTime, isWrongYear, personBirthday, personKey);
if (!peopleCollection.ContainsKey(personKey)) if (!peopleCollection.ContainsKey(personKey))
continue; continue;
person = peopleCollection[personKey][0]; person = peopleCollection[personKey][0];
@ -709,13 +712,14 @@ internal class E_Distance
for (int i = 0; i < faceEncodings.Length; i++) for (int i = 0; i < faceEncodings.Length; i++)
rawEncodings.Add(faceEncodings[i].GetRawEncoding()); rawEncodings.Add(faceEncodings[i].GetRawEncoding());
json = JsonSerializer.Serialize(rawEncodings, new JsonSerializerOptions { WriteIndented = true }); json = JsonSerializer.Serialize(rawEncodings, new JsonSerializerOptions { WriteIndented = true });
_ = Property.Models.Stateless.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: true, compareBeforeWrite: true); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: true, compareBeforeWrite: true);
} }
} }
internal static List<(FileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile)> GetClosest(string argZero, List<Container> containers, Dictionary<string, List<Shared.Models.Person>> peopleCollection, string eDistanceContentDirectory, string dFacesContentDirectory) internal static List<(IFileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile)> GetClosest(string argZero, List<Container> containers, Dictionary<string, List<Person>> peopleCollection, string dFacesContentDirectory, string d2ResultsFullGroupDirectory, string eDistanceContentDirectory)
{ {
List<(FileHolder?, string, FileInfo?, string, string)> results = new(); List<(IFileHolder?, string, FileInfo?, string, string)> results = new();
Person person;
string checkFile; string checkFile;
string directory; string directory;
string personKey; string personKey;
@ -725,7 +729,8 @@ internal class E_Distance
string? directoryName; string? directoryName;
string facesDirectory; string facesDirectory;
string personDirectory; string personDirectory;
Shared.Models.Person person; FileInfo landmarkFileInfo;
string landmarksDirectory;
double deterministicHashCodeKey; double deterministicHashCodeKey;
const string facePopulatedKey = "Closest"; const string facePopulatedKey = "Closest";
const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]"; const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]";
@ -749,7 +754,7 @@ internal class E_Distance
if (closest.Average is null || closest.NormalizedPixelPercentage is null || closest.PersonBirthday is null) if (closest.Average is null || closest.NormalizedPixelPercentage is null || closest.PersonBirthday is null)
continue; continue;
personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(closest.PersonBirthday); personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(closest.PersonBirthday);
directory = Item.GetDirectory(eDistanceContentDirectory, facePopulatedKey, closest.MinimumDateTime, closest.IsWrongYear, closest.PersonBirthday, personKey); directory = Map.Models.MapLogic.GetDirectory(eDistanceContentDirectory, facePopulatedKey, closest.MinimumDateTime, closest.IsWrongYear, closest.PersonBirthday, personKey);
if (!peopleCollection.ContainsKey(personKey)) if (!peopleCollection.ContainsKey(personKey))
personDirectory = string.Empty; personDirectory = string.Empty;
else else
@ -760,9 +765,11 @@ internal class E_Distance
results.Add(new(null, personDirectory, null, string.Empty, string.Empty)); results.Add(new(null, personDirectory, null, string.Empty, string.Empty));
} }
facesDirectory = string.Concat(dFacesContentDirectory, Path.Combine(directoryName, item.ImageFileHolder.NameWithoutExtension)); facesDirectory = string.Concat(dFacesContentDirectory, Path.Combine(directoryName, item.ImageFileHolder.NameWithoutExtension));
deterministicHashCodeKey = Named.GetDeterministicHashCodeKey(item, closest); landmarksDirectory = string.Concat(d2ResultsFullGroupDirectory, Path.Combine(directoryName, item.ImageFileHolder.NameWithoutExtension));
deterministicHashCodeKey = Shared.Models.Stateless.Methods.INamed.GetDeterministicHashCodeKey(item, closest);
checkFile = Path.Combine(directory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}"); checkFile = Path.Combine(directory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}");
faceFileInfo = new(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}.png")); faceFileInfo = new(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}.png"));
landmarkFileInfo = new(Path.Combine(landmarksDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}.gif"));
if (string.IsNullOrEmpty(personDirectory)) if (string.IsNullOrEmpty(personDirectory))
shortcutFile = string.Empty; shortcutFile = string.Empty;
else else
@ -774,10 +781,10 @@ internal class E_Distance
return results; return results;
} }
internal static void SaveClosest(string argZero, List<Container> containers, Dictionary<string, List<Shared.Models.Person>> peopleCollection, string eDistanceContentDirectory, string dFacesContentDirectory) internal static void SaveClosest(string argZero, List<Container> containers, Dictionary<string, List<Person>> peopleCollection, string dFacesContentDirectory, string d2ResultsFullGroupDirectory, string eDistanceContentDirectory)
{ {
WindowsShortcut windowsShortcut; WindowsShortcut windowsShortcut;
List<(FileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile)> collection = GetClosest(argZero, containers, peopleCollection, eDistanceContentDirectory, dFacesContentDirectory); List<(IFileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile)> collection = GetClosest(argZero, containers, peopleCollection, dFacesContentDirectory, d2ResultsFullGroupDirectory, eDistanceContentDirectory);
string[] directories = (from l in collection select l.directory).Distinct().ToArray(); string[] directories = (from l in collection select l.directory).Distinct().ToArray();
foreach (string directory in directories) foreach (string directory in directories)
{ {
@ -786,7 +793,7 @@ internal class E_Distance
if (!Directory.Exists(directory)) if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory); _ = Directory.CreateDirectory(directory);
} }
foreach ((FileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile) in collection) foreach ((IFileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile) in collection)
{ {
if (string.IsNullOrEmpty(directory) || string.IsNullOrEmpty(checkFile) || resizedFileHolder is null || faceFileInfo is null) if (string.IsNullOrEmpty(directory) || string.IsNullOrEmpty(checkFile) || resizedFileHolder is null || faceFileInfo is null)
continue; continue;
@ -797,7 +804,7 @@ internal class E_Distance
else else
File.Copy(resizedFileHolder.FullName, checkFile); File.Copy(resizedFileHolder.FullName, checkFile);
} }
foreach ((FileHolder? resizedFileHolder, string directory, FileInfo? _, string checkFile, string shortcutFile) in collection) foreach ((IFileHolder? resizedFileHolder, string directory, FileInfo? _, string checkFile, string shortcutFile) in collection)
{ {
if (string.IsNullOrEmpty(directory) || string.IsNullOrEmpty(checkFile) || resizedFileHolder is null) if (string.IsNullOrEmpty(directory) || string.IsNullOrEmpty(checkFile) || resizedFileHolder is null)
continue; continue;

View File

@ -28,8 +28,6 @@ internal class F_Random
private bool IsIgnoreRelativePath(string directory) private bool IsIgnoreRelativePath(string directory)
{ {
bool result = false; bool result = false;
if (_Configuration?.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
string? checkDirectory = Path.GetFullPath(directory); string? checkDirectory = Path.GetFullPath(directory);
for (int i = 0; i < int.MaxValue; i++) for (int i = 0; i < int.MaxValue; i++)
{ {
@ -71,7 +69,7 @@ internal class F_Random
relativePaths = (from l in relativePaths orderby random.NextDouble() select l).ToList(); relativePaths = (from l in relativePaths orderby random.NextDouble() select l).ToList();
jsonFile = Path.Combine(fRandomCollectionDirectory, $"{dateTime.AddDays(i):MM-dd}.json"); jsonFile = Path.Combine(fRandomCollectionDirectory, $"{dateTime.AddDays(i):MM-dd}.json");
json = JsonSerializer.Serialize(relativePaths, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(relativePaths, _WriteIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: false, compareBeforeWrite: false); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: false, compareBeforeWrite: false);
if (!_Configuration.SaveFullYearOfRandomFiles) if (!_Configuration.SaveFullYearOfRandomFiles)
break; break;
} }
@ -81,7 +79,7 @@ internal class F_Random
ignoreRelativePaths = (from l in ignoreRelativePaths orderby random.NextDouble() select l).ToList(); ignoreRelativePaths = (from l in ignoreRelativePaths orderby random.NextDouble() select l).ToList();
jsonFile = Path.Combine(fRandomCollectionDirectory, "01-01.txt"); jsonFile = Path.Combine(fRandomCollectionDirectory, "01-01.txt");
json = JsonSerializer.Serialize(ignoreRelativePaths, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(ignoreRelativePaths, _WriteIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: false, compareBeforeWrite: false); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: false, compareBeforeWrite: false);
} }
} }

View File

@ -1,7 +1,6 @@
using Phares.Shared; using Phares.Shared;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods; using View_by_Distance.Shared.Models.Methods;
@ -103,7 +102,7 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify
json = JsonSerializer.Serialize(resultKeyValuePairs, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(resultKeyValuePairs, _WriteIndentedJsonSerializerOptions);
if (!isEnvironment.DebuggerWasAttachedDuringConstructor) if (!isEnvironment.DebuggerWasAttachedDuringConstructor)
throw new Exception("Only allowed when debugger is attached during constructor!"); throw new Exception("Only allowed when debugger is attached during constructor!");
_ = Property.Models.Stateless.IPath.WriteAllText(named.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(named.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true);
} }
} }
@ -189,7 +188,7 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify
string jsonFile; string jsonFile;
string directoryFullName; string directoryFullName;
string fileNameWithoutExtension; string fileNameWithoutExtension;
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(Property.Models.A_Property), "{}");
string g2IdentifyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(G2_Identify), "[]"); string g2IdentifyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(G2_Identify), "[]");
Dictionary<string, List<KeyValuePair<string, string>>> keyValuePairs = new(); Dictionary<string, List<KeyValuePair<string, string>>> keyValuePairs = new();
foreach (G2_Identify identified in identifiedCollection) foreach (G2_Identify identified in identifiedCollection)
@ -221,7 +220,7 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify
_ = Directory.CreateDirectory(directoryFullName); _ = Directory.CreateDirectory(directoryFullName);
jsonFile = string.Concat(g2IdentifyCollectionDirectory, keyValuePair.Key, ".json"); jsonFile = string.Concat(g2IdentifyCollectionDirectory, keyValuePair.Key, ".json");
json = JsonSerializer.Serialize(keyValuePair.Value, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(keyValuePair.Value, _WriteIndentedJsonSerializerOptions);
if (!Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: true, compareBeforeWrite: true)) if (!Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: true, compareBeforeWrite: true))
continue; continue;
} }
} }

View File

@ -1,6 +1,5 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models.Methods; using View_by_Distance.Shared.Models.Methods;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
@ -76,11 +75,11 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex
return result; return result;
} }
private void WriteNeeded(List<int> indices, List<Tuple<List<string>, string, A_Property>> neededTuples) private void WriteNeeded(List<int> indices, List<Tuple<List<string>, string, Shared.Models.Property>> neededTuples)
{ {
string json; string json;
DateTime dateTime; DateTime dateTime;
A_Property property; Shared.Models.Property property;
G_Index indexInfo; G_Index indexInfo;
int maxIndexPlusOne; int maxIndexPlusOne;
DateTime?[] dateTimes; DateTime?[] dateTimes;
@ -91,7 +90,7 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex
maxIndexPlusOne = 1000000; maxIndexPlusOne = 1000000;
throw new Exception("Are you sure exception. Use debugger to step over."); throw new Exception("Are you sure exception. Use debugger to step over.");
} }
foreach (Tuple<List<string>, string, A_Property> tuple in neededTuples) foreach (Tuple<List<string>, string, Shared.Models.Property> tuple in neededTuples)
{ {
maxIndexPlusOne += 1; maxIndexPlusOne += 1;
property = tuple.Item3; property = tuple.Item3;
@ -99,7 +98,7 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex
dateTime = (from l in dateTimes where l.HasValue select l.Value).Min(); dateTime = (from l in dateTimes where l.HasValue select l.Value).Min();
indexInfo = new(dateTime, maxIndexPlusOne, tuple.Item1); indexInfo = new(dateTime, maxIndexPlusOne, tuple.Item1);
json = JsonSerializer.Serialize(indexInfo, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(indexInfo, _WriteIndentedJsonSerializerOptions);
if (!Property.Models.Stateless.IPath.WriteAllText(tuple.Item2, json, updateDateWhenMatches: true, compareBeforeWrite: true)) if (!Shared.Models.Stateless.Methods.IPath.WriteAllText(tuple.Item2, json, updateDateWhenMatches: true, compareBeforeWrite: true))
continue; continue;
} }
} }
@ -114,24 +113,24 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex
indices = (from l in tuple.Item2 select l.Value).ToArray(); indices = (from l in tuple.Item2 select l.Value).ToArray();
directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, model, predictorModel, tuple.Item1, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: string.Empty, collectionDescription: "Unknown A"); directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, model, predictorModel, tuple.Item1, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: string.Empty, collectionDescription: "Unknown A");
json = JsonSerializer.Serialize(indices, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(indices, _WriteIndentedJsonSerializerOptions);
if (!Property.Models.Stateless.IPath.WriteAllText(string.Concat(directoryInfoCollection[0].Replace("<>", "[]"), ".json"), json, updateDateWhenMatches: true, compareBeforeWrite: true)) if (!Shared.Models.Stateless.Methods.IPath.WriteAllText(string.Concat(directoryInfoCollection[0].Replace("<>", "[]"), ".json"), json, updateDateWhenMatches: true, compareBeforeWrite: true))
continue; continue;
} }
} }
private void AppendTSV(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, Dictionary<string, List<Tuple<string, A_Property>>> filePropertiesKeyValuePairs) private void AppendTSV(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, Dictionary<string, List<Tuple<string, Shared.Models.Property>>> filePropertiesKeyValuePairs)
{ {
A_Property property; Shared.Models.Property property;
DateTime?[] dateTimes; DateTime?[] dateTimes;
DateTime? maximumDateTime; DateTime? maximumDateTime;
DateTime? minimumDateTime; DateTime? minimumDateTime;
List<string> directoryInfoCollection; List<string> directoryInfoCollection;
long ticks = System.DateTime.Now.Ticks; long ticks = System.DateTime.Now.Ticks;
foreach (KeyValuePair<string, List<Tuple<string, A_Property>>> tuples in filePropertiesKeyValuePairs) foreach (KeyValuePair<string, List<Tuple<string, Shared.Models.Property>>> tuples in filePropertiesKeyValuePairs)
{ {
maximumDateTime = null; maximumDateTime = null;
minimumDateTime = null; minimumDateTime = null;
foreach (Tuple<string, A_Property> tuple in tuples.Value) foreach (Tuple<string, Shared.Models.Property> tuple in tuples.Value)
{ {
property = tuple.Item2; property = tuple.Item2;
dateTimes = new DateTime?[] { maximumDateTime, minimumDateTime, property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeOriginal, property.GPSDateStamp }; dateTimes = new DateTime?[] { maximumDateTime, minimumDateTime, property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeOriginal, property.GPSDateStamp };
@ -142,7 +141,7 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex
} }
} }
internal void SetIndex(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, Dictionary<string, List<Tuple<string, A_Property>>> filePropertiesKeyValuePairs) internal void SetIndex(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, Dictionary<string, List<Tuple<string, Shared.Models.Property>>> filePropertiesKeyValuePairs)
{ {
FileInfo fileInfo; FileInfo fileInfo;
G_Index indexInfo; G_Index indexInfo;
@ -151,7 +150,7 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex
Dictionary<int, G_Index> valuePairs; Dictionary<int, G_Index> valuePairs;
List<string> directoryInfoCollection; List<string> directoryInfoCollection;
List<string> parseExceptions = new(); List<string> parseExceptions = new();
List<Tuple<List<string>, string, A_Property>> neededTuples = new(); List<Tuple<List<string>, string, Shared.Models.Property>> neededTuples = new();
List<Tuple<string, Dictionary<int, G_Index>>> indexInfoTuples = new(); List<Tuple<string, Dictionary<int, G_Index>>> indexInfoTuples = new();
for (short i = 0; i < short.MaxValue; i++) for (short i = 0; i < short.MaxValue; i++)
{ {
@ -164,11 +163,11 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex
parseExceptions.Clear(); parseExceptions.Clear();
} }
neededTuples.Clear(); neededTuples.Clear();
foreach (KeyValuePair<string, List<Tuple<string, A_Property>>> tuples in filePropertiesKeyValuePairs) foreach (KeyValuePair<string, List<Tuple<string, Shared.Models.Property>>> tuples in filePropertiesKeyValuePairs)
{ {
valuePairs = new Dictionary<int, G_Index>(); valuePairs = new Dictionary<int, G_Index>();
directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, model, predictorModel, tuples.Key, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: "Unknown C", collectionDescription: string.Empty); directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, model, predictorModel, tuples.Key, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: "Unknown C", collectionDescription: string.Empty);
foreach (Tuple<string, A_Property> tuple in tuples.Value) foreach (Tuple<string, Shared.Models.Property> tuple in tuples.Value)
{ {
fileInfo = new FileInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "{}"), string.Concat(Path.GetFileNameWithoutExtension(tuple.Item1), ".json"))); fileInfo = new FileInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "{}"), string.Concat(Path.GetFileNameWithoutExtension(tuple.Item1), ".json")));
if (!fileInfo.Exists) if (!fileInfo.Exists)
@ -191,7 +190,7 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex
valuePairs.Add(indexInfo.Index.Value, indexInfo); valuePairs.Add(indexInfo.Index.Value, indexInfo);
} }
else else
neededTuples.Add(new Tuple<List<string>, string, A_Property>(new List<string> { tuple.Item1 }, fileInfo.FullName, tuple.Item2)); neededTuples.Add(new Tuple<List<string>, string, Shared.Models.Property>(new List<string> { tuple.Item1 }, fileInfo.FullName, tuple.Item2));
} }
indexInfoTuples.Add(new Tuple<string, Dictionary<int, G_Index>>(tuples.Key, valuePairs)); indexInfoTuples.Add(new Tuple<string, Dictionary<int, G_Index>>(tuples.Key, valuePairs));
} }

View File

@ -52,7 +52,7 @@
"Configuration": { "Configuration": {
"CheckJsonForDistanceResults": false, "CheckJsonForDistanceResults": false,
"CrossDirectoryMaxItemsInDistanceCollection": 7, "CrossDirectoryMaxItemsInDistanceCollection": 7,
"DateGroup": "2022-08-14", "DateGroup": "2022-08-22",
"DistanceFactor": 8, "DistanceFactor": 8,
"FileNameDirectorySeparator": ".Z.", "FileNameDirectorySeparator": ".Z.",
"ForceFaceLastWriteTimeToCreationTime": false, "ForceFaceLastWriteTimeToCreationTime": false,
@ -62,7 +62,7 @@
"LoadOrCreateThenSaveIndex": false, "LoadOrCreateThenSaveIndex": false,
"LocationConfidenceFactor": 2, "LocationConfidenceFactor": 2,
"MappedMaxIndex": 1034720, "MappedMaxIndex": 1034720,
"MaxImagesInDirectoryForTopLevelFirstPass": 50, "MaxImagesInDirectoryForTopLevelFirstPass": 10,
"MaxItemsInDistanceCollection": 50, "MaxItemsInDistanceCollection": 50,
"ModelDirectory": "C:/GitHub/dlib-models", "ModelDirectory": "C:/GitHub/dlib-models",
"ModelName": "Hog", "ModelName": "Hog",
@ -85,7 +85,7 @@
"PropertiesChangedForResize": false, "PropertiesChangedForResize": false,
"Reverse": false, "Reverse": false,
"xRootDirectory": "C:/Tmp/phares/Pictures", "xRootDirectory": "C:/Tmp/phares/Pictures",
"RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-08-14 - b756859b616424dc98b7742a64c15a8951632473 - III", "RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-08-22 - b756859b616424dc98b7742a64c15a8951632473 - III",
"SaveFullYearOfRandomFiles": true, "SaveFullYearOfRandomFiles": true,
"SaveResizedSubFiles": true, "SaveResizedSubFiles": true,
"SkipSearch": false, "SkipSearch": false,

View File

@ -52,7 +52,7 @@
"Configuration": { "Configuration": {
"CheckJsonForDistanceResults": false, "CheckJsonForDistanceResults": false,
"CrossDirectoryMaxItemsInDistanceCollection": 7, "CrossDirectoryMaxItemsInDistanceCollection": 7,
"DateGroup": "2022-08-14", "DateGroup": "2022-08-22",
"DistanceFactor": 8, "DistanceFactor": 8,
"FileNameDirectorySeparator": ".Z.", "FileNameDirectorySeparator": ".Z.",
"ForceFaceLastWriteTimeToCreationTime": false, "ForceFaceLastWriteTimeToCreationTime": false,
@ -62,7 +62,7 @@
"LoadOrCreateThenSaveIndex": false, "LoadOrCreateThenSaveIndex": false,
"LocationConfidenceFactor": 2, "LocationConfidenceFactor": 2,
"MappedMaxIndex": 1034720, "MappedMaxIndex": 1034720,
"MaxImagesInDirectoryForTopLevelFirstPass": 50, "MaxImagesInDirectoryForTopLevelFirstPass": 10,
"MaxItemsInDistanceCollection": 50, "MaxItemsInDistanceCollection": 50,
"ModelDirectory": "L:/GitHub/dlib-models", "ModelDirectory": "L:/GitHub/dlib-models",
"ModelName": "Hog", "ModelName": "Hog",

View File

@ -52,7 +52,7 @@
"Configuration": { "Configuration": {
"CheckJsonForDistanceResults": false, "CheckJsonForDistanceResults": false,
"CrossDirectoryMaxItemsInDistanceCollection": 7, "CrossDirectoryMaxItemsInDistanceCollection": 7,
"DateGroup": "2022-08-14", "DateGroup": "2022-08-22",
"DistanceFactor": 8, "DistanceFactor": 8,
"FileNameDirectorySeparator": ".Z.", "FileNameDirectorySeparator": ".Z.",
"ForceFaceLastWriteTimeToCreationTime": false, "ForceFaceLastWriteTimeToCreationTime": false,
@ -62,7 +62,7 @@
"LoadOrCreateThenSaveIndex": false, "LoadOrCreateThenSaveIndex": false,
"LocationConfidenceFactor": 2, "LocationConfidenceFactor": 2,
"MappedMaxIndex": 1034720, "MappedMaxIndex": 1034720,
"MaxImagesInDirectoryForTopLevelFirstPass": 50, "MaxImagesInDirectoryForTopLevelFirstPass": 10,
"MaxItemsInDistanceCollection": 50, "MaxItemsInDistanceCollection": 50,
"ModelDirectory": "C:/GitHub/dlib-models", "ModelDirectory": "C:/GitHub/dlib-models",
"ModelName": "Hog", "ModelName": "Hog",

7
Map/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"cSpell.words": [
"dlib",
"Exif",
"Serilog"
]
}

46
Map/Map.csproj Normal file
View File

@ -0,0 +1,46 @@
<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.Map</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>6.0.100.1</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="Serilog" Version="2.10.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
</ItemGroup>
</Project>

546
Map/Models/MapLogic.cs Normal file
View File

@ -0,0 +1,546 @@
using System.Diagnostics;
using System.Text.Json;
using View_by_Distance.Property.Models;
namespace View_by_Distance.Map.Models;
public class MapLogic
{
protected readonly List<(int, string[])> _AllCollection;
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 Dictionary<int, int[]> KeyValuePairs => _KeyValuePairs;
public Dictionary<int, int[]> IndicesFromNew => _IndicesFromNew;
public string DeterministicHashCodeRootDirectory => _DeterministicHashCodeRootDirectory;
public Dictionary<double, string[]> NamedDeterministicHashCodeKeyValuePairs => _NamedDeterministicHashCodeKeyValuePairs;
public Dictionary<double, string[]> IncorrectDeterministicHashCodeKeyValuePairs => _IncorrectDeterministicHashCodeKeyValuePairs;
public Dictionary<int, string[]> NamedFaceInfoDeterministicHashCodeKeyValuePairs => _NamedFaceInfoDeterministicHashCodeKeyValuePairs;
private readonly Serilog.ILogger? _Log;
private readonly Configuration _Configuration;
public MapLogic(int maxDegreeOfParallelism, Configuration configuration)
{
_AllCollection = new();
_Configuration = configuration;
_Log = Serilog.Log.ForContext<MapLogic>();
Dictionary<int, string[]>? namedFaceInfoDeterministicHashCode;
if (configuration.VerifyToSeason is null || !configuration.VerifyToSeason.Any())
throw new Exception();
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<Shared.Models.Face>> 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<Shared.Models.Face>> 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 = Shared.Models.Stateless.Methods.INamed.GetReversedDeterministicHashCode(fileName);
if (idAndNormalizedPixelPercentage is null)
{
(checkFile, idAndNormalizedPixelPercentage) = Shared.Models.Stateless.Methods.INamed.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 = Shared.Models.Stateless.Methods.INamed.GetReversedDeterministicHashCode(fileName);
if (idAndNormalizedPixelPercentage is null)
{
(checkFile, idAndNormalizedPixelPercentage) = Shared.Models.Stateless.Methods.INamed.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<Shared.Models.Face>> 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<Shared.Models.Container> containers)
{
Dictionary<int, List<Shared.Models.Face>> keyValuePairs = new();
Dictionary<double, string[]> namedDeterministicHashCode = new();
Dictionary<double, string[]> incorrectDeterministicHashCode = new();
foreach (Shared.Models.Container container in containers)
{
foreach (Shared.Models.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 void AddToMapLogicAllCollection(Shared.Models.Item[] filteredItems)
{
if (_SixCharacterNamedFaceInfo.Any())
{
string[] keys;
Shared.Models.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;
long ticks = DateTime.Now.Ticks;
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");
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: true, compareBeforeWrite: true);
_ = LogDelta(ticks, new StackFrame().GetMethod()?.Name);
}
}
public static void AddToNamed(MapLogic mapLogic, List<Shared.Models.Item> items)
{
bool? isWrongYear;
DateTime minimumDateTime;
double deterministicHashCodeKey;
List<string> personKeys = new();
Shared.Models.PersonBirthday? personBirthday;
foreach (Shared.Models.Item item in items)
{
if (item.ImageFileHolder is null)
continue;
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
foreach (Shared.Models.Face face in item.Faces)
{
personKeys.Clear();
if (face.LocationIndex is null)
continue;
deterministicHashCodeKey = Shared.Models.Stateless.Methods.INamed.GetDeterministicHashCodeKey(item, face);
if (!mapLogic.NamedDeterministicHashCodeKeyValuePairs.ContainsKey(deterministicHashCodeKey))
continue;
minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
personKeys.AddRange(mapLogic.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;
if (face.Location is null)
continue;
item.Named.Add(new(isWrongYear, minimumDateTime, face.Location.NormalizedPixelPercentage, personBirthday));
}
}
if (!personKeys.Any())
{
if (!mapLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs.ContainsKey(item.Property.Id.Value))
continue;
minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
personKeys.AddRange(mapLogic.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<(Shared.Models.Item, (string, Shared.Models.Face?, (string, string, string, string))[])> GetCollection(MapLogic mapLogic, List<Shared.Models.Item> items, string dFacesContentDirectory)
{
List<(Shared.Models.Item, (string, Shared.Models.Face?, (string, string, string, string))[])> results = new();
string[] keys;
string directory;
string personKey;
bool? isWrongYear;
const int zero = 0;
TimeSpan? timeSpan;
string copyFileName;
string copyDirectory;
string? relativePath;
string isWrongYearFlag;
Shared.Models.Face face;
string shortcutFileName;
Shared.Models.Item item;
string subDirectoryName;
List<int> indices = new();
DateTime? minimumDateTime;
List<Shared.Models.Face> faceCollection;
Shared.Models.PersonBirthday? personBirthday;
List<(string, Shared.Models.Face?, (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 (!mapLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs.ContainsKey(item.Property.Id.Value))
{
faceCollection = new();
personKey = string.Empty;
directory = Path.Combine(dFacesContentDirectory, $"Unnamed{relativePath[2..]}");
}
else
{
faceCollection = item.Faces;
keys = mapLogic.NamedFaceInfoDeterministicHashCodeKeyValuePairs[item.Property.Id.Value];
minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
if (minimumDateTime is null)
continue;
(isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime.Value);
isWrongYearFlag = Shared.Models.Stateless.Methods.IItem.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}";
}
face = faceCollection[zero];
directory = Path.Combine(dFacesContentDirectory, "Shortcuts", personKey, subDirectoryName);
if (face.FaceEncoding is not null && face.Location?.NormalizedPixelPercentage is not null)
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, Shared.Models.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 = Shared.Models.Stateless.Methods.IItem.GetWrongYearFlag(isWrongYear);
result = string.Concat(personKey, $"{isWrongYearFlag}{minimumDateTime:yyyy}");
}
return result;
}
public static string GetDirectory(string directory, string subDirectory, DateTime minimumDateTime, bool? isWrongYear, Shared.Models.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 = Shared.Models.Stateless.Methods.IItem.GetWrongYearFlag(isWrongYear);
result = Path.Combine(directory, subDirectory, personKey, $"{isWrongYearFlag}{minimumDateTime:yyyy}");
}
return result;
}
public static Dictionary<string, List<(DateTime, bool?, Shared.Models.PersonBirthday, Shared.Models.Face)>> GetKeyValuePairs(string argZero, List<Shared.Models.Container> containers)
{
Dictionary<string, List<(DateTime, bool?, Shared.Models.PersonBirthday, Shared.Models.Face)>> results = new();
string key;
foreach (Shared.Models.Container container in containers)
{
if (!container.Items.Any())
continue;
if (!container.SourceDirectory.StartsWith(argZero))
continue;
foreach (Shared.Models.Item item in container.Items)
{
if (item.ImageFileHolder is null || item.Property is null || !item.Named.Any())
continue;
foreach (Shared.Models.Named named in item.Named)
{
if (named.NormalizedPixelPercentage is null && (item.Named.Count != 1 || item.Faces.Count != 1))
continue;
foreach (Shared.Models.Face face in item.Faces)
{
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
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;
}
public static (bool?, string[]) IsWrongYear(Shared.Models.Item item)
{
(bool?, string[]) result;
if (item.Property is null || item.ImageFileHolder is null)
throw new NullReferenceException();
DateTime? minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
result = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime);
return result;
}
}

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.Map.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);
}

View File

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

View File

@ -78,7 +78,7 @@ public class B_Metadata
return results; return results;
} }
public (int, List<KeyValuePair<string, string>>) GetMetadataCollection(string bResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Property.Models.Item item) public (int, List<KeyValuePair<string, string>>) GetMetadataCollection(string bResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Item item)
{ {
List<KeyValuePair<string, string>> results = new(); List<KeyValuePair<string, string>> results = new();
if (item.Property?.Id is null) if (item.Property?.Id is null)
@ -151,7 +151,7 @@ public class B_Metadata
json = JsonSerializer.Serialize(dictionary, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(dictionary, _WriteIndentedJsonSerializerOptions);
bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime;
DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime))
{ {
if (!_ForceMetadataLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime)) if (!_ForceMetadataLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(B_Metadata), DateTime.Now)); subFileTuples.Add(new Tuple<string, DateTime>(nameof(B_Metadata), DateTime.Now));
@ -171,29 +171,4 @@ public class B_Metadata
return new(dictionary.Count, results); return new(dictionary.Count, results);
} }
public static List<KeyValuePair<string, string>> GetFiltered(List<KeyValuePair<string, string>> metadataCollection)
{
List<KeyValuePair<string, string>> results = new();
foreach (KeyValuePair<string, string> keyValuePair in metadataCollection)
{
if (keyValuePair.Key.Contains("File") || keyValuePair.Key.Contains("JPEG") || keyValuePair.Key.Contains("Orientation") || keyValuePair.Key.Contains("Thumbnail"))
continue;
results.Add(new(keyValuePair.Key, keyValuePair.Value));
}
if (!results.Any())
results = metadataCollection;
return results;
}
public static string GetUniqueImageId(List<KeyValuePair<string, string>> metadataCollection)
{
string result = string.Empty;
const string exifSubIFD = "Exif SubIFD";
const string uniqueImageID = "42016\tUnique Image ID";
List<string> uniqueImageIDs = (from l in metadataCollection where l.Key.StartsWith(exifSubIFD) && l.Key.EndsWith(uniqueImageID) select l.Value).ToList();
if (uniqueImageIDs.Any())
result = uniqueImageIDs[0];
return result;
}
} }

View File

@ -26,23 +26,22 @@ public class NotCopyCopy
_AppSettings = appSettings; _AppSettings = appSettings;
_IsEnvironment = isEnvironment; _IsEnvironment = isEnvironment;
_Log = Serilog.Log.ForContext<NotCopyCopy>(); _Log = Serilog.Log.ForContext<NotCopyCopy>();
Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory); Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
Property.Models.Configuration.Verify(propertyConfiguration); Property.Models.Configuration.Verify(propertyConfiguration);
Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration);
Verify(configuration); Verify(configuration);
bool reverse = false; bool reverse = false;
Model? model = null; Model? model = null;
PredictorModel? predictorModel = null; string outputExtension = ".jpg";
_Configuration = configuration; _Configuration = configuration;
if (propertyConfiguration.PopulatePropertyId is null) PredictorModel? predictorModel = null;
throw new NullReferenceException(nameof(propertyConfiguration.PopulatePropertyId));
if (!_IsEnvironment.Development) if (!_IsEnvironment.Development)
throw new Exception("This program only allows development environments!"); throw new Exception("This program only allows development environments!");
PropertyLogic propertyLogic = GetPropertyLogic(reverse, model, predictorModel); A_Property propertyLogic = GetPropertyLogic(reverse, model, outputExtension, predictorModel);
propertyConfiguration.ChangeRootDirectory(configuration.CompareSource); propertyConfiguration.ChangeRootDirectory(configuration.CompareSource);
List<Container> compareContainers = Property.Models.Stateless.A_Property.Get(propertyConfiguration, propertyLogic); List<Shared.Models.Container> compareContainers = A_Property.Get(propertyConfiguration, propertyLogic);
propertyConfiguration.ChangeRootDirectory(configuration.SelectedSource); propertyConfiguration.ChangeRootDirectory(configuration.SelectedSource);
List<Container> selectedContainers = Property.Models.Stateless.A_Property.Get(propertyConfiguration, propertyLogic); List<Shared.Models.Container> selectedContainers = A_Property.Get(propertyConfiguration, propertyLogic);
if (compareContainers.Count == selectedContainers.Count) if (compareContainers.Count == selectedContainers.Count)
throw new Exception(); throw new Exception();
string directoryName; string directoryName;
@ -103,12 +102,12 @@ public class NotCopyCopy
throw new NullReferenceException(nameof(configuration.SelectedSource)); throw new NullReferenceException(nameof(configuration.SelectedSource));
} }
private PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel) private A_Property GetPropertyLogic(bool reverse, Model? model, string outputExtension, PredictorModel? predictorModel)
{ {
PropertyLogic result; A_Property result;
if (_Configuration?.PropertyConfiguration is null) if (_Configuration?.PropertyConfiguration is null)
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, reverse, model, predictorModel); result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, outputExtension, reverse, model, predictorModel);
return result; return result;
} }
@ -119,12 +118,12 @@ public class NotCopyCopy
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
string key; string key;
string fileName; string fileName;
A_Property? property; Shared.Models.Property? property;
string destinationDirectory; string destinationDirectory;
List<string> directoryNames; List<string> directoryNames;
List<string> destinationCollection; List<string> destinationCollection;
string filteredSourceDirectoryFile; string filteredSourceDirectoryFile;
Dictionary<string, A_Property> keyValuePairs = new(); Dictionary<string, Shared.Models.Property> keyValuePairs = new();
foreach (Property.Models.DirectoryInfo group in compareSourceGroupCollection) foreach (Property.Models.DirectoryInfo group in compareSourceGroupCollection)
{ {
for (int i = 0; i < group.SourceDirectoryFileHolderCollection.Length; i++) for (int i = 0; i < group.SourceDirectoryFileHolderCollection.Length; i++)
@ -150,7 +149,7 @@ public class NotCopyCopy
if (keyValuePairs.ContainsKey(key) && keyValuePairs[key].LastWriteTime == property.LastWriteTime) if (keyValuePairs.ContainsKey(key) && keyValuePairs[key].LastWriteTime == property.LastWriteTime)
continue; continue;
destinationDirectory = string.Concat(_Configuration.EmptyDestination, group.SourceDirectory[_Configuration.SelectedSource.Length..]); destinationDirectory = string.Concat(_Configuration.EmptyDestination, group.SourceDirectory[_Configuration.SelectedSource.Length..]);
directoryNames = Property.Models.Stateless.IPath.GetDirectoryNames(destinationDirectory); directoryNames = Shared.Models.Stateless.Methods.IPath.GetDirectoryNames(destinationDirectory);
destinationCollection.AddRange(directoryNames); destinationCollection.AddRange(directoryNames);
destinationCollection.Add(fileName); destinationCollection.Add(fileName);
results.Add(new(filteredSourceDirectoryFile, destinationCollection.ToArray())); results.Add(new(filteredSourceDirectoryFile, destinationCollection.ToArray()));

View File

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

View File

@ -39,60 +39,60 @@ public class Program
if (args is null) if (args is null)
throw new Exception("args is null!"); throw new Exception("args is null!");
#nullable disable #nullable disable
if (Property.Models.Stateless.A_Property.IsWrongYear("-".Split(' '), "2021").Item1.HasValue) if (IProperty.IsWrongYear("-".Split(' '), "2021").Item1.HasValue)
throw new Exception("-"); throw new Exception("-");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass".Split(' '), "2021").Item1.HasValue) if (IProperty.IsWrongYear("Christmass".Split(' '), "2021").Item1.HasValue)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass 2021".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Christmass 2021".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Christmass ~2021".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021.4".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Christmass ~2021.4".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass 2021".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Christmass 2021".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Christmass ~2021".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021.4".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Christmass ~2021.4".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass"); throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("England 2017".Split(' '), "2017").Item1.Value) if (IProperty.IsWrongYear("England 2017".Split(' '), "2017").Item1.Value)
throw new Exception("England"); throw new Exception("England");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael".Split(' '), "2021").Item1.HasValue) if (IProperty.IsWrongYear("Logan Michael".Split(' '), "2021").Item1.HasValue)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael 2021".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Logan Michael 2021".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Logan Michael ~2021".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item1.Value) if (IProperty.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael 2021".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Logan Michael 2021".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Logan Michael ~2021".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2025").Item1.Value) if (!IProperty.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item2[0] != "~2021.4") if (IProperty.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item2[0] != "~2021.4")
throw new Exception("Logan Michael"); throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Chelsea's 2nd Birthday =2014".Split(' '), "2014").Item1.Value) if (IProperty.IsWrongYear("Chelsea's 2nd Birthday =2014".Split(' '), "2014").Item1.Value)
throw new Exception("Chelsea"); throw new Exception("Chelsea");
#nullable restore #nullable restore
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"C:\Tmp")[0] != @"C:\") if (IPath.GetDirectoryNames(@"C:\Tmp")[0] != @"C:\")
throw new Exception(); throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"C:\Tmp")[1] != "Tmp") if (IPath.GetDirectoryNames(@"C:\Tmp")[1] != "Tmp")
throw new Exception(); throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"C:\Tmp\mike.txt")[1] != "Tmp") if (IPath.GetDirectoryNames(@"C:\Tmp\mike.txt")[1] != "Tmp")
throw new Exception(); throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"C:\Tmp\a.txt")[1] != "Tmp") if (IPath.GetDirectoryNames(@"C:\Tmp\a.txt")[1] != "Tmp")
throw new Exception(); throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"C:\Tmp\Mike\a.txt")[2] != "Mike") if (IPath.GetDirectoryNames(@"C:\Tmp\Mike\a.txt")[2] != "Mike")
throw new Exception(); throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer\Dsc_8558.jpg")[0] != @"I:\") if (IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer\Dsc_8558.jpg")[0] != @"I:\")
throw new Exception(); throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer\Dsc_8558.jpg")[1] != @"Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II") if (IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer\Dsc_8558.jpg")[1] != @"Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II")
throw new Exception(); throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer\Dsc_8558.jpg")[2] != @"=2010.2 Summer") if (IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer\Dsc_8558.jpg")[2] != @"=2010.2 Summer")
throw new Exception(); throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer")[2] != @"=2010.2 Summer") if (IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer")[2] != @"=2010.2 Summer")
throw new Exception(); throw new Exception();
Shared.Models.Console console = new(); Shared.Models.Console console = new();
NotCopyCopy _ = new(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console); NotCopyCopy _ = new(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console);

View File

@ -50,10 +50,10 @@
"WorkingDirectoryName": "PharesApps", "WorkingDirectoryName": "PharesApps",
"Windows": { "Windows": {
"Configuration": { "Configuration": {
"DateGroup": "2022-08-14", "DateGroup": "2022-08-22",
"FileNameDirectorySeparator": ".Z.", "FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false, "ForcePropertyLastWriteTimeToCreationTime": false,
"MaxImagesInDirectoryForTopLevelFirstPass": 50, "MaxImagesInDirectoryForTopLevelFirstPass": 10,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": false, "PopulatePropertyId": false,
"PropertiesChangedForProperty": false, "PropertiesChangedForProperty": false,

View File

@ -3,7 +3,6 @@ using Phares.Shared;
using System.Text.Json; using System.Text.Json;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using View_by_Distance.PrepareForOld.Models; using View_by_Distance.PrepareForOld.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models.Methods; using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.PrepareForOld; namespace View_by_Distance.PrepareForOld;
@ -15,10 +14,10 @@ public class PrepareForOld
private readonly AppSettings _AppSettings; private readonly AppSettings _AppSettings;
private readonly List<string> _Exceptions; private readonly List<string> _Exceptions;
private readonly IsEnvironment _IsEnvironment; private readonly IsEnvironment _IsEnvironment;
private readonly Models.Configuration _Configuration; private readonly Configuration _Configuration;
private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs; private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs;
private readonly List<(string Find, string Replace)> _SpellingFindReplace; private readonly List<(string Find, string Replace)> _SpellingFindReplace;
private readonly Dictionary<string, List<Tuple<string, A_Property>>> _FilePropertiesKeyValuePairs; private readonly Dictionary<string, List<Tuple<string, Shared.Models.Property>>> _FilePropertiesKeyValuePairs;
public PrepareForOld(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) public PrepareForOld(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{ {
@ -34,10 +33,10 @@ public class PrepareForOld
_Exceptions = new List<string>(); _Exceptions = new List<string>();
_Log = Serilog.Log.ForContext<PrepareForOld>(); _Log = Serilog.Log.ForContext<PrepareForOld>();
_FileKeyValuePairs = new List<KeyValuePair<string, string>>(); _FileKeyValuePairs = new List<KeyValuePair<string, string>>();
_FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, A_Property>>>(); _FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, Shared.Models.Property>>>();
Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory); Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
Property.Models.Configuration.Verify(propertyConfiguration); Property.Models.Configuration.Verify(propertyConfiguration);
Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration);
Verify(configuration); Verify(configuration);
if (propertyConfiguration.IgnoreExtensions is null) if (propertyConfiguration.IgnoreExtensions is null)
throw new NullReferenceException(nameof(propertyConfiguration.IgnoreExtensions)); throw new NullReferenceException(nameof(propertyConfiguration.IgnoreExtensions));
@ -53,7 +52,7 @@ public class PrepareForOld
string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories); string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories);
foreach (string dbFile in dbFiles) foreach (string dbFile in dbFiles)
File.Delete(dbFile); File.Delete(dbFile);
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A_Property), "{}"); string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(Property.Models.A_Property), "{}");
if (!Directory.Exists(aPropertySingletonDirectory)) if (!Directory.Exists(aPropertySingletonDirectory))
throw new Exception(aPropertySingletonDirectory); throw new Exception(aPropertySingletonDirectory);
ConsoleKey? consoleKey = null; ConsoleKey? consoleKey = null;
@ -104,7 +103,7 @@ public class PrepareForOld
_Configuration = configuration; _Configuration = configuration;
} }
private static void Verify(Models.Configuration configuration) private static void Verify(Configuration configuration)
{ {
if (configuration.Spelling is null || !configuration.Spelling.Any()) if (configuration.Spelling is null || !configuration.Spelling.Any())
throw new NullReferenceException(nameof(configuration.Spelling)); throw new NullReferenceException(nameof(configuration.Spelling));
@ -157,7 +156,7 @@ public class PrepareForOld
indexInfoFiles.AddRange(Directory.GetFiles(infoDirectoryExtra, "IndexInfo.json", SearchOption.AllDirectories)); indexInfoFiles.AddRange(Directory.GetFiles(infoDirectoryExtra, "IndexInfo.json", SearchOption.AllDirectories));
foreach (Models.SaveTabSeparatedValues.ImageExifInfo exifInfo in exifCollection) foreach (Models.SaveTabSeparatedValues.ImageExifInfo exifInfo in exifCollection)
{ {
dateTimes = Property.Models.Stateless.A_Property.GetDateTimes(exifInfo.CreationTime, exifInfo.LastWriteTime, exifInfo.DateTime, exifInfo.DateTimeDigitized, exifInfo.DateTimeOriginal, exifInfo.GPSDateStamp); dateTimes = Shared.Models.Stateless.Methods.IProperty.GetDateTimes(exifInfo.CreationTime, exifInfo.LastWriteTime, exifInfo.DateTime, exifInfo.DateTimeDigitized, exifInfo.DateTimeOriginal, exifInfo.GPSDateStamp);
if (!checkDistinct && keyValuePairs.ContainsKey(exifInfo.Index)) if (!checkDistinct && keyValuePairs.ContainsKey(exifInfo.Index))
continue; continue;
keyValuePairs.Add(exifInfo.Index, dateTimes.Min().Ticks); keyValuePairs.Add(exifInfo.Index, dateTimes.Min().Ticks);
@ -252,7 +251,7 @@ public class PrepareForOld
{ {
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray(); string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray();
string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "[{}]"); string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(Property.Models.A_Property), "[{}]");
File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines); File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines);
string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true }); string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json); File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json);
@ -611,7 +610,7 @@ public class PrepareForOld
{ {
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray(); string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray();
string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "[{}]"); string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(Property.Models.A_Property), "[{}]");
File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines); File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines);
string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true }); string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json); File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json);

View File

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

View File

@ -50,11 +50,11 @@
"WorkingDirectoryName": "PharesApps", "WorkingDirectoryName": "PharesApps",
"Windows": { "Windows": {
"Configuration": { "Configuration": {
"DateGroup": "2022-08-14", "DateGroup": "2022-08-22",
"FileNameDirectorySeparator": ".Z.", "FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false, "ForcePropertyLastWriteTimeToCreationTime": false,
"KeepFullPath": false, "KeepFullPath": false,
"MaxImagesInDirectoryForTopLevelFirstPass": 50, "MaxImagesInDirectoryForTopLevelFirstPass": 10,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": false, "PopulatePropertyId": false,
"PropertiesChangedForProperty": false, "PropertiesChangedForProperty": false,

View File

@ -1,5 +1,4 @@
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Property.Models;
namespace View_by_Distance.PropertyCompare.Models; namespace View_by_Distance.PropertyCompare.Models;
@ -11,7 +10,7 @@ public partial class PropertyCompare
protected readonly bool _IsArg; protected readonly bool _IsArg;
protected DateTime _MinimumDateTime; protected DateTime _MinimumDateTime;
protected readonly List<long> _Numbers; protected readonly List<long> _Numbers;
protected A_Property? _Property; protected Shared.Models.Property? _Property;
protected string _RegexResult; protected string _RegexResult;
protected string _RelativeDirectory; protected string _RelativeDirectory;
protected readonly List<string> _Strings; protected readonly List<string> _Strings;
@ -21,12 +20,12 @@ public partial class PropertyCompare
public bool IsArg => _IsArg; public bool IsArg => _IsArg;
public DateTime MinimumDateTime => _MinimumDateTime; public DateTime MinimumDateTime => _MinimumDateTime;
public List<long> Numbers => _Numbers; public List<long> Numbers => _Numbers;
public A_Property? Property => _Property; public Shared.Models.Property? Property => _Property;
public string RegexResult => _RegexResult; public string RegexResult => _RegexResult;
public string RelativeDirectory => _RelativeDirectory; public string RelativeDirectory => _RelativeDirectory;
public List<string> Strings => _Strings; public List<string> Strings => _Strings;
public PropertyCompare(string extension, string fileNameWithoutExtension, bool isArg, DateTime minimumDateTime, List<long> numbers, A_Property property, string regexResult, string relativeDirectory, List<string> strings) public PropertyCompare(string extension, string fileNameWithoutExtension, bool isArg, DateTime minimumDateTime, List<long> numbers, Shared.Models.Property property, string regexResult, string relativeDirectory, List<string> strings)
{ {
_IsArg = isArg; _IsArg = isArg;
_Numbers = numbers; _Numbers = numbers;
@ -49,7 +48,7 @@ public partial class PropertyCompare
#nullable disable #nullable disable
public string GetSelect() => string.Concat(_RelativeDirectory, _FileNameWithoutExtension, _Extension, '\t', _Property.CreationTime.Ticks, '\t', View_by_Distance.Property.Models.Stateless.A_Property.GetDateTime(_Property).ToString("yyyy-MM-dd_HH-mm-ss"), '\t', _Property.Id, '\t', _Property.FileSize, '\t', _Property.Width, '\t', _Property.Height); public string GetSelect() => string.Concat(_RelativeDirectory, _FileNameWithoutExtension, _Extension, '\t', _Property.CreationTime.Ticks, '\t', Shared.Models.Stateless.Methods.IProperty.GetDateTime(_Property).ToString("yyyy-MM-dd_HH-mm-ss"), '\t', _Property.Id, '\t', _Property.FileSize, '\t', _Property.Width, '\t', _Property.Height);
#nullable restore #nullable restore

View File

@ -1,5 +1,3 @@
using View_by_Distance.Property.Models;
namespace View_by_Distance.PropertyCompare.Models; namespace View_by_Distance.PropertyCompare.Models;
internal class PropertyCompareItem internal class PropertyCompareItem
@ -9,16 +7,16 @@ internal class PropertyCompareItem
protected readonly bool _IsArg; protected readonly bool _IsArg;
protected readonly string _JsonFileNameWithoutExtension; protected readonly string _JsonFileNameWithoutExtension;
protected readonly long[] _Numbers; protected readonly long[] _Numbers;
protected readonly A_Property _Property; protected readonly Shared.Models.Property _Property;
protected readonly string[] _Strings; protected readonly string[] _Strings;
public string ImageFileName => _ImageFileName; public string ImageFileName => _ImageFileName;
public bool IsArg => _IsArg; public bool IsArg => _IsArg;
public string JsonFileNameWithoutExtension => _JsonFileNameWithoutExtension; public string JsonFileNameWithoutExtension => _JsonFileNameWithoutExtension;
public long[] Numbers => _Numbers; public long[] Numbers => _Numbers;
public A_Property Property => _Property; public Shared.Models.Property Property => _Property;
public string[] Strings => _Strings; public string[] Strings => _Strings;
public PropertyCompareItem(string imageFileName, bool isArg, string jsonFileNameWithoutExtension, long[] numbers, A_Property property, string[] strings) public PropertyCompareItem(string imageFileName, bool isArg, string jsonFileNameWithoutExtension, long[] numbers, Shared.Models.Property property, string[] strings)
{ {
_ImageFileName = imageFileName; _ImageFileName = imageFileName;
_IsArg = isArg; _IsArg = isArg;

View File

@ -19,7 +19,7 @@ public class PropertyCompareLogic
_Configuration = configuration; _Configuration = configuration;
_DiffRootDirectory = diffRootDirectory; _DiffRootDirectory = diffRootDirectory;
_SpellingFindReplace = spellingFindReplace; _SpellingFindReplace = spellingFindReplace;
_Log = Serilog.Log.ForContext<A_Property>(); _Log = Serilog.Log.ForContext<PropertyCompareLogic>();
_MaxDegreeOfParallelism = Math.Abs(maxDegreeOfParallelism); _MaxDegreeOfParallelism = Math.Abs(maxDegreeOfParallelism);
} }
@ -175,10 +175,10 @@ public class PropertyCompareLogic
else else
extension = Path.GetExtension(files[index]); extension = Path.GetExtension(files[index]);
string json = File.ReadAllText(jsonFile); string json = File.ReadAllText(jsonFile);
A_Property? property = JsonSerializer.Deserialize<A_Property>(json); Shared.Models.Property? property = JsonSerializer.Deserialize<Shared.Models.Property>(json);
if (property?.Id is null) if (property?.Id is null)
throw new NullReferenceException(nameof(property)); throw new NullReferenceException(nameof(property));
DateTime minimumDateTime = Property.Models.Stateless.A_Property.GetMinimumDateTime(property); DateTime minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
corrected = string.Concat(relativeDirectory, jsonFileNameWithoutExtension); corrected = string.Concat(relativeDirectory, jsonFileNameWithoutExtension);
if (_SpellingFindReplace is not null && (from l in _SpellingFindReplace where corrected.Contains(l.Find) select true).Any()) if (_SpellingFindReplace is not null && (from l in _SpellingFindReplace where corrected.Contains(l.Find) select true).Any())
{ {
@ -200,17 +200,17 @@ public class PropertyCompareLogic
2 => property.Id.Value, 2 => property.Id.Value,
3 => property.Id.Value, 3 => property.Id.Value,
4 => property.Id.Value, 4 => property.Id.Value,
5 => Property.Models.Stateless.A_Property.GetDateTime(property).Ticks, 5 => Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks,
6 => property.CreationTime.Ticks, 6 => property.CreationTime.Ticks,
7 => property.FileSize, 7 => property.FileSize,
8 => Property.Models.Stateless.A_Property.GetDateTime(property).Ticks, 8 => Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks,
9 => property.FileSize, 9 => property.FileSize,
_ => throw new Exception() _ => throw new Exception()
}; };
s = i switch s = i switch
{ {
0 => $"{jsonFileNameWithoutExtension.ToLower()}", 0 => $"{jsonFileNameWithoutExtension.ToLower()}",
1 => $"{property.FileSize}{Property.Models.Stateless.A_Property.GetDateTime(property).Ticks}", 1 => $"{property.FileSize}{Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks}",
2 => $"{property.FileSize}{property.CreationTime:yyyy-MM-dd_HH-mm-ss}", 2 => $"{property.FileSize}{property.CreationTime:yyyy-MM-dd_HH-mm-ss}",
3 => $"{property.FileSize}{property.Width}{property.Height}", 3 => $"{property.FileSize}{property.Width}{property.Height}",
4 => string.Empty, 4 => string.Empty,
@ -313,7 +313,7 @@ public class PropertyCompareLogic
} }
if (exceptionCount != 0) if (exceptionCount != 0)
throw new Exception(); throw new Exception();
return (from l in results orderby Property.Models.Stateless.A_Property.GetMinimumDateTime(l.Property).Ticks select l).ToArray(); return (from l in results orderby Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(l.Property).Ticks select l).ToArray();
} }
private void MoveFiles(string[] directories, List<string[]> fromThenToCollection) private void MoveFiles(string[] directories, List<string[]> fromThenToCollection)

View File

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

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;
using System.Text.Json.Serialization; using View_by_Distance.Property.Models.Stateless;
using View_by_Distance.Shared.Models.Methods; 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; namespace View_by_Distance.Property.Models;
/// <summary> public class A_Property
// A_Property
/// </summary>
public class A_Property : Shared.Models.Properties.IProperty, IProperty
{ {
protected DateTime _CreationTime; protected readonly List<string> _ExceptionsDirectories;
protected DateTime? _DateTime; protected readonly Dictionary<int, int[]> _KeyValuePairs;
protected DateTime? _DateTimeDigitized; protected readonly Dictionary<int, int[]> _IndicesFromNew;
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 bool Reverse { get; }
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 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; _Model = model;
_Orientation = orientation; Reverse = reverse;
_Width = width; _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(int maxDegreeOfParallelism, Configuration configuration, string outputExtension, bool reverse, Model? model, PredictorModel? predictorModel) :
this(maxDegreeOfParallelism, configuration, outputExtension, reverse, model, predictorModel, new(), new())
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() public override string ToString()
{ {
@ -86,38 +64,658 @@ public class A_Property : Shared.Models.Properties.IProperty, IProperty
return result; return result;
} }
public List<DateTime> GetDateTimes() => Stateless.A_Property.GetDateTimes(_CreationTime, _LastWriteTime, _DateTime, _DateTimeDigitized, _DateTimeOriginal, _GPSDateStamp); private long LogDelta(long ticks, string? methodName)
public (bool?, string[]) IsWrongYear(string filteredSourceDirectoryFile, DateTime? minimumDateTime)
{ {
string[] results = Array.Empty<string>(); long result;
bool? result = null; if (_Log is null)
string year; throw new NullReferenceException(nameof(_Log));
string directoryName; double delta = new TimeSpan(DateTime.Now.Ticks - ticks).TotalMilliseconds;
string[] directorySegments; _Log.Debug($"{methodName} took {Math.Floor(delta)} millisecond(s)");
string? check = Path.GetFullPath(filteredSourceDirectoryFile); result = DateTime.Now.Ticks;
string? pathRoot = Path.GetPathRoot(filteredSourceDirectoryFile); return result;
if (string.IsNullOrEmpty(pathRoot)) }
throw new Exception();
if (minimumDateTime.HasValue) public static List<DateTime> GetMetadataDateTimesByPattern(string dateTimeFormat, string filteredSourceDirectoryFile)
year = minimumDateTime.Value.ToString("yyyy"); {
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 else
{ {
List<DateTime> dateTimes = GetDateTimes(); ticks = DateTime.Now.Ticks;
year = dateTimes.Min().ToString("yyyy"); 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]);
} }
for (int i = 0; i < int.MaxValue; i++) }
width = image.Width;
height = image.Height;
dateTimeFormat = Shared.Models.Stateless.Methods.IProperty.DateTimeFormat();
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTime))
{ {
check = Path.GetDirectoryName(check); propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTime);
if (string.IsNullOrEmpty(check) || check == pathRoot) if (propertyItem?.Value is not null)
break; {
directoryName = Path.GetFileName(check); value = _ASCIIEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
directorySegments = directoryName.Split(' '); if (value.Length > dateTimeFormat.Length)
(result, results) = Stateless.A_Property.IsWrongYear(directorySegments, year); value = value[..dateTimeFormat.Length];
if (result.HasValue) 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
{
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));
}
}
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 && 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));
}
}
}
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; break;
} }
return new(result, results); _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.ComponentModel.DataAnnotations;
using System.Text.Json; using System.Text.Json;
@ -6,6 +8,8 @@ namespace View_by_Distance.Property.Models.Binder;
public class Configuration public class Configuration
{ {
#nullable disable
[Display(Name = "Date Group"), Required] public string DateGroup { get; set; } [Display(Name = "Date Group"), Required] public string DateGroup { get; set; }
[Display(Name = "File Name Directory Separator"), Required] public string FileNameDirectorySeparator { 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 = "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 = "Verify to Season"), Required] public string[] VerifyToSeason { get; set; }
[Display(Name = "Write Bitmap Data Bytes"), Required] public bool? WriteBitmapDataBytes { get; set; } [Display(Name = "Write Bitmap Data Bytes"), Required] public bool? WriteBitmapDataBytes { get; set; }
public Configuration() #nullable restore
{
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() public override string ToString()
{ {
@ -45,4 +33,61 @@ public class Configuration
return result; 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

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

View File

@ -3,24 +3,24 @@ namespace View_by_Distance.Property.Models;
public class DirectoryInfo public class DirectoryInfo
{ {
protected readonly FileHolder[] _SourceDirectoryFileHolderCollection; protected readonly Shared.Models.FileHolder[] _SourceDirectoryFileHolderCollection;
protected readonly string[] _FilteredSourceDirectoryFiles; protected readonly string[] _FilteredSourceDirectoryFiles;
protected readonly int _G; protected readonly int _G;
protected readonly bool[] _Moved; protected readonly bool[] _Moved;
protected readonly bool?[] _Changed; protected readonly bool?[] _Changed;
protected readonly A_Property?[] _PropertyCollection; protected readonly Shared.Models.Property?[] _PropertyCollection;
protected readonly FileInfo?[] _PropertyFileHolderCollection; protected readonly FileInfo?[] _PropertyFileHolderCollection;
protected readonly int _R; protected readonly int _R;
protected readonly string _SourceDirectory; protected readonly string _SourceDirectory;
protected readonly bool[] _ValidImageFormatExtensionCollection; protected readonly bool[] _ValidImageFormatExtensionCollection;
protected readonly bool[] _WrongYear; protected readonly bool[] _WrongYear;
public FileHolder[] SourceDirectoryFileHolderCollection => _SourceDirectoryFileHolderCollection; public Shared.Models.FileHolder[] SourceDirectoryFileHolderCollection => _SourceDirectoryFileHolderCollection;
[Obsolete($"Use {nameof(SourceDirectoryFileHolderCollection)}")] [Obsolete($"Use {nameof(SourceDirectoryFileHolderCollection)}")]
public string[] FilteredSourceDirectoryFiles => _FilteredSourceDirectoryFiles; public string[] FilteredSourceDirectoryFiles => _FilteredSourceDirectoryFiles;
public int G => _G; public int G => _G;
public bool[] Moved => _Moved; public bool[] Moved => _Moved;
public bool?[] Changed => _Changed; public bool?[] Changed => _Changed;
public A_Property?[] PropertyCollection => _PropertyCollection; public Shared.Models.Property?[] PropertyCollection => _PropertyCollection;
public FileInfo?[] PropertyFileHolderCollection => _PropertyFileHolderCollection; public FileInfo?[] PropertyFileHolderCollection => _PropertyFileHolderCollection;
public int R => _R; public int R => _R;
public string SourceDirectory => _SourceDirectory; public string SourceDirectory => _SourceDirectory;
@ -37,10 +37,11 @@ public class DirectoryInfo
_Moved = Enumerable.Repeat(false, length).ToArray(); _Moved = Enumerable.Repeat(false, length).ToArray();
_WrongYear = Enumerable.Repeat(false, length).ToArray(); _WrongYear = Enumerable.Repeat(false, length).ToArray();
_FilteredSourceDirectoryFiles = filteredSourceDirectoryFiles; _FilteredSourceDirectoryFiles = filteredSourceDirectoryFiles;
_PropertyCollection = Enumerable.Repeat<A_Property?>(null, length).ToArray();
_ValidImageFormatExtensionCollection = Enumerable.Repeat(false, length).ToArray(); _ValidImageFormatExtensionCollection = Enumerable.Repeat(false, length).ToArray();
_PropertyFileHolderCollection = Enumerable.Repeat<FileInfo?>(null, 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,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,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 System.Text.Json;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Property.Models.Stateless; namespace View_by_Distance.Property.Models.Stateless;
@ -98,67 +99,61 @@ public class Container
return results; 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; List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> results;
if (configuration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new NullReferenceException(nameof(configuration.MaxImagesInDirectoryForTopLevelFirstPass));
string searchPattern = "*.json"; string searchPattern = "*.json";
List<string> topDirectories = new(); 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; 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(); List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles, int r)> results = new();
if (configuration.MaxImagesInDirectoryForTopLevelFirstPass is null) List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)>? collection = GetGroupCollection(configuration.RootDirectory, configuration.MaxImagesInDirectoryForTopLevelFirstPass, propertyLogic.Reverse, searchPattern, topDirectories);
throw new NullReferenceException(nameof(configuration.MaxImagesInDirectoryForTopLevelFirstPass));
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)>? collection = GetGroupCollection(configuration.RootDirectory, configuration.MaxImagesInDirectoryForTopLevelFirstPass.Value, propertyLogic.Reverse, searchPattern, topDirectories);
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in collection) 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)); results.Add(new(g, sourceDirectory, (from l in sourceDirectoryFiles select new FileHolder(l)).ToArray(), r));
return results; 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 key;
string json; string json;
Models.A_Property? property; Shared.Models.Property? property;
(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) = jsonCollection[i]; (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) foreach (string sourceDirectoryFile in sourceDirectoryFiles)
{ {
json = File.ReadAllText(sourceDirectoryFile); json = File.ReadAllText(sourceDirectoryFile);
key = XPath.GetRelativePath(sourceDirectoryFile, length); key = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFile, length);
property = JsonSerializer.Deserialize<Models.A_Property>(json); property = JsonSerializer.Deserialize<Shared.Models.Property>(json);
collection.Add(new(sourceDirectoryFile, property)); collection.Add(new(sourceDirectoryFile, property));
} }
lock (results) lock (results)
results.Add(new(g, sourceDirectory, collection, r)); 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; int length = rootDirectory.Length;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = Environment.ProcessorCount }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = Environment.ProcessorCount };
_ = Parallel.For(0, jsonCollection.Count, parallelOptions, i => ParallelFor(jsonCollection, i, length, results)); _ = Parallel.For(0, jsonCollection.Count, parallelOptions, i => ParallelFor(jsonCollection, i, length, results));
return 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(); List<Shared.Models.Container> results = new();
if (configuration.PropertiesChangedForProperty is null)
throw new Exception($"{configuration.PropertiesChangedForProperty} is null");
int length; int length;
string key; string key;
string inferred; string inferred;
List<Item> items; List<Item> items;
string relativePath; string relativePath;
FileHolder keyFileHolder; FileHolder keyFileHolder;
Models.Container container; Shared.Models.Container container;
bool isValidImageFormatExtension; bool isValidImageFormatExtension;
List<string> keySourceDirectories; List<string> keySourceDirectories;
Dictionary<string, (string SourceDirectory, FileHolder FileHolder)> fileHolderKeyValuePairs = new(); Dictionary<string, (string SourceDirectory, FileHolder FileHolder)> fileHolderKeyValuePairs = new();
@ -167,21 +162,21 @@ public class Container
{ {
foreach (FileHolder sourceDirectoryFileHolder in sourceDirectoryFileHolderCollection) 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"); key = string.Concat(relativePath, ".json");
fileHolderKeyValuePairs.Add(key, new(sourceDirectory, sourceDirectoryFileHolder)); fileHolderKeyValuePairs.Add(key, new(sourceDirectory, sourceDirectoryFileHolder));
} }
} }
length = aPropertySingletonDirectory.Length; 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()) if (!collection.Any())
continue; continue;
items = new(); items = new();
keySourceDirectories = 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]; relativePath = key[..^5];
if (!fileHolderKeyValuePairs.ContainsKey(key)) if (!fileHolderKeyValuePairs.ContainsKey(key))
{ {
@ -204,7 +199,7 @@ public class Container
isValidImageFormatExtension = configuration.ValidImageFormatExtensions.Contains(keyFileHolder.ExtensionLowered); isValidImageFormatExtension = configuration.ValidImageFormatExtensions.Contains(keyFileHolder.ExtensionLowered);
if (property?.Id is null || property?.Width is null || property?.Height is null) if (property?.Id is null || property?.Width is null || property?.Height is null)
items.Add(new(sourceDirectoryFile, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, 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)); items.Add(new(sourceDirectoryFile, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, true));
else else
items.Add(new(sourceDirectoryFile, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, false)); items.Add(new(sourceDirectoryFile, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, false));
@ -224,7 +219,7 @@ public class Container
items = new(); items = new();
foreach (FileHolder sourceDirectoryFileHolder in sourceDirectoryFileHolderCollection) 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"); key = string.Concat(relativePath, ".json");
if (!fileHolderKeyValuePairs.ContainsKey(key)) if (!fileHolderKeyValuePairs.ContainsKey(key))
continue; continue;
@ -247,16 +242,15 @@ public class Container
return results; 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 = "*"; string searchPattern = "*";
long ticks = DateTime.Now.Ticks;
List<string> topDirectories = new(); List<string> topDirectories = new();
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> jsonCollection; List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> jsonCollection;
List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles, int r)> fileHolderGroupCollection; List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles, int r)> fileHolderGroupCollection;
string aPropertySingletonDirectory = IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); 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); jsonCollection = GetJsonGroupCollection(configuration, propertyLogic, aPropertySingletonDirectory);
fileHolderGroupCollection = GetFileHolderGroupCollection(configuration, propertyLogic, searchPattern, topDirectories); fileHolderGroupCollection = GetFileHolderGroupCollection(configuration, propertyLogic, searchPattern, topDirectories);
collectionFromJson = GetCollection(aPropertySingletonDirectory, jsonCollection); collectionFromJson = GetCollection(aPropertySingletonDirectory, jsonCollection);

View File

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

View File

@ -5,13 +5,13 @@ namespace View_by_Distance.Property.Models.Stateless;
internal class Result 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; 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("_", ") ")); string result = Path.Combine($"{configuration.RootDirectory} - Results", description.Replace("_", ") "));
if (!Directory.Exists(result)) if (!Directory.Exists(result))
@ -19,7 +19,7 @@ internal class Result
return 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); string result = Path.Combine(GetResultsGroupDirectory(configuration, description), configuration.DateGroup);
if (!Directory.Exists(result)) if (!Directory.Exists(result))
@ -27,7 +27,7 @@ internal class Result
return 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); string result = Path.Combine(GetResultsDateGroupDirectory(configuration, description), jsonGroup);
if (!Directory.Exists(result)) if (!Directory.Exists(result))
@ -35,7 +35,7 @@ internal class Result
return 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); string result = GetResultsDateGroupDirectory(configuration, description);
if (includeResizeGroup) if (includeResizeGroup)
@ -64,14 +64,9 @@ internal class Result
return 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)
{ {
List<string> results = new();
string checkDirectory; 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); checkDirectory = Path.Combine(dateGroupDirectory, IResult.Content, IResult.AllInOne);
if (!Directory.Exists(checkDirectory)) if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory); _ = Directory.CreateDirectory(checkDirectory);
@ -82,8 +77,10 @@ internal class Result
if (!Directory.Exists(checkDirectory)) if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory); _ = Directory.CreateDirectory(checkDirectory);
} }
if (!string.IsNullOrEmpty(singletonDescription))
private static void CheckSingleton(string dateGroupDirectory, string singletonDescription, bool converted, string result)
{ {
string checkDirectory;
checkDirectory = Path.Combine(dateGroupDirectory, IResult.Singleton, IResult.AllInOne); checkDirectory = Path.Combine(dateGroupDirectory, IResult.Singleton, IResult.AllInOne);
if (!Directory.Exists(checkDirectory)) if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory); _ = Directory.CreateDirectory(checkDirectory);
@ -97,9 +94,10 @@ internal class Result
if (!Directory.Exists(checkDirectory)) if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory); _ = Directory.CreateDirectory(checkDirectory);
} }
if (!string.IsNullOrEmpty(collectionDescription))
private static void CheckCollection(string dateGroupDirectory, string collectionDescription, bool converted, string result)
{ {
checkDirectory = Path.Combine(dateGroupDirectory, IResult.Collection, IResult.AllInOne); string checkDirectory = Path.Combine(dateGroupDirectory, IResult.Collection, IResult.AllInOne);
if (!Directory.Exists(checkDirectory)) if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory); _ = Directory.CreateDirectory(checkDirectory);
if (!converted) if (!converted)
@ -112,11 +110,23 @@ internal class Result
if (!Directory.Exists(checkDirectory)) if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(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 sourceDirectorySegment = GetRelativePath(configuration, sourceDirectory);
string result = string.Concat(Path.Combine(dateGroupDirectory, "<>"), sourceDirectorySegment);
if (!string.IsNullOrEmpty(contentDescription))
CheckContent(dateGroupDirectory, contentDescription, result);
if (!string.IsNullOrEmpty(singletonDescription))
CheckSingleton(dateGroupDirectory, singletonDescription, converted, result);
if (!string.IsNullOrEmpty(collectionDescription))
CheckCollection(dateGroupDirectory, collectionDescription, converted, result);
results.Add(result); results.Add(result);
return results; 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; List<string> results;
bool converted = false; bool converted = false;

View File

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

View File

@ -6,7 +6,6 @@ using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Metadata.Models; using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Resize.Models; namespace View_by_Distance.Resize.Models;
@ -19,6 +18,9 @@ public class C_Resize
public List<string> AngleBracketCollection { get; } public List<string> AngleBracketCollection { get; }
protected readonly string _FilenameExtension;
public string FilenameExtension => _FilenameExtension;
private readonly Serilog.ILogger? _Log; private readonly Serilog.ILogger? _Log;
private readonly int _TempResolutionWidth; private readonly int _TempResolutionWidth;
private readonly int _TempResolutionHeight; private readonly int _TempResolutionHeight;
@ -35,7 +37,7 @@ public class C_Resize
private readonly bool _ForceResizeLastWriteTimeToCreationTime; private readonly bool _ForceResizeLastWriteTimeToCreationTime;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
public C_Resize(bool forceResizeLastWriteTimeToCreationTime, bool overrideForResizeImages, bool propertiesChangedForResize, string[] validResolutions, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters) public C_Resize(bool forceResizeLastWriteTimeToCreationTime, bool overrideForResizeImages, bool propertiesChangedForResize, string[] validResolutions, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension)
{ {
_TempResolutionWidth = 3; _TempResolutionWidth = 3;
_TempResolutionHeight = 4; _TempResolutionHeight = 4;
@ -46,6 +48,7 @@ public class C_Resize
_ValidResolutions = validResolutions; _ValidResolutions = validResolutions;
_OutputResolutionOrientationIndex = 2; _OutputResolutionOrientationIndex = 2;
_EncoderParameters = encoderParameters; _EncoderParameters = encoderParameters;
_FilenameExtension = filenameExtension;
_Log = Serilog.Log.ForContext<C_Resize>(); _Log = Serilog.Log.ForContext<C_Resize>();
AngleBracketCollection = new List<string>(); AngleBracketCollection = new List<string>();
_OverrideForResizeImages = overrideForResizeImages; _OverrideForResizeImages = overrideForResizeImages;
@ -66,14 +69,44 @@ public class C_Resize
#pragma warning disable CA1416 #pragma warning disable CA1416
public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters) GetTuple(string outputExtension, int outputQuality) public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetGifLowQuality()
{ {
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters) result; (ImageCodecInfo, EncoderParameters, string) result;
System.Drawing.Imaging.ImageFormat imageFormat = System.Drawing.Imaging.ImageFormat.Gif;
ImageCodecInfo imageCodecInfo = (from l in ImageCodecInfo.GetImageEncoders() where l.FormatID == imageFormat.Guid select l).First();
EncoderParameters encoderParameters = new(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L);
if (string.IsNullOrEmpty(imageCodecInfo.FilenameExtension))
throw new NullReferenceException(nameof(imageCodecInfo.FilenameExtension));
result = new(imageCodecInfo, encoderParameters, imageCodecInfo.FilenameExtension.Split(';')[0].ToLower()[1..]);
return result;
}
public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetPngLowQuality()
{
(ImageCodecInfo, EncoderParameters, string) result;
System.Drawing.Imaging.ImageFormat imageFormat = System.Drawing.Imaging.ImageFormat.Png;
ImageCodecInfo imageCodecInfo = (from l in ImageCodecInfo.GetImageEncoders() where l.FormatID == imageFormat.Guid select l).First();
EncoderParameters encoderParameters = new(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L);
if (string.IsNullOrEmpty(imageCodecInfo.FilenameExtension))
throw new NullReferenceException(nameof(imageCodecInfo.FilenameExtension));
result = new(imageCodecInfo, encoderParameters, imageCodecInfo.FilenameExtension.Split(';')[0].ToLower()[1..]);
return result;
}
public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetTuple(string outputExtension, int outputQuality)
{
(ImageCodecInfo, EncoderParameters, string) result;
System.Drawing.Imaging.ImageFormat imageFormat = outputExtension switch System.Drawing.Imaging.ImageFormat imageFormat = outputExtension switch
{ {
".gif" => System.Drawing.Imaging.ImageFormat.Gif, ".gif" => System.Drawing.Imaging.ImageFormat.Gif,
".jfif" => System.Drawing.Imaging.ImageFormat.Jpeg,
".jpe" => System.Drawing.Imaging.ImageFormat.Jpeg,
".jpeg" => System.Drawing.Imaging.ImageFormat.Jpeg,
".jpg" => System.Drawing.Imaging.ImageFormat.Jpeg, ".jpg" => System.Drawing.Imaging.ImageFormat.Jpeg,
".png" => System.Drawing.Imaging.ImageFormat.Png, ".png" => System.Drawing.Imaging.ImageFormat.Png,
".tif" => System.Drawing.Imaging.ImageFormat.Tiff,
".tiff" => System.Drawing.Imaging.ImageFormat.Tiff, ".tiff" => System.Drawing.Imaging.ImageFormat.Tiff,
_ => throw new Exception(), _ => throw new Exception(),
}; };
@ -82,7 +115,9 @@ public class C_Resize
// encoderParameters.Param[0] = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, CType(75L, Int32)) 'Default // encoderParameters.Param[0] = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, CType(75L, Int32)) 'Default
// encoderParameters.Param[0] = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, CType(95L, Int32)) 'Paint // encoderParameters.Param[0] = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, CType(95L, Int32)) 'Paint
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, outputQuality); encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, outputQuality);
result = new(imageCodecInfo, encoderParameters); if (string.IsNullOrEmpty(imageCodecInfo.FilenameExtension))
throw new NullReferenceException(nameof(imageCodecInfo.FilenameExtension));
result = new(imageCodecInfo, encoderParameters, imageCodecInfo.FilenameExtension.Split(';')[0].ToLower()[1..]);
return result; return result;
} }
@ -129,7 +164,7 @@ public class C_Resize
} }
} }
private byte[] SaveResizedSubfile3(string subFile, int[] resize, byte[] bytes, FileHolder? fileHolder) private byte[] SaveResizedSubfile3(string subFile, int[] resize, byte[] bytes, Shared.Models.FileHolder? fileHolder)
{ {
byte[] results; byte[] results;
Bitmap bitmap; Bitmap bitmap;
@ -181,7 +216,7 @@ public class C_Resize
return results; return results;
} }
private byte[] SaveResizedSubfile5(string subFile, int[] resize, byte[] bytes, FileHolder? fileHolder) private byte[] SaveResizedSubfile5(string subFile, int[] resize, byte[] bytes, Shared.Models.FileHolder? fileHolder)
{ {
byte[] results; byte[] results;
Bitmap bitmap; Bitmap bitmap;
@ -248,11 +283,11 @@ public class C_Resize
#pragma warning restore CA1416 #pragma warning restore CA1416
private byte[] SaveResizedSubfile(string subFile, A_Property property, int[] resize, FileHolder? fileHolder) private byte[] SaveResizedSubfile(string subFile, Shared.Models.Property property, int[] resize, Shared.Models.FileHolder? fileHolder)
{ {
byte[] results; byte[] results;
string dateTimeFormat = Property.Models.Stateless.A_Property.DateTimeFormat(); string dateTimeFormat = Shared.Models.Stateless.Methods.IProperty.DateTimeFormat();
DateTime dateTime = Property.Models.Stateless.A_Property.GetMinimumDateTime(property); DateTime dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
string dateTimeValue = dateTime.ToString(dateTimeFormat); string dateTimeValue = dateTime.ToString(dateTimeFormat);
byte[] bytes = _ASCIIEncoding.GetBytes(dateTimeValue); byte[] bytes = _ASCIIEncoding.GetBytes(dateTimeValue);
if (_ASCIIEncoding.GetString(bytes, 0, bytes.Length) != dateTimeValue) if (_ASCIIEncoding.GetString(bytes, 0, bytes.Length) != dateTimeValue)
@ -284,7 +319,7 @@ public class C_Resize
return results; return results;
} }
public byte[] GetResizedBytes(string outputResolution, string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, Item item, A_Property property, Dictionary<string, int[]> imageResizes) public byte[] GetResizedBytes(string outputResolution, string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, Shared.Models.Item item, Shared.Models.Property property, Dictionary<string, int[]> imageResizes)
{ {
byte[] results; byte[] results;
if (item.ImageFileHolder is null) if (item.ImageFileHolder is null)
@ -300,7 +335,7 @@ public class C_Resize
return results; return results;
} }
public void SaveResizedSubfile(string outputResolution, string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, Item item, string original, Dictionary<string, int[]> imageResizes) public void SaveResizedSubfile(string outputResolution, string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, Shared.Models.Item item, string original, Dictionary<string, int[]> imageResizes)
{ {
if (item.Property is null) if (item.Property is null)
throw new NullReferenceException(nameof(item.Property)); throw new NullReferenceException(nameof(item.Property));
@ -308,7 +343,7 @@ public class C_Resize
throw new NullReferenceException(nameof(item.ImageFileHolder)); throw new NullReferenceException(nameof(item.ImageFileHolder));
if (item.ResizedFileHolder is null) if (item.ResizedFileHolder is null)
throw new NullReferenceException(nameof(item.ResizedFileHolder)); throw new NullReferenceException(nameof(item.ResizedFileHolder));
FileHolder fileHolder = item.ResizedFileHolder; Shared.Models.FileHolder fileHolder = item.ResizedFileHolder;
if (!imageResizes.ContainsKey(outputResolution)) if (!imageResizes.ContainsKey(outputResolution))
throw new Exception(); throw new Exception();
if (!fileHolder.Exists) if (!fileHolder.Exists)
@ -320,7 +355,7 @@ public class C_Resize
if (File.Exists(parentCheck)) if (File.Exists(parentCheck))
{ {
File.Move(parentCheck, fileInfo.FullName); File.Move(parentCheck, fileInfo.FullName);
item.SetResizedFileHolder(FileHolder.Refresh(fileHolder)); item.SetResizedFileHolder(_FilenameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(fileHolder));
} }
} }
int[] resize = imageResizes[outputResolution]; int[] resize = imageResizes[outputResolution];
@ -339,7 +374,7 @@ public class C_Resize
else else
{ {
bool check = false; bool check = false;
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata), nameof(C_Resize) };
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
if (_OverrideForResizeImages) if (_OverrideForResizeImages)
check = true; check = true;
@ -378,7 +413,7 @@ public class C_Resize
return result; return result;
} }
private Dictionary<string, int[]> GetImageResizes(A_Property property, List<KeyValuePair<string, string>> metadataCollection, string original) private Dictionary<string, int[]> GetImageResizes(Shared.Models.Property property, List<KeyValuePair<string, string>> metadataCollection, string original)
{ {
Dictionary<string, int[]> results = new(); Dictionary<string, int[]> results = new();
int[] desired; int[] desired;
@ -424,7 +459,7 @@ public class C_Resize
return results; return results;
} }
public Dictionary<string, int[]> GetResizeKeyValuePairs(string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string original, List<KeyValuePair<string, string>> metadataCollection, Item item) public Dictionary<string, int[]> GetResizeKeyValuePairs(string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string original, List<KeyValuePair<string, string>> metadataCollection, Shared.Models.Item item)
{ {
Dictionary<string, int[]> results; Dictionary<string, int[]> results;
if (item.Property?.Id is null) if (item.Property?.Id is null)
@ -432,7 +467,7 @@ public class C_Resize
if (item.ImageFileHolder is null) if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder)); throw new NullReferenceException(nameof(item.ImageFileHolder));
string json; string json;
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata) }; string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata) };
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
string usingRelativePath = Path.Combine(AngleBracketCollection[0].Replace("<>", "{}"), string.Concat(item.ImageFileHolder.NameWithoutExtension, ".json")); string usingRelativePath = Path.Combine(AngleBracketCollection[0].Replace("<>", "{}"), string.Concat(item.ImageFileHolder.NameWithoutExtension, ".json"));
string cResizeSingletonFile = Path.Combine(cResultsFullGroupDirectory, "{}", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}.json"); string cResizeSingletonFile = Path.Combine(cResultsFullGroupDirectory, "{}", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}.json");
@ -504,7 +539,7 @@ public class C_Resize
json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions);
bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime;
DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime))
{ {
if (!_ForceResizeLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime)) if (!_ForceResizeLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(C_Resize), DateTime.Now)); subFileTuples.Add(new Tuple<string, DateTime>(nameof(C_Resize), DateTime.Now));

View File

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

1
Shared/.vscode/format-report.json vendored Normal file
View File

@ -0,0 +1 @@
[]

View File

@ -1,14 +1,10 @@
using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Property.Models; namespace View_by_Distance.Shared.Models;
public class Closest public class Closest : Properties.IClosest
{ {
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 double? _Average;
protected readonly int? _NormalizedPixelPercentage; protected readonly int? _NormalizedPixelPercentage;
@ -36,14 +32,16 @@ public class Closest
public Closest(int? normalizedPixelPercentage, DateTime minimumDateTime, bool? isWrongYear) : public Closest(int? normalizedPixelPercentage, DateTime minimumDateTime, bool? isWrongYear) :
this(null, normalizedPixelPercentage, isWrongYear, null, minimumDateTime, null) this(null, normalizedPixelPercentage, isWrongYear, null, minimumDateTime, null)
{ { }
}
public Closest(int? normalizedPixelPercentage, DateTime minimumDateTime, bool? isWrongYear, PersonBirthday? personBirthday, List<double> faceDistances) : public Closest(int? normalizedPixelPercentage, DateTime minimumDateTime, bool? isWrongYear, PersonBirthday? personBirthday, List<double> faceDistances) :
this(faceDistances.Average(), normalizedPixelPercentage, isWrongYear, faceDistances.Min(), minimumDateTime, personBirthday) this(faceDistances.Average(), normalizedPixelPercentage, isWrongYear, faceDistances.Min(), minimumDateTime, personBirthday)
{ }
public override string ToString()
{ {
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
} }
public static Closest[] Get(List<Closest> collection) => (from l in collection orderby l.Minimum < MinimumMinimum, l.Average select l).ToArray();
} }

View File

@ -1,8 +1,9 @@
using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Property.Models; namespace View_by_Distance.Shared.Models;
public class Container public class Container : Properties.IContainer
{ {
protected readonly int _G; protected readonly int _G;
@ -31,4 +32,10 @@ public class Container
_SourceDirectory = sourceDirectory; _SourceDirectory = sourceDirectory;
} }
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
} }

View File

@ -1,10 +1,9 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class DirectoryFileSystem : FileSystem, Properties.IDirectoryFileSystem, IDirectoryFileSystem public class DirectoryFileSystem : FileSystem, Properties.IDirectoryFileSystem
{ {
// protected new string _ClassName; // protected new string _ClassName;

View File

@ -1,38 +1,32 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.FaceRecognitionDotNet;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models.Properties;
namespace View_by_Distance.Instance.Models; namespace View_by_Distance.Shared.Models;
internal class DistanceHolder public class DistanceHolder : Properties.IDistanceHolder
{ {
public IFace Face { init; get; } public Face Face { init; get; }
public FaceEncoding? FaceEncoding { init; get; }
public FileHolder FileHolder { init; get; } public FileHolder FileHolder { init; get; }
public int Id { init; get; } public int Id { init; get; }
public string JSONDirectory { init; get; } public string JSONDirectory { init; get; }
public ILocation Location { init; get; } public Location? Location { init; get; }
public string TSVDirectory { init; get; } public string TSVDirectory { init; get; }
public double Sort { get; set; } public double Sort { get; set; }
[JsonConstructor] [JsonConstructor]
public DistanceHolder( public DistanceHolder(
IFace face, Face face,
FaceEncoding? faceEncoding,
FileHolder fileHolder, FileHolder fileHolder,
int id, int id,
string jsonDirectory, string jsonDirectory,
ILocation location, Location? location,
string tsvDirectory string tsvDirectory
) )
{ {
FileHolder = fileHolder; FileHolder = fileHolder;
Sort = double.MaxValue; Sort = double.MaxValue;
Face = face; Face = face;
FaceEncoding = faceEncoding;
Id = id; Id = id;
JSONDirectory = jsonDirectory; JSONDirectory = jsonDirectory;
Location = location; Location = location;

View File

@ -1,52 +1,68 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class Face : Properties.IFace, IFace public class Face : Properties.IFace
{ {
protected double? _Α;
protected DateTime _DateTime; protected DateTime _DateTime;
protected FaceEncoding _FaceEncoding; protected FaceEncoding? _FaceEncoding;
protected Dictionary<string, FacePoint[]> _FaceLandmarks; protected Dictionary<Stateless.FacePart, FacePoint[]>? _FaceParts;
protected OutputResolution _OutputResolution; protected readonly OutputResolution? _OutputResolution;
protected Location _Location; protected Location? _Location;
protected int? _LocationIndex; protected readonly int? _LocationIndex;
protected bool _Populated; protected readonly string _RelativePath;
protected string _RelativePath;
public double? α => _Α;
public DateTime DateTime => _DateTime; public DateTime DateTime => _DateTime;
public FaceEncoding FaceEncoding => _FaceEncoding; public FaceEncoding? FaceEncoding => _FaceEncoding;
public Dictionary<string, FacePoint[]> FaceLandmarks => _FaceLandmarks; public Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts => _FaceParts;
public OutputResolution OutputResolution => _OutputResolution; public Location? Location => _Location;
public Location Location => _Location;
public int? LocationIndex => _LocationIndex; public int? LocationIndex => _LocationIndex;
public bool Populated => _Populated; public OutputResolution? OutputResolution => _OutputResolution;
public string RelativePath => _RelativePath; public string RelativePath => _RelativePath;
[JsonConstructor] [JsonConstructor]
public Face(double? α, DateTime dateTime, FaceEncoding faceEncoding, Dictionary<string, FacePoint[]> faceLandmarks, OutputResolution outputResolution, Location location, int? locationIndex, bool populated, string relativePath) public Face(DateTime dateTime, FaceEncoding? faceEncoding, Dictionary<Stateless.FacePart, FacePoint[]>? faceParts, Location? location, int? locationIndex, OutputResolution? outputResolution, string relativePath)
{ {
_Α = α;
_DateTime = dateTime; _DateTime = dateTime;
_FaceEncoding = faceEncoding; _FaceEncoding = faceEncoding;
_FaceLandmarks = faceLandmarks; _FaceParts = faceParts;
_Location = location; _Location = location;
_LocationIndex = locationIndex; _LocationIndex = locationIndex;
_OutputResolution = outputResolution; _OutputResolution = outputResolution;
_Populated = populated;
_RelativePath = relativePath; _RelativePath = relativePath;
} }
double Stateless.Methods.IFace.TestStatic_Getα(int x1, int x2, int y1, int y2) => throw new NotImplementedException(); public Face() :
this(DateTime.MinValue, null, null, null, null, null, string.Empty)
{ }
string Stateless.Methods.IFace.TestStatic_GetJson(string jsonFileFullName) => throw new NotImplementedException(); public Face(Location location) :
this(DateTime.MinValue, null, null, location, null, null, string.Empty)
{ }
Face Stateless.Methods.IFace.TestStatic_GetFace(string jsonFileFullName) => throw new NotImplementedException(); public Face(int facesCount, Face face) :
this(face.DateTime, face.FaceEncoding, face.FaceParts, face.Location, face.LocationIndex, face.OutputResolution, face.RelativePath)
{
if (face.Location?.Confidence is not null && face.OutputResolution is not null)
_Location = new(face.Location.Confidence, face.OutputResolution.Height, face.Location, face.OutputResolution.Width, facesCount);
}
Face[] Stateless.Methods.IFace.TestStatic_GetFaces(string jsonFileFullName) => throw new NotImplementedException(); public Face(int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, Face face) :
this(face.DateTime, face.FaceEncoding, face.FaceParts, face.Location, face.LocationIndex, null, face.RelativePath)
{
if (outputResolutionHeight > 0)
_OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth);
}
public Face(Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string relativePath, int? i, Location? location) :
this(DateTime.MinValue, null, null, location, i, null, relativePath)
{
DateTime?[] dateTimes;
_OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth);
dateTimes = new DateTime?[] { property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeOriginal, property.GPSDateStamp };
_DateTime = (from l in dateTimes where l.HasValue select l.Value).Min();
}
public override string ToString() public override string ToString()
{ {
@ -54,4 +70,7 @@ public class Face : Properties.IFace, IFace
return result; return result;
} }
public void SetFaceEncoding(FaceEncoding faceEncoding) => _FaceEncoding = faceEncoding;
public void SetFaceParts(Dictionary<Stateless.FacePart, FacePoint[]> faceParts) => _FaceParts = faceParts;
} }

View File

@ -1,10 +1,9 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class FaceEncoding : Properties.IFaceEncoding, IFaceEncoding public class FaceEncoding : Properties.IFaceEncoding
{ {
protected double[] _RawEncoding; protected double[] _RawEncoding;

View File

@ -1,10 +1,9 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class FaceFileSystem : FileSystem, Properties.IFaceFileSystem, IFaceFileSystem public class FaceFileSystem : FileSystem, Properties.IFaceFileSystem
{ {
// protected new string _ClassName; // protected new string _ClassName;
@ -77,6 +76,38 @@ public class FaceFileSystem : FileSystem, Properties.IFaceFileSystem, IFaceFileS
_SourceSize = sourceSize; _SourceSize = sourceSize;
} }
private static void FileExists(Face face, int? faceBottom, int? faceRight, out int imageHeight, out int imageWidth, out long sourceSize, FileInfo fileInfo)
{
sourceSize = fileInfo.Length;
if (face.OutputResolution is not null)
{
imageWidth = face.OutputResolution.Width;
imageHeight = face.OutputResolution.Height;
}
else
{
System.Drawing.Size size = Stateless.Methods.ImageHelper.GetDimensions(fileInfo.FullName, faceRight, faceBottom);
imageWidth = size.Width;
imageHeight = size.Height;
}
}
private static void FileDoesNotExist(string dataFullFileName, Face face, out int imageHeight, out int imageWidth, out long sourceSize, FileInfo fileInfo)
{
sourceSize = 0;
if (face.OutputResolution is null)
{
imageWidth = 0;
imageHeight = 0;
}
else
{
imageWidth = face.OutputResolution.Width;
imageHeight = face.OutputResolution.Height;
}
Stateless.Methods.IFaceFileSystem.SearchForMissingFile(fileInfo.FullName, fileInfo, dataFullFileName);
}
internal FaceFileSystem(string requestPath, int rootResultsDirectoryAbsoluteUriLength, string cResizeContent, string dFacesContentDirectory, string dataFullFileName, Face face) : base(string.Empty, string.Empty, dataFullFileName, string.Empty, DateTime.MinValue) internal FaceFileSystem(string requestPath, int rootResultsDirectoryAbsoluteUriLength, string cResizeContent, string dFacesContentDirectory, string dataFullFileName, Face face) : base(string.Empty, string.Empty, dataFullFileName, string.Empty, DateTime.MinValue)
{ {
string confidence; string confidence;
@ -130,38 +161,12 @@ public class FaceFileSystem : FileSystem, Properties.IFaceFileSystem, IFaceFileS
string faceRelativePath = string.Concat(requestPath, new Uri(faceFullFileName).AbsoluteUri[rootResultsDirectoryAbsoluteUriLength..]); string faceRelativePath = string.Concat(requestPath, new Uri(faceFullFileName).AbsoluteUri[rootResultsDirectoryAbsoluteUriLength..]);
string sourceRelativePath = string.Concat(requestPath, new Uri(sourceFullFileName).AbsoluteUri[rootResultsDirectoryAbsoluteUriLength..]); string sourceRelativePath = string.Concat(requestPath, new Uri(sourceFullFileName).AbsoluteUri[rootResultsDirectoryAbsoluteUriLength..]);
FileInfo fileInfo = new(sourceFullFileName); FileInfo fileInfo = new(sourceFullFileName);
if (face.Populated && !File.Exists(faceFullFileName)) if (face.FaceEncoding is not null && face.Location?.NormalizedPixelPercentage is not null && !File.Exists(faceFullFileName))
Stateless.Methods.IFaceFileSystem.SearchForMissingFile(faceFullFileName, fileInfo: new FileInfo(string.Empty), dataFullFileName); Stateless.Methods.IFaceFileSystem.SearchForMissingFile(faceFullFileName, fileInfo: new FileInfo(string.Empty), dataFullFileName);
if (!fileInfo.Exists) if (fileInfo.Exists)
{ FileExists(face, faceBottom, faceRight, out imageHeight, out imageWidth, out sourceSize, fileInfo);
sourceSize = 0;
if (face.OutputResolution is null)
{
imageWidth = 0;
imageHeight = 0;
}
else else
{ FileDoesNotExist(dataFullFileName, face, out imageHeight, out imageWidth, out sourceSize, fileInfo);
imageWidth = face.OutputResolution.Width;
imageHeight = face.OutputResolution.Height;
}
Stateless.Methods.IFaceFileSystem.SearchForMissingFile(fileInfo.FullName, fileInfo, dataFullFileName);
}
else
{
sourceSize = fileInfo.Length;
if (face.OutputResolution is not null)
{
imageWidth = face.OutputResolution.Width;
imageHeight = face.OutputResolution.Height;
}
else
{
System.Drawing.Size size = Stateless.Methods.ImageHelper.GetDimensions(fileInfo.FullName, faceRight, faceBottom);
imageWidth = size.Width;
imageHeight = size.Height;
}
}
_ClassName = "file"; _ClassName = "file";
_FaceBottom = faceBottom; _FaceBottom = faceBottom;
_Confidence = confidence; _Confidence = confidence;
@ -176,7 +181,7 @@ public class FaceFileSystem : FileSystem, Properties.IFaceFileSystem, IFaceFileS
_FaceLeft = faceLeft; _FaceLeft = faceLeft;
_LocationDisplayIndex = locationDisplayIndex; _LocationDisplayIndex = locationDisplayIndex;
_LocationIndex = face.LocationIndex; _LocationIndex = face.LocationIndex;
_Populated = face.Populated; _Populated = face.FaceEncoding is not null && face.Location?.NormalizedPixelPercentage is not null;
_RelativePath = string.Empty; _RelativePath = string.Empty;
_FaceRight = faceRight; _FaceRight = faceRight;
_SourceFullFileName = sourceFullFileName; _SourceFullFileName = sourceFullFileName;
@ -187,13 +192,13 @@ public class FaceFileSystem : FileSystem, Properties.IFaceFileSystem, IFaceFileS
_ImageWidth = imageWidth; _ImageWidth = imageWidth;
} }
string IFileSystem.GetDate() public override string ToString()
{ {
string result = _LastModified.ToString("MM/dd/yyyy hh:mm:ss tt"); string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result; return result;
} }
string IFaceFileSystem.GetSize() public string GetSize()
{ {
string result; string result;
if (_SourceSize is null) if (_SourceSize is null)
@ -208,19 +213,9 @@ public class FaceFileSystem : FileSystem, Properties.IFaceFileSystem, IFaceFileS
order++; order++;
len /= 1024; len /= 1024;
} }
result = String.Format("{0:0.##} {1}", len, sizes[order]); result = string.Format("{0:0.##} {1}", len, sizes[order]);
} }
return result; return result;
} }
void Stateless.Methods.IFaceFileSystem.TestStatic_SearchForMissingFile(string fullFileName, FileInfo fileInfo, string dataFullFileName) => throw new NotImplementedException();
FaceFileSystem[][] Stateless.Methods.IFaceFileSystem.TestStatic_GetFaceFileSystemCollection(string requestPath, string rootResultsDirectory, (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple, string selectedFileFullName) => throw new NotImplementedException();
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
} }

View File

@ -1,11 +1,10 @@
using System.Drawing; using System.Drawing;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class FacePoint : Properties.IFacePoint, IFacePoint public class FacePoint : Properties.IFacePoint
{ {
protected int _Index; protected int _Index;

View File

@ -1,7 +1,10 @@
namespace View_by_Distance.Property.Models; using System.Text.Json;
public class FileHolder namespace View_by_Distance.Shared.Models;
public class FileHolder : Properties.IFileHolder
{ {
protected readonly DateTime _CreationTime; protected readonly DateTime _CreationTime;
protected readonly string? _DirectoryName; protected readonly string? _DirectoryName;
protected readonly bool _Exists; protected readonly bool _Exists;
@ -65,6 +68,10 @@ public class FileHolder
_NameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName); _NameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);
} }
public static FileHolder Refresh(FileHolder fileHolder) => new(fileHolder.FullName); public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
} }

View File

@ -1,10 +1,9 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class FileSystem : Properties.IFileSystem, IFileSystem public class FileSystem : Properties.IFileSystem
{ {
protected string _ClassName; protected string _ClassName;
@ -37,14 +36,12 @@ public class FileSystem : Properties.IFileSystem, IFileSystem
_LastModified = DateTime.Now; _LastModified = DateTime.Now;
} }
string IFileSystem.GetDate() public string GetDate()
{ {
string result = _LastModified.ToString("MM/dd/yyyy hh:mm:ss tt"); string result = _LastModified.ToString("MM/dd/yyyy hh:mm:ss tt");
return result; return result;
} }
List<FileSystem> Stateless.Methods.IFileSystem.TestStatic_GetFileSystemCollection(string requestPath, string rootResultsDirectory, (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple, string[] directories, string[] files, bool all) => throw new NotImplementedException();
public override string ToString() public override string ToString()
{ {
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });

95
Shared/Models/Item.cs Normal file
View File

@ -0,0 +1,95 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public class Item : Properties.IItem
{
protected readonly bool? _Abandoned;
protected readonly bool? _Changed;
protected List<Closest> _Closest;
protected List<Face> _Faces;
protected readonly FileHolder? _ImageFileHolder;
protected bool? _Moved;
protected List<Named> _Named;
protected readonly bool? _NoJson;
protected 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<Face> Faces => _Faces;
public FileHolder? ImageFileHolder => _ImageFileHolder;
public bool? Moved => _Moved;
public bool? NoJson => _NoJson;
public List<Named> Named => _Named;
public 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<Face> faces, FileHolder? imageFileHolder, bool? moved, List<Named> named, bool? noJson, 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, 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!");
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
public void SetMoved(bool moved) => _Moved = moved;
public void SetResizedFileHolder(string filenameExtension, FileHolder fileHolder)
{
if (fileHolder.ExtensionLowered == filenameExtension)
_ResizedFileHolder = fileHolder;
else if (fileHolder.ExtensionLowered.Length > 3 && fileHolder.ExtensionLowered[3] == 'e' && fileHolder.ExtensionLowered.Remove(3, 1) == filenameExtension)
_ResizedFileHolder = fileHolder;
else
throw new NotImplementedException();
}
public bool Any() => (_Abandoned.HasValue && _Abandoned.Value) || (_Changed.HasValue && _Changed.Value) || (_Moved.HasValue && _Moved.Value) || (_NoJson.HasValue && _NoJson.Value);
public void Update(Property property) => _Property = property;
}

View File

@ -1,10 +1,9 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class Location : Properties.ILocation, ILocation, IEquatable<Location> public class Location : Properties.ILocation, IEquatable<Location>
{ {
protected int _Bottom; protected int _Bottom;
@ -13,8 +12,8 @@ public class Location : Properties.ILocation, ILocation, IEquatable<Location>
protected readonly int? _NormalizedPixelPercentage; protected readonly int? _NormalizedPixelPercentage;
protected int _Right; protected int _Right;
protected int _Top; protected int _Top;
public int Bottom => _Bottom;
public double Confidence => _Confidence; public double Confidence => _Confidence;
public int Bottom => _Bottom;
public int Left => _Left; public int Left => _Left;
public int? NormalizedPixelPercentage => _NormalizedPixelPercentage; public int? NormalizedPixelPercentage => _NormalizedPixelPercentage;
public int Right => _Right; public int Right => _Right;
@ -23,27 +22,22 @@ public class Location : Properties.ILocation, ILocation, IEquatable<Location>
[JsonConstructor] [JsonConstructor]
public Location(int bottom, double confidence, int left, int? normalizedPixelPercentage, int right, int top) public Location(int bottom, double confidence, int left, int? normalizedPixelPercentage, int right, int top)
{ {
if (normalizedPixelPercentage < 0)
normalizedPixelPercentage = 3;
_Confidence = confidence; _Confidence = confidence;
_Bottom = bottom; _Bottom = bottom;
_Left = left; _Left = left;
_NormalizedPixelPercentage = normalizedPixelPercentage; _NormalizedPixelPercentage = normalizedPixelPercentage;
_Right = right; _Right = right;
_Top = top; _Top = top;
Check(bottom, left, normalizedPixelPercentage, right, top, zCount: 1);
} }
public Location(double confidence, int bottom, int left, int right, int top, int width, int height) : public Location(double confidence, int height, Location location, int width, int zCount) :
this(bottom, confidence, left, GetNormalizedPixelPercentage(bottom, height, left, right, top, width), right, top) this(location.Bottom, confidence, location.Left, GetNormalizedPixelPercentage(location.Bottom, height, location.Left, location.Right, location.Top, width, zCount), location.Right, location.Top) =>
{ } Check(_Bottom, _Left, _NormalizedPixelPercentage, _Right, _Top, zCount);
public Location(double confidence, Location location, int width, int height) : public Location(int bottom, double confidence, int height, int left, int right, int top, int width, int zCount) :
this(location.Bottom, confidence, location.Left, GetNormalizedPixelPercentage(location.Bottom, height, location.Left, location.Right, location.Top, width), location.Right, location.Top) this(bottom, confidence, left, GetNormalizedPixelPercentage(bottom, height, left, right, top, width, zCount), right, top) =>
{ } Check(_Bottom, height, _Left, _NormalizedPixelPercentage, _Right, _Top, width, zCount);
public Location(int left, int top, int right, int bottom, int width, int height) :
this(bottom, -1.0d, left, GetNormalizedPixelPercentage(bottom, height, left, right, top, width), right, top)
{ }
public override bool Equals(object? obj) => Equals(obj as Location); public override bool Equals(object? obj) => Equals(obj as Location);
@ -53,6 +47,53 @@ public class Location : Properties.ILocation, ILocation, IEquatable<Location>
return result; return result;
} }
private static void Check(int bottom, int left, int right, int top, int zCount)
{
if (left < 0)
throw new Exception();
if (right < 0)
throw new Exception();
if (right < left)
throw new Exception();
if (top < 0)
throw new Exception();
if (bottom < 0)
throw new Exception();
if (bottom < top)
throw new Exception();
if (zCount < 0)
throw new Exception();
}
private static void Check(int bottom, int height, int left, int right, int top, int width, int zCount)
{
if (bottom > height)
throw new Exception();
if (left > width)
throw new Exception();
if (right > width)
throw new Exception();
if (top > height)
throw new Exception();
if (zCount < 0)
throw new Exception();
}
private static void Check(int bottom, int left, int? normalizedPixelPercentage, int right, int top, int zCount)
{
Check(bottom, left, right, top, zCount);
if (normalizedPixelPercentage.HasValue && normalizedPixelPercentage.Value < 0)
throw new Exception();
}
private static void Check(int bottom, int height, int left, int? normalizedPixelPercentage, int right, int top, int width, int zCount)
{
Check(bottom, left, right, top, zCount);
Check(bottom, height, left, right, top, width, zCount);
if (normalizedPixelPercentage.HasValue && normalizedPixelPercentage.Value < 0)
throw new Exception();
}
public override int GetHashCode() public override int GetHashCode()
{ {
int hashCode = -773114317; int hashCode = -773114317;
@ -63,16 +104,21 @@ public class Location : Properties.ILocation, ILocation, IEquatable<Location>
return hashCode; return hashCode;
} }
public static int GetNormalizedPixelPercentage(int bottom, int height, int left, int right, int top, int width) public static int GetNormalizedPixelPercentage(int bottom, int height, int left, int right, int top, int width, int zCount)
{ {
int result; int result;
double value; double value;
int decimals = 6;
int factor = 1000000;
double total = width * height;
Check(bottom, left, right, top, zCount);
double xCenter = left + ((right - left) / 2); double xCenter = left + ((right - left) / 2);
double yCenter = top + ((bottom - top) / 2); double yCenter = top + ((bottom - top) / 2);
value = ((yCenter * width) + xCenter) / (width * height); double at = ((yCenter - 1) * width) + xCenter;
value = at / total;
if (value < 0) if (value < 0)
value = 3; value = 3;
result = (int)(Math.Round((decimal)value, 4) * Stateless.Methods.ILocation.Factor); result = (int)(Math.Round(value, decimals) * factor);
return result; return result;
} }

View File

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

View File

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

View File

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

View File

@ -1,8 +1,6 @@
namespace View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Shared.Models.Methods;
public interface IFaceFileSystem : Stateless.Methods.IFaceFileSystem, IFileSystem public interface IFaceFileSystem : Stateless.Methods.IFaceFileSystem
{ {
string GetSize();
} }

View File

@ -1,6 +1,6 @@
namespace View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Shared.Models.Methods;
public interface IFacePoint public interface IFacePoint : Stateless.Methods.IFacePoint
{ {
} }

View File

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

View File

@ -3,6 +3,4 @@ namespace View_by_Distance.Shared.Models.Methods;
public interface IFileSystem : Stateless.Methods.IFileSystem public interface IFileSystem : Stateless.Methods.IFileSystem
{ {
string GetDate();
} }

View File

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

View File

@ -1,6 +1,6 @@
namespace View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Shared.Models.Methods;
public interface ILocation public interface ILocation : Stateless.Methods.ILocation
{ {
} }

View File

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

View File

@ -1,6 +1,6 @@
namespace View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Shared.Models.Methods;
public interface IOutputResolution public interface IOutputResolution : Stateless.Methods.IPerson
{ {
} }

View File

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

View File

@ -1,6 +1,6 @@
namespace View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Shared.Models.Methods;
public interface IProperty public interface IProperty : Stateless.Methods.IProperty
{ {
} }

View File

@ -1,6 +1,6 @@
namespace View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Shared.Models.Methods;
public interface IRelativePaths public interface IRelativePaths : Stateless.Methods.IRelativePaths
{ {
} }

37
Shared/Models/Named.cs Normal file
View File

@ -0,0 +1,37 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public class Named : Properties.INamed
{
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)
{ }
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -1,10 +1,9 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class OutputResolution : Properties.IOutputResolution, IOutputResolution public class OutputResolution : Properties.IOutputResolution
{ {
protected int _Height; protected int _Height;

View File

@ -0,0 +1,13 @@
namespace View_by_Distance.Shared.Models.Properties;
public interface IClosest
{
public double? Average { get; }
public int? NormalizedPixelPercentage { get; }
public bool? IsWrongYear { get; }
public double? Minimum { get; }
public DateTime MinimumDateTime { get; }
public PersonBirthday? PersonBirthday { get; }
}

View File

@ -1,45 +0,0 @@
// using View_by_Distance.Shared.Models.Methods;
// namespace View_by_Distance.Shared.Models.Properties;
// public interface IConfiguration
// {
// public bool? checkJsonForDistanceResults;
// public string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions;
// public string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions;
// public bool? loadOrCreateThenSaveIndex;
// public bool? overrideForFaceImages;
// public bool? overrideForFaceLandmarkImages;
// public bool? overrideForResizeImages;
// public bool? propertiesChangedForDistance;
// public bool? propertiesChangedForFaces;
// public bool? propertiesChangedForIndex;
// public bool? propertiesChangedForMetadata;
// public bool? propertiesChangedForProperty;
// public bool? propertiesChangedForResize;
// public bool? reverse;
// public bool? saveFullYearOfRandomFiles;
// public bool? testDistanceResults;
// public int? distanceFactor;
// public int? locationConfidenceFactor;
// public int? mappedMaxIndex;
// public int? maxImagesInDirectoryForTopLevelFirstPass;
// public int? maxItemsInDistanceCollection;
// public int? numberOfJitters;
// public int? outputQuality;
// public int? paddingLoops;
// public string dateGroup;
// public string modelDirectory;
// public string modelName;
// public string outputExtension;
// public string predictorModelName;
// public string rootDirectory;
// public string[] ignoreExtensions;
// public string[] ignoreRelativePaths;
// public string[] mixedYearRelativePaths;
// public string[] outputResolutions;
// public string[] saveFaceLandmarkForOutputResolutions;
// public string[] validResolutions;
// }

View File

@ -0,0 +1,11 @@
namespace View_by_Distance.Shared.Models.Properties;
public interface IContainer
{
public int G { get; }
public List<Item> Items { get; }
public int R { get; }
public string SourceDirectory { get; }
}

View File

@ -3,10 +3,4 @@ namespace View_by_Distance.Shared.Models.Properties;
public interface IDirectoryFileSystem public interface IDirectoryFileSystem
{ {
// protected new string ClassName { get; }
// protected new string DataDisplayFileName { get; }
// protected new string DataFullFileName { get; }
// protected new string Display { get; }
// protected new DateTime LastModified { get; }
} }

View File

@ -0,0 +1,14 @@
namespace View_by_Distance.Shared.Models.Properties;
public interface IDistanceHolder
{
public Face Face { init; get; }
public FileHolder FileHolder { init; get; }
public int Id { init; get; }
public string JSONDirectory { init; get; }
public Location? Location { init; get; }
public string TSVDirectory { init; get; }
public double Sort { get; set; }
}

View File

@ -3,16 +3,12 @@ namespace View_by_Distance.Shared.Models.Properties;
public interface IFace public interface IFace
{ {
#pragma warning disable IDE1006
public double? α { get; }
#pragma warning restore IDE1006
public DateTime DateTime { get; } public DateTime DateTime { get; }
public FaceEncoding FaceEncoding { get; } public FaceEncoding? FaceEncoding { get; }
public Dictionary<string, FacePoint[]> FaceLandmarks { get; } public Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts { get; }
public Location Location { get; } public Location? Location { get; }
public int? LocationIndex { get; } public int? LocationIndex { get; }
public OutputResolution OutputResolution { get; } public OutputResolution? OutputResolution { get; }
public bool Populated { get; }
public string RelativePath { get; } public string RelativePath { get; }
} }

View File

@ -0,0 +1,16 @@
namespace View_by_Distance.Shared.Models.Properties;
public interface IFileHolder
{
public DateTime CreationTime { get; }
public string? DirectoryName { get; }
public bool Exists { get; }
public string ExtensionLowered { get; }
public string FullName { get; }
public DateTime LastWriteTime { get; }
public long? Length { get; }
public string Name { get; }
public string NameWithoutExtension { get; }
}

View File

@ -0,0 +1,20 @@
namespace View_by_Distance.Shared.Models.Properties;
public interface IItem
{
public bool? Abandoned { get; }
public bool? Changed { get; }
public List<Closest> Closest { get; }
public List<Face> Faces { get; }
public FileHolder? ImageFileHolder { get; }
public bool? Moved { get; }
public bool? NoJson { get; }
public List<Named> Named { get; }
public Property? Property { get; }
public string RelativePath { get; }
public FileHolder? ResizedFileHolder { get; }
public string SourceDirectoryFile { get; }
public bool ValidImageFormatExtension { get; }
}

View File

@ -0,0 +1,11 @@
namespace View_by_Distance.Shared.Models.Properties;
public interface INamed
{
public bool? IsWrongYear { get; }
public DateTime MinimumDateTime { get; }
public int? NormalizedPixelPercentage { get; }
public PersonBirthday? PersonBirthday { get; }
}

View File

@ -0,0 +1,6 @@
namespace View_by_Distance.Shared.Models.Properties;
public interface IPath
{
}

View File

@ -6,61 +6,52 @@ namespace View_by_Distance.Shared.Models;
public class Property : Properties.IProperty public class Property : Properties.IProperty
{ {
protected bool? _WrongYear;
protected DateTime _CreationTime; protected DateTime _CreationTime;
protected DateTime _LastWriteTime;
protected DateTime? _DateTime; protected DateTime? _DateTime;
protected DateTime? _DateTimeDigitized; protected DateTime? _DateTimeDigitized;
protected DateTime? _DateTimeOriginal; protected DateTime? _DateTimeOriginal;
protected long _FileSize; protected long _FileSize;
protected DateTime? _GPSDateStamp; protected DateTime? _GPSDateStamp;
protected int? _Height;
protected int? _Id; protected int? _Id;
protected int[] _Indices; protected int[] _Indices;
protected int? _Height; protected DateTime _LastWriteTime;
protected int? _Width;
protected string _Make; protected string _Make;
protected int? _MetadataGroups;
protected string _Model; protected string _Model;
protected string _Orientation; protected string _Orientation;
protected string _UniqueImageId; protected int? _Width;
public bool? WrongYear => _WrongYear;
public DateTime CreationTime => _CreationTime; public DateTime CreationTime => _CreationTime;
public DateTime LastWriteTime => _LastWriteTime;
public DateTime? DateTime => _DateTime; public DateTime? DateTime => _DateTime;
public DateTime? DateTimeDigitized => _DateTimeDigitized; public DateTime? DateTimeDigitized => _DateTimeDigitized;
public DateTime? DateTimeOriginal => _DateTimeOriginal; public DateTime? DateTimeOriginal => _DateTimeOriginal;
public long FileSize => _FileSize; public long FileSize => _FileSize;
public DateTime? GPSDateStamp => _GPSDateStamp; public DateTime? GPSDateStamp => _GPSDateStamp;
public int? Height => _Height;
public int? Id => _Id; public int? Id => _Id;
public int[] Indices => _Indices; public int[] Indices => _Indices;
public int? Height => _Height; public DateTime LastWriteTime => _LastWriteTime;
public int? Width => _Width;
public string Make => _Make; public string Make => _Make;
public int? MetadataGroups => _MetadataGroups;
public string Model => _Model; public string Model => _Model;
public string Orientation => _Orientation; public string Orientation => _Orientation;
public string UniqueImageId => _UniqueImageId; public int? Width => _Width;
[JsonConstructor] [JsonConstructor]
public Property(bool? wrongYear, DateTime creationTime, DateTime lastWriteTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeOriginal, DateTime? gpsDateStamp, long fileSize, int? id, int[] indices, int? height, int? width, string make, int? metadataGroups, string model, string orientation, string uniqueImageId) public 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; _CreationTime = creationTime;
_DateTime = dateTime; _DateTime = dateTime;
_DateTimeDigitized = dateTimeDigitized; _DateTimeDigitized = dateTimeDigitized;
_DateTimeOriginal = dateTimeOriginal; _DateTimeOriginal = dateTimeOriginal;
_GPSDateStamp = gpsDateStamp;
_FileSize = fileSize; _FileSize = fileSize;
_GPSDateStamp = gpsDateStamp;
_Height = height; _Height = height;
_Id = id; _Id = id;
_Indices = indices; _Indices = indices;
_LastWriteTime = lastWriteTime; _LastWriteTime = lastWriteTime;
_Make = make; _Make = make;
_MetadataGroups = metadataGroups;
_Model = model; _Model = model;
_Orientation = orientation; _Orientation = orientation;
_Width = width; _Width = width;
_WrongYear = wrongYear;
_UniqueImageId = uniqueImageId;
} }
public override string ToString() public override string ToString()
@ -69,4 +60,38 @@ public class Property : Properties.IProperty
return result; return result;
} // ... } // ...
public List<DateTime> GetDateTimes() => Stateless.Methods.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.GetFullPath(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.Methods.Property.IsWrongYear(directorySegments, year);
if (result.HasValue)
break;
}
return new(result, results);
}
} }

View File

@ -1,10 +1,9 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class RelativePaths : Properties.IRelativePaths, IRelativePaths public class RelativePaths : Properties.IRelativePaths
{ {
protected string _Value; protected string _Value;

View File

@ -0,0 +1,8 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class Closest
{
internal static Models.Closest[] Get(List<Models.Closest> collection) => (from l in collection orderby l.Minimum < IClosest.MinimumMinimum, l.Average select l).ToArray();
}

View File

@ -0,0 +1,8 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class Container
{
internal static double GetDefaultValue() => throw new Exception();
}

View File

@ -0,0 +1,8 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class DistanceHolder
{
internal static double GetDefaultValue() => throw new Exception();
}

Some files were not shown because too many files have changed in this diff Show More