Mostly Sorting
Video Merge as 4, 5, and 6
This commit is contained in:
parent
d5fa108f81
commit
130e3b6528
14
.vscode/tasks.json
vendored
14
.vscode/tasks.json
vendored
@ -99,6 +99,20 @@
|
|||||||
"/consoleloggerparameters:NoSummary"
|
"/consoleloggerparameters:NoSummary"
|
||||||
],
|
],
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "File-Folder-Helper AOT s X Day-Helper-2025-03-20",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe",
|
||||||
|
"args": [
|
||||||
|
"s",
|
||||||
|
"X",
|
||||||
|
"L:/Git/View-by-Distance-MKLink-Console",
|
||||||
|
"Day-Helper-2025-03-20",
|
||||||
|
"false",
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"problemMatcher": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -242,6 +242,53 @@ public class Compare
|
|||||||
_ = Directory.CreateDirectory(currentYearDirectory);
|
_ = Directory.CreateDirectory(currentYearDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void Verify(Models.Configuration configuration)
|
||||||
|
{
|
||||||
|
if (configuration.Spelling is null || !configuration.Spelling.Any())
|
||||||
|
throw new NullReferenceException(nameof(configuration.Spelling));
|
||||||
|
}
|
||||||
|
|
||||||
|
private A_Property GetPropertyLogic(bool reverse, string outputExtension, Map.Models.MapLogic mapLogic)
|
||||||
|
{
|
||||||
|
A_Property result;
|
||||||
|
if (_Configuration?.PropertyConfiguration is null)
|
||||||
|
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
|
||||||
|
result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, outputExtension, reverse);
|
||||||
|
string fromPrepareForOld = "34720-637858334555170379.tsv";
|
||||||
|
string fromPrepareForOldFile = Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, fromPrepareForOld);
|
||||||
|
if (File.Exists(fromPrepareForOldFile))
|
||||||
|
{
|
||||||
|
string[] lines;
|
||||||
|
string[] columns;
|
||||||
|
List<string> debug = new();
|
||||||
|
long ticks = DateTime.Now.Ticks;
|
||||||
|
lines = File.ReadAllLines(fromPrepareForOldFile);
|
||||||
|
string resultsDirectory = $"{_Configuration.PropertyConfiguration.RootDirectory}-Results";
|
||||||
|
int[]? zeros = (from l in mapLogic.IndicesFromNew where l.Value.Any() select l.Value[0]).ToArray();
|
||||||
|
lines = (from l in mapLogic.IndicesFromNew select string.Concat(l.Key, '\t', string.Join('\t', l.Value))).ToArray();
|
||||||
|
if (!Directory.Exists(resultsDirectory))
|
||||||
|
_ = Directory.CreateDirectory(resultsDirectory);
|
||||||
|
File.WriteAllLines(Path.Combine(resultsDirectory, $"{ticks}.tsv"), lines);
|
||||||
|
string json = JsonSerializer.Serialize(mapLogic.IndicesFromNew, new JsonSerializerOptions { WriteIndented = true });
|
||||||
|
File.WriteAllText(Path.Combine(resultsDirectory, $"{ticks}.json"), json);
|
||||||
|
foreach (string line in lines)
|
||||||
|
{
|
||||||
|
columns = line.Split('\t');
|
||||||
|
// select $"{l.Index}\t{l.PropertyId}\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t{l.PropertyTicks}\t{l.RelativeDirectory}\t{l.FileName}"
|
||||||
|
if (columns.Length != 7)
|
||||||
|
continue;
|
||||||
|
if (!int.TryParse(columns[1], out int propertyId))
|
||||||
|
continue;
|
||||||
|
if (!zeros.Contains(propertyId))
|
||||||
|
debug.Add(line);
|
||||||
|
else
|
||||||
|
debug.Add(propertyId.ToString());
|
||||||
|
}
|
||||||
|
File.WriteAllLines(Path.Combine(resultsDirectory, $"{ticks}-{fromPrepareForOld}"), debug);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private string GetRename(string renameA)
|
private string GetRename(string renameA)
|
||||||
{
|
{
|
||||||
string result;
|
string result;
|
||||||
@ -376,12 +423,6 @@ public class Compare
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Verify(Models.Configuration configuration)
|
|
||||||
{
|
|
||||||
if (configuration.Spelling is null || !configuration.Spelling.Any())
|
|
||||||
throw new NullReferenceException(nameof(configuration.Spelling));
|
|
||||||
}
|
|
||||||
|
|
||||||
private long LogDelta(long ticks, string? methodName)
|
private long LogDelta(long ticks, string? methodName)
|
||||||
{
|
{
|
||||||
long result;
|
long result;
|
||||||
@ -391,121 +432,6 @@ public class Compare
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private A_Property GetPropertyLogic(bool reverse, string outputExtension, Map.Models.MapLogic mapLogic)
|
|
||||||
{
|
|
||||||
A_Property result;
|
|
||||||
if (_Configuration?.PropertyConfiguration is null)
|
|
||||||
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
|
|
||||||
result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, outputExtension, reverse);
|
|
||||||
string fromPrepareForOld = "34720-637858334555170379.tsv";
|
|
||||||
string fromPrepareForOldFile = Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, fromPrepareForOld);
|
|
||||||
if (File.Exists(fromPrepareForOldFile))
|
|
||||||
{
|
|
||||||
string[] lines;
|
|
||||||
string[] columns;
|
|
||||||
List<string> debug = new();
|
|
||||||
long ticks = DateTime.Now.Ticks;
|
|
||||||
lines = File.ReadAllLines(fromPrepareForOldFile);
|
|
||||||
string resultsDirectory = $"{_Configuration.PropertyConfiguration.RootDirectory}-Results";
|
|
||||||
int[]? zeros = (from l in mapLogic.IndicesFromNew where l.Value.Any() select l.Value[0]).ToArray();
|
|
||||||
lines = (from l in mapLogic.IndicesFromNew select string.Concat(l.Key, '\t', string.Join('\t', l.Value))).ToArray();
|
|
||||||
if (!Directory.Exists(resultsDirectory))
|
|
||||||
_ = Directory.CreateDirectory(resultsDirectory);
|
|
||||||
File.WriteAllLines(Path.Combine(resultsDirectory, $"{ticks}.tsv"), lines);
|
|
||||||
string json = JsonSerializer.Serialize(mapLogic.IndicesFromNew, new JsonSerializerOptions { WriteIndented = true });
|
|
||||||
File.WriteAllText(Path.Combine(resultsDirectory, $"{ticks}.json"), json);
|
|
||||||
foreach (string line in lines)
|
|
||||||
{
|
|
||||||
columns = line.Split('\t');
|
|
||||||
// select $"{l.Index}\t{l.PropertyId}\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t{l.PropertyTicks}\t{l.RelativeDirectory}\t{l.FileName}"
|
|
||||||
if (columns.Length != 7)
|
|
||||||
continue;
|
|
||||||
if (!int.TryParse(columns[1], out int propertyId))
|
|
||||||
continue;
|
|
||||||
if (!zeros.Contains(propertyId))
|
|
||||||
debug.Add(line);
|
|
||||||
else
|
|
||||||
debug.Add(propertyId.ToString());
|
|
||||||
}
|
|
||||||
File.WriteAllLines(Path.Combine(resultsDirectory, $"{ticks}-{fromPrepareForOld}"), debug);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveDiffFilesOrSaveLogAndMoveFiles(Property.Models.Configuration configuration)
|
|
||||||
{
|
|
||||||
if (_Configuration?.PropertyConfiguration is null)
|
|
||||||
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
|
|
||||||
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
|
|
||||||
_Logger?.LogInformation(aPropertySingletonDirectory);
|
|
||||||
_Logger?.LogInformation("to");
|
|
||||||
_Logger?.LogInformation(_Configuration.DiffPropertyDirectory);
|
|
||||||
for (int y = 0; y < int.MaxValue; y++)
|
|
||||||
{
|
|
||||||
_Logger?.LogInformation("Press \"Y\" key to continue or close console if compare not needed");
|
|
||||||
if (Console.ReadKey().Key == ConsoleKey.Y)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_Logger?.LogInformation(". . .");
|
|
||||||
int loadLessThan = 7;
|
|
||||||
string diffRootDirectory;
|
|
||||||
ConsoleKey? consoleKey = null;
|
|
||||||
List<PropertyCompare.Models.PropertyCompare>? duplicates = null;
|
|
||||||
PropertyCompare.Models.PropertyCompare[] diffPropertyCompareCollection;
|
|
||||||
if (string.IsNullOrEmpty(_Configuration.DiffPropertyDirectory))
|
|
||||||
diffRootDirectory = string.Empty;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!_Configuration.DiffPropertyDirectory.EndsWith("{}"))
|
|
||||||
throw new Exception("Invalid directory should end with {}!");
|
|
||||||
diffRootDirectory = Shared.Models.Stateless.Methods.IProperty.GetDiffRootDirectory(_Configuration.DiffPropertyDirectory);
|
|
||||||
}
|
|
||||||
PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory);
|
|
||||||
if (string.IsNullOrEmpty(_Configuration.DiffPropertyDirectory) || !Directory.Exists(_Configuration.DiffPropertyDirectory))
|
|
||||||
diffPropertyCompareCollection = Array.Empty<PropertyCompare.Models.PropertyCompare>();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
diffPropertyCompareCollection = propertyCompareLogic.Get(_Configuration.DiffPropertyDirectory, loadLessThan, duplicates, deleteExtension: false);
|
|
||||||
if (!diffPropertyCompareCollection.Any())
|
|
||||||
throw new Exception("Invalid directory!");
|
|
||||||
}
|
|
||||||
string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "[{}]");
|
|
||||||
PropertyCompare.Models.PropertyCompare[] propertyCompareCollection = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan, duplicates, deleteExtension: false);
|
|
||||||
{
|
|
||||||
long ticks = DateTime.Now.Ticks;
|
|
||||||
string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray();
|
|
||||||
File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines);
|
|
||||||
string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true });
|
|
||||||
File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json);
|
|
||||||
}
|
|
||||||
for (int x = 0; x < int.MaxValue; x++)
|
|
||||||
{
|
|
||||||
_Logger?.LogInformation($"Press \"D\" key to {nameof(PropertyCompare.Models.PropertyCompareLogic.SaveDiffFiles)}");
|
|
||||||
_Logger?.LogInformation($"Press \"M\" key to {nameof(PropertyCompare.Models.PropertyCompareLogic.SaveLogAndMoveFiles)}");
|
|
||||||
_Logger?.LogInformation("Press \"End\" key when ready to skip");
|
|
||||||
consoleKey = Console.ReadKey().Key;
|
|
||||||
if (consoleKey is ConsoleKey.D or ConsoleKey.M or ConsoleKey.End)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_Logger?.LogInformation(". . .");
|
|
||||||
if (consoleKey.HasValue && consoleKey.Value == ConsoleKey.D)
|
|
||||||
propertyCompareLogic.SaveDiffFiles(aPropertyCollectionDirectory, loadLessThan, propertyCompareCollection, diffPropertyCompareCollection);
|
|
||||||
else if (consoleKey.HasValue && consoleKey.Value == ConsoleKey.M)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < int.MaxValue; x++)
|
|
||||||
{
|
|
||||||
_Logger?.LogInformation($"Press \"0 - {loadLessThan}\" key when ready to continue");
|
|
||||||
_Logger?.LogInformation("Press \"End\" key when ready to skip");
|
|
||||||
consoleKey = Console.ReadKey().Key;
|
|
||||||
if (consoleKey.Value is ConsoleKey.D0 or ConsoleKey.D1 or ConsoleKey.D2 or ConsoleKey.D3 or ConsoleKey.D4 or ConsoleKey.D5 or ConsoleKey.D6 or ConsoleKey.End)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_Logger?.LogInformation(". . .");
|
|
||||||
int i = int.Parse(consoleKey.Value.ToString()[1..]);
|
|
||||||
propertyCompareLogic.SaveLogAndMoveFiles(aPropertyCollectionDirectory, loadLessThan, propertyCompareCollection, diffPropertyCompareCollection, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ChangeExtensionFromDeleteToJson(string aPropertySingletonDirectory)
|
private void ChangeExtensionFromDeleteToJson(string aPropertySingletonDirectory)
|
||||||
{
|
{
|
||||||
string searchPattern = "*.delete";
|
string searchPattern = "*.delete";
|
||||||
@ -524,227 +450,6 @@ public class Compare
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool PossiblyRename(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
string replaceFile;
|
|
||||||
string replaceDirectory;
|
|
||||||
int remainingDirectories = 0;
|
|
||||||
IEnumerable<(string Find, string Replace)>? found;
|
|
||||||
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in groupCollection)
|
|
||||||
{
|
|
||||||
if (!topDirectories.Any())
|
|
||||||
continue;
|
|
||||||
found = from l in _RenameFindReplace where sourceDirectory == l.Find select l;
|
|
||||||
if (!found.Any())
|
|
||||||
continue;
|
|
||||||
if (!result)
|
|
||||||
result = true;
|
|
||||||
replaceDirectory = found.First().Replace;
|
|
||||||
if (!Directory.Exists(replaceDirectory))
|
|
||||||
Directory.Move(sourceDirectory, replaceDirectory);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Directory.EnumerateDirectories(sourceDirectory).Any())
|
|
||||||
remainingDirectories += 1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
|
|
||||||
{
|
|
||||||
replaceFile = Path.Combine(replaceDirectory, Path.GetFileName(sourceDirectoryFile));
|
|
||||||
if (File.Exists(replaceFile))
|
|
||||||
{
|
|
||||||
if (replaceFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
|
|
||||||
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpeg"));
|
|
||||||
else if (replaceFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
|
|
||||||
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpg"));
|
|
||||||
}
|
|
||||||
if (File.Exists(replaceFile))
|
|
||||||
continue;
|
|
||||||
File.Move(sourceDirectoryFile, replaceFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool PossiblyRenameB(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
string replaceFile;
|
|
||||||
string replaceDirectory;
|
|
||||||
IEnumerable<(string Find, string Replace)>? found;
|
|
||||||
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in groupCollection)
|
|
||||||
{
|
|
||||||
if (!topDirectories.Any())
|
|
||||||
continue;
|
|
||||||
found = from l in _RenameBFindReplace where sourceDirectory == l.Find select l;
|
|
||||||
if (!found.Any())
|
|
||||||
continue;
|
|
||||||
if (!result)
|
|
||||||
result = true;
|
|
||||||
replaceDirectory = found.First().Replace;
|
|
||||||
if (!Directory.Exists(replaceDirectory))
|
|
||||||
_ = Directory.CreateDirectory(replaceDirectory);
|
|
||||||
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
|
|
||||||
{
|
|
||||||
replaceFile = Path.Combine(replaceDirectory, Path.GetFileName(sourceDirectoryFile));
|
|
||||||
if (File.Exists(replaceFile))
|
|
||||||
{
|
|
||||||
if (replaceFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
|
|
||||||
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpeg"));
|
|
||||||
else if (replaceFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
|
|
||||||
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpg"));
|
|
||||||
}
|
|
||||||
if (File.Exists(replaceFile))
|
|
||||||
continue;
|
|
||||||
File.Move(sourceDirectoryFile, replaceFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool PossiblyRenameC(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
string replaceFile;
|
|
||||||
string replaceDirectory;
|
|
||||||
IEnumerable<(string Find, string Replace)>? found;
|
|
||||||
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in groupCollection)
|
|
||||||
{
|
|
||||||
if (!topDirectories.Any())
|
|
||||||
continue;
|
|
||||||
found = from l in _RenameCFindReplace where sourceDirectory == l.Find select l;
|
|
||||||
if (!found.Any())
|
|
||||||
continue;
|
|
||||||
if (!result)
|
|
||||||
result = true;
|
|
||||||
replaceDirectory = found.First().Replace;
|
|
||||||
if (!Directory.Exists(replaceDirectory))
|
|
||||||
_ = Directory.CreateDirectory(replaceDirectory);
|
|
||||||
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
|
|
||||||
{
|
|
||||||
replaceFile = Path.Combine(replaceDirectory, Path.GetFileName(sourceDirectoryFile));
|
|
||||||
if (File.Exists(replaceFile))
|
|
||||||
{
|
|
||||||
if (replaceFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
|
|
||||||
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpeg"));
|
|
||||||
else if (replaceFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
|
|
||||||
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpg"));
|
|
||||||
}
|
|
||||||
if (File.Exists(replaceFile))
|
|
||||||
continue;
|
|
||||||
File.Move(sourceDirectoryFile, replaceFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool PossiblyCorrect(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection)
|
|
||||||
{
|
|
||||||
if (_Configuration?.PropertyConfiguration is null)
|
|
||||||
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
|
|
||||||
bool result = false;
|
|
||||||
string corrected;
|
|
||||||
string correctedMoveTo;
|
|
||||||
string? correctedDirectory;
|
|
||||||
string filteredSourceDirectoryFile;
|
|
||||||
string[] filteredSourceDirectoryFiles;
|
|
||||||
(string Find, string Replace) findReplace;
|
|
||||||
IEnumerable<(string Find, string Replace)>? found;
|
|
||||||
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in groupCollection)
|
|
||||||
{
|
|
||||||
if (!topDirectories.Any())
|
|
||||||
continue;
|
|
||||||
filteredSourceDirectoryFiles = (from l in sourceDirectoryFiles where !_Configuration.PropertyConfiguration.IgnoreExtensions.Contains(Path.GetExtension(l)) select l).ToArray();
|
|
||||||
if (!filteredSourceDirectoryFiles.Any())
|
|
||||||
continue;
|
|
||||||
for (int i = 0; i < filteredSourceDirectoryFiles.Length; i++)
|
|
||||||
{
|
|
||||||
found = null;
|
|
||||||
for (int z = 0; z < int.MaxValue; z++)
|
|
||||||
{
|
|
||||||
filteredSourceDirectoryFile = filteredSourceDirectoryFiles[i];
|
|
||||||
found = from l in _SpellingFindReplace where filteredSourceDirectoryFile.Contains(l.Find) select l;
|
|
||||||
if (!found.Any())
|
|
||||||
break;
|
|
||||||
findReplace = found.First();
|
|
||||||
corrected = filteredSourceDirectoryFile.Replace(findReplace.Find, findReplace.Replace);
|
|
||||||
correctedDirectory = Path.GetDirectoryName(corrected);
|
|
||||||
if (string.IsNullOrEmpty(correctedDirectory))
|
|
||||||
break;
|
|
||||||
correctedMoveTo = Path.Combine(correctedDirectory, Path.GetFileName(corrected));
|
|
||||||
if (File.Exists(correctedMoveTo))
|
|
||||||
break;
|
|
||||||
if (!Directory.Exists(correctedDirectory))
|
|
||||||
_ = Directory.CreateDirectory(correctedDirectory);
|
|
||||||
if (!result)
|
|
||||||
result = true;
|
|
||||||
File.Move(filteredSourceDirectoryFile, correctedMoveTo);
|
|
||||||
filteredSourceDirectoryFiles[i] = corrected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> GetMissingVerifyToSeasonCollection(List<string> _, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection)
|
|
||||||
{
|
|
||||||
if (_Configuration?.PropertyConfiguration is null)
|
|
||||||
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
|
|
||||||
List<string> results = new();
|
|
||||||
string check;
|
|
||||||
foreach ((int _, string sourceDirectory, string[] _) in groupCollection)
|
|
||||||
{
|
|
||||||
if (sourceDirectory == _Configuration.PropertyConfiguration.RootDirectory)
|
|
||||||
continue;
|
|
||||||
check = sourceDirectory[(_Configuration.PropertyConfiguration.RootDirectory.Length + 1)..];
|
|
||||||
if (check[0] is '=' || check.StartsWith("zzz ="))
|
|
||||||
{
|
|
||||||
if (!_Configuration.PropertyConfiguration.VerifyToSeason.Contains(check))
|
|
||||||
results.Add(check);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateWindowsShortcuts((long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] collection, bool keepAll)
|
|
||||||
{
|
|
||||||
int z = 0;
|
|
||||||
string fileName;
|
|
||||||
WindowsShortcut windowsShortcut;
|
|
||||||
foreach ((long ticks, string filteredSourceDirectoryFile, string propertyDirectory, int propertyId) in collection)
|
|
||||||
{
|
|
||||||
z += 1;
|
|
||||||
if (z % 1000 == 0)
|
|
||||||
_Log.Debug($"{z}) Loop {propertyDirectory}");
|
|
||||||
if (!keepAll)
|
|
||||||
{
|
|
||||||
fileName = Path.Combine(propertyDirectory, $"{propertyId}.lnk");
|
|
||||||
if (File.Exists(fileName))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fileName = string.Empty;
|
|
||||||
for (short c = 65; c < short.MaxValue; c++)
|
|
||||||
{
|
|
||||||
if (c > 95)
|
|
||||||
break;
|
|
||||||
fileName = Path.Combine(propertyDirectory, $"{(char)c}", $"{propertyId}.lnk");
|
|
||||||
if (File.Exists(fileName))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (string.IsNullOrEmpty(fileName))
|
|
||||||
continue;
|
|
||||||
windowsShortcut = new() { Path = filteredSourceDirectoryFile };
|
|
||||||
windowsShortcut.Save(fileName);
|
|
||||||
windowsShortcut.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThirdPassToMove(Property.Models.Configuration configuration, Map.Models.MapLogic mapLogic, A_Property propertyLogic, Shared.Models.Container[] containers, string aPropertyContentCollectionDirectory)
|
private void ThirdPassToMove(Property.Models.Configuration configuration, Map.Models.MapLogic mapLogic, A_Property propertyLogic, Shared.Models.Container[] containers, string aPropertyContentCollectionDirectory)
|
||||||
{
|
{
|
||||||
if (_Configuration?.PropertyConfiguration is null)
|
if (_Configuration?.PropertyConfiguration is null)
|
||||||
@ -865,4 +570,299 @@ public class Compare
|
|||||||
CreateWindowsShortcuts(collection, keepAll);
|
CreateWindowsShortcuts(collection, keepAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CreateWindowsShortcuts((long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] collection, bool keepAll)
|
||||||
|
{
|
||||||
|
int z = 0;
|
||||||
|
string fileName;
|
||||||
|
WindowsShortcut windowsShortcut;
|
||||||
|
foreach ((long ticks, string filteredSourceDirectoryFile, string propertyDirectory, int propertyId) in collection)
|
||||||
|
{
|
||||||
|
z += 1;
|
||||||
|
if (z % 1000 == 0)
|
||||||
|
_Log.Debug($"{z}) Loop {propertyDirectory}");
|
||||||
|
if (!keepAll)
|
||||||
|
{
|
||||||
|
fileName = Path.Combine(propertyDirectory, $"{propertyId}.lnk");
|
||||||
|
if (File.Exists(fileName))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileName = string.Empty;
|
||||||
|
for (short c = 65; c < short.MaxValue; c++)
|
||||||
|
{
|
||||||
|
if (c > 95)
|
||||||
|
break;
|
||||||
|
fileName = Path.Combine(propertyDirectory, $"{(char)c}", $"{propertyId}.lnk");
|
||||||
|
if (File.Exists(fileName))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(fileName))
|
||||||
|
continue;
|
||||||
|
windowsShortcut = new() { Path = filteredSourceDirectoryFile };
|
||||||
|
windowsShortcut.Save(fileName);
|
||||||
|
windowsShortcut.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveDiffFilesOrSaveLogAndMoveFiles(Property.Models.Configuration configuration)
|
||||||
|
{
|
||||||
|
if (_Configuration?.PropertyConfiguration is null)
|
||||||
|
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
|
||||||
|
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
|
||||||
|
_Logger?.LogInformation(aPropertySingletonDirectory);
|
||||||
|
_Logger?.LogInformation("to");
|
||||||
|
_Logger?.LogInformation(_Configuration.DiffPropertyDirectory);
|
||||||
|
for (int y = 0; y < int.MaxValue; y++)
|
||||||
|
{
|
||||||
|
_Logger?.LogInformation("Press \"Y\" key to continue or close console if compare not needed");
|
||||||
|
if (Console.ReadKey().Key == ConsoleKey.Y)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_Logger?.LogInformation(". . .");
|
||||||
|
int loadLessThan = 7;
|
||||||
|
string diffRootDirectory;
|
||||||
|
ConsoleKey? consoleKey = null;
|
||||||
|
List<PropertyCompare.Models.PropertyCompare>? duplicates = null;
|
||||||
|
PropertyCompare.Models.PropertyCompare[] diffPropertyCompareCollection;
|
||||||
|
if (string.IsNullOrEmpty(_Configuration.DiffPropertyDirectory))
|
||||||
|
diffRootDirectory = string.Empty;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!_Configuration.DiffPropertyDirectory.EndsWith("{}"))
|
||||||
|
throw new Exception("Invalid directory should end with {}!");
|
||||||
|
diffRootDirectory = Shared.Models.Stateless.Methods.IProperty.GetDiffRootDirectory(_Configuration.DiffPropertyDirectory);
|
||||||
|
}
|
||||||
|
PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory);
|
||||||
|
if (string.IsNullOrEmpty(_Configuration.DiffPropertyDirectory) || !Directory.Exists(_Configuration.DiffPropertyDirectory))
|
||||||
|
diffPropertyCompareCollection = Array.Empty<PropertyCompare.Models.PropertyCompare>();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diffPropertyCompareCollection = propertyCompareLogic.Get(_Configuration.DiffPropertyDirectory, loadLessThan, duplicates, deleteExtension: false);
|
||||||
|
if (!diffPropertyCompareCollection.Any())
|
||||||
|
throw new Exception("Invalid directory!");
|
||||||
|
}
|
||||||
|
string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "[{}]");
|
||||||
|
PropertyCompare.Models.PropertyCompare[] propertyCompareCollection = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan, duplicates, deleteExtension: false);
|
||||||
|
{
|
||||||
|
long ticks = DateTime.Now.Ticks;
|
||||||
|
string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray();
|
||||||
|
File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines);
|
||||||
|
string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true });
|
||||||
|
File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json);
|
||||||
|
}
|
||||||
|
for (int x = 0; x < int.MaxValue; x++)
|
||||||
|
{
|
||||||
|
_Logger?.LogInformation($"Press \"D\" key to {nameof(PropertyCompare.Models.PropertyCompareLogic.SaveDiffFiles)}");
|
||||||
|
_Logger?.LogInformation($"Press \"M\" key to {nameof(PropertyCompare.Models.PropertyCompareLogic.SaveLogAndMoveFiles)}");
|
||||||
|
_Logger?.LogInformation("Press \"End\" key when ready to skip");
|
||||||
|
consoleKey = Console.ReadKey().Key;
|
||||||
|
if (consoleKey is ConsoleKey.D or ConsoleKey.M or ConsoleKey.End)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_Logger?.LogInformation(". . .");
|
||||||
|
if (consoleKey.HasValue && consoleKey.Value == ConsoleKey.D)
|
||||||
|
propertyCompareLogic.SaveDiffFiles(aPropertyCollectionDirectory, loadLessThan, propertyCompareCollection, diffPropertyCompareCollection);
|
||||||
|
else if (consoleKey.HasValue && consoleKey.Value == ConsoleKey.M)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < int.MaxValue; x++)
|
||||||
|
{
|
||||||
|
_Logger?.LogInformation($"Press \"0 - {loadLessThan}\" key when ready to continue");
|
||||||
|
_Logger?.LogInformation("Press \"End\" key when ready to skip");
|
||||||
|
consoleKey = Console.ReadKey().Key;
|
||||||
|
if (consoleKey.Value is ConsoleKey.D0 or ConsoleKey.D1 or ConsoleKey.D2 or ConsoleKey.D3 or ConsoleKey.D4 or ConsoleKey.D5 or ConsoleKey.D6 or ConsoleKey.End)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_Logger?.LogInformation(". . .");
|
||||||
|
int i = int.Parse(consoleKey.Value.ToString()[1..]);
|
||||||
|
propertyCompareLogic.SaveLogAndMoveFiles(aPropertyCollectionDirectory, loadLessThan, propertyCompareCollection, diffPropertyCompareCollection, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool PossiblyRename(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
string replaceFile;
|
||||||
|
string replaceDirectory;
|
||||||
|
int remainingDirectories = 0;
|
||||||
|
IEnumerable<(string Find, string Replace)>? found;
|
||||||
|
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in groupCollection)
|
||||||
|
{
|
||||||
|
if (!topDirectories.Any())
|
||||||
|
continue;
|
||||||
|
found = from l in _RenameFindReplace where sourceDirectory == l.Find select l;
|
||||||
|
if (!found.Any())
|
||||||
|
continue;
|
||||||
|
if (!result)
|
||||||
|
result = true;
|
||||||
|
replaceDirectory = found.First().Replace;
|
||||||
|
if (!Directory.Exists(replaceDirectory))
|
||||||
|
Directory.Move(sourceDirectory, replaceDirectory);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Directory.EnumerateDirectories(sourceDirectory).Any())
|
||||||
|
remainingDirectories += 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
|
||||||
|
{
|
||||||
|
replaceFile = Path.Combine(replaceDirectory, Path.GetFileName(sourceDirectoryFile));
|
||||||
|
if (File.Exists(replaceFile))
|
||||||
|
{
|
||||||
|
if (replaceFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
|
||||||
|
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpeg"));
|
||||||
|
else if (replaceFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
|
||||||
|
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpg"));
|
||||||
|
}
|
||||||
|
if (File.Exists(replaceFile))
|
||||||
|
continue;
|
||||||
|
File.Move(sourceDirectoryFile, replaceFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool PossiblyCorrect(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection)
|
||||||
|
{
|
||||||
|
if (_Configuration?.PropertyConfiguration is null)
|
||||||
|
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
|
||||||
|
bool result = false;
|
||||||
|
string corrected;
|
||||||
|
string correctedMoveTo;
|
||||||
|
string? correctedDirectory;
|
||||||
|
string filteredSourceDirectoryFile;
|
||||||
|
string[] filteredSourceDirectoryFiles;
|
||||||
|
(string Find, string Replace) findReplace;
|
||||||
|
IEnumerable<(string Find, string Replace)>? found;
|
||||||
|
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in groupCollection)
|
||||||
|
{
|
||||||
|
if (!topDirectories.Any())
|
||||||
|
continue;
|
||||||
|
filteredSourceDirectoryFiles = (from l in sourceDirectoryFiles where !_Configuration.PropertyConfiguration.IgnoreExtensions.Contains(Path.GetExtension(l)) select l).ToArray();
|
||||||
|
if (!filteredSourceDirectoryFiles.Any())
|
||||||
|
continue;
|
||||||
|
for (int i = 0; i < filteredSourceDirectoryFiles.Length; i++)
|
||||||
|
{
|
||||||
|
found = null;
|
||||||
|
for (int z = 0; z < int.MaxValue; z++)
|
||||||
|
{
|
||||||
|
filteredSourceDirectoryFile = filteredSourceDirectoryFiles[i];
|
||||||
|
found = from l in _SpellingFindReplace where filteredSourceDirectoryFile.Contains(l.Find) select l;
|
||||||
|
if (!found.Any())
|
||||||
|
break;
|
||||||
|
findReplace = found.First();
|
||||||
|
corrected = filteredSourceDirectoryFile.Replace(findReplace.Find, findReplace.Replace);
|
||||||
|
correctedDirectory = Path.GetDirectoryName(corrected);
|
||||||
|
if (string.IsNullOrEmpty(correctedDirectory))
|
||||||
|
break;
|
||||||
|
correctedMoveTo = Path.Combine(correctedDirectory, Path.GetFileName(corrected));
|
||||||
|
if (File.Exists(correctedMoveTo))
|
||||||
|
break;
|
||||||
|
if (!Directory.Exists(correctedDirectory))
|
||||||
|
_ = Directory.CreateDirectory(correctedDirectory);
|
||||||
|
if (!result)
|
||||||
|
result = true;
|
||||||
|
File.Move(filteredSourceDirectoryFile, correctedMoveTo);
|
||||||
|
filteredSourceDirectoryFiles[i] = corrected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool PossiblyRenameB(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
string replaceFile;
|
||||||
|
string replaceDirectory;
|
||||||
|
IEnumerable<(string Find, string Replace)>? found;
|
||||||
|
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in groupCollection)
|
||||||
|
{
|
||||||
|
if (!topDirectories.Any())
|
||||||
|
continue;
|
||||||
|
found = from l in _RenameBFindReplace where sourceDirectory == l.Find select l;
|
||||||
|
if (!found.Any())
|
||||||
|
continue;
|
||||||
|
if (!result)
|
||||||
|
result = true;
|
||||||
|
replaceDirectory = found.First().Replace;
|
||||||
|
if (!Directory.Exists(replaceDirectory))
|
||||||
|
_ = Directory.CreateDirectory(replaceDirectory);
|
||||||
|
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
|
||||||
|
{
|
||||||
|
replaceFile = Path.Combine(replaceDirectory, Path.GetFileName(sourceDirectoryFile));
|
||||||
|
if (File.Exists(replaceFile))
|
||||||
|
{
|
||||||
|
if (replaceFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
|
||||||
|
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpeg"));
|
||||||
|
else if (replaceFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
|
||||||
|
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpg"));
|
||||||
|
}
|
||||||
|
if (File.Exists(replaceFile))
|
||||||
|
continue;
|
||||||
|
File.Move(sourceDirectoryFile, replaceFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool PossiblyRenameC(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
string replaceFile;
|
||||||
|
string replaceDirectory;
|
||||||
|
IEnumerable<(string Find, string Replace)>? found;
|
||||||
|
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in groupCollection)
|
||||||
|
{
|
||||||
|
if (!topDirectories.Any())
|
||||||
|
continue;
|
||||||
|
found = from l in _RenameCFindReplace where sourceDirectory == l.Find select l;
|
||||||
|
if (!found.Any())
|
||||||
|
continue;
|
||||||
|
if (!result)
|
||||||
|
result = true;
|
||||||
|
replaceDirectory = found.First().Replace;
|
||||||
|
if (!Directory.Exists(replaceDirectory))
|
||||||
|
_ = Directory.CreateDirectory(replaceDirectory);
|
||||||
|
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
|
||||||
|
{
|
||||||
|
replaceFile = Path.Combine(replaceDirectory, Path.GetFileName(sourceDirectoryFile));
|
||||||
|
if (File.Exists(replaceFile))
|
||||||
|
{
|
||||||
|
if (replaceFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
|
||||||
|
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpeg"));
|
||||||
|
else if (replaceFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
|
||||||
|
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpg"));
|
||||||
|
}
|
||||||
|
if (File.Exists(replaceFile))
|
||||||
|
continue;
|
||||||
|
File.Move(sourceDirectoryFile, replaceFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<string> GetMissingVerifyToSeasonCollection(List<string> _, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> groupCollection)
|
||||||
|
{
|
||||||
|
if (_Configuration?.PropertyConfiguration is null)
|
||||||
|
throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
|
||||||
|
List<string> results = new();
|
||||||
|
string check;
|
||||||
|
foreach ((int _, string sourceDirectory, string[] _) in groupCollection)
|
||||||
|
{
|
||||||
|
if (sourceDirectory == _Configuration.PropertyConfiguration.RootDirectory)
|
||||||
|
continue;
|
||||||
|
check = sourceDirectory[(_Configuration.PropertyConfiguration.RootDirectory.Length + 1)..];
|
||||||
|
if (check[0] is '=' || check.StartsWith("zzz ="))
|
||||||
|
{
|
||||||
|
if (!_Configuration.PropertyConfiguration.VerifyToSeason.Contains(check))
|
||||||
|
results.Add(check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -9,16 +9,10 @@ namespace View_by_Distance.Container.Models.Stateless.Methods;
|
|||||||
internal abstract class Container
|
internal abstract class Container
|
||||||
{
|
{
|
||||||
|
|
||||||
private record FilePair(bool IsUnique, List<string> Collection, FilePath FilePath, Item Item) { }
|
private record FilePair(bool IsUnique,
|
||||||
|
List<string> Collection,
|
||||||
internal static DateTime[] GetContainerDateTimes(ReadOnlyCollection<Item> items)
|
FilePath FilePath,
|
||||||
{
|
Item Item);
|
||||||
DateTime[] results;
|
|
||||||
long containerMinimumTicks = (from l in items select l.FilePath.LastWriteTicks).Min();
|
|
||||||
long containerMaximumTicks = (from l in items select l.FilePath.LastWriteTicks).Max();
|
|
||||||
results = [new(containerMinimumTicks), new(containerMaximumTicks)];
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container)
|
internal static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container)
|
||||||
{
|
{
|
||||||
@ -32,28 +26,140 @@ internal abstract class Container
|
|||||||
return container.Items.Count == results.Count ? container.Items : results.AsReadOnly();
|
return container.Items.Count == results.Count ? container.Items : results.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
|
internal static DateTime[] GetContainerDateTimes(ReadOnlyCollection<Item> items)
|
||||||
{
|
{
|
||||||
Dictionary<string, List<string>> results = [];
|
DateTime[] results;
|
||||||
List<string>? collection;
|
long containerMinimumTicks = (from l in items select l.FilePath.LastWriteTicks).Min();
|
||||||
string fileNameWithoutExtensionMinusOne;
|
long containerMaximumTicks = (from l in items select l.FilePath.LastWriteTicks).Max();
|
||||||
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
|
results = [new(containerMinimumTicks), new(containerMaximumTicks)];
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<int> GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers)
|
||||||
|
{
|
||||||
|
List<int> results = [];
|
||||||
|
ReadOnlyCollection<Item> filteredItems;
|
||||||
|
foreach (Models.Container container in readOnlyContainers)
|
||||||
{
|
{
|
||||||
foreach (FilePath filePath in filePaths)
|
if (container.Items.Count == 0)
|
||||||
|
continue;
|
||||||
|
filteredItems = GetValidImageItems(propertyConfiguration, container);
|
||||||
|
if (filteredItems.Count == 0)
|
||||||
|
continue;
|
||||||
|
foreach (Item item in filteredItems)
|
||||||
{
|
{
|
||||||
fileNameWithoutExtensionMinusOne = filePath.NameWithoutExtension[..^1];
|
if (item.Property?.Id is null || item.ResizedFileHolder is null)
|
||||||
if (!results.TryGetValue(fileNameWithoutExtensionMinusOne, out collection))
|
continue;
|
||||||
{
|
if (results.Contains(item.Property.Id.Value))
|
||||||
results.Add(fileNameWithoutExtensionMinusOne, []);
|
continue;
|
||||||
if (!results.TryGetValue(fileNameWithoutExtensionMinusOne, out collection))
|
results.Add(item.Property.Id.Value);
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
collection.Add(filePath.FullName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string _)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
Models.Container[] results;
|
||||||
|
const bool useCeilingAverage = true;
|
||||||
|
const string fileSearchFilter = "*";
|
||||||
|
IDlibDotNet dlibDotNet = GetDlibDotNet();
|
||||||
|
const string directorySearchFilter = "*";
|
||||||
|
ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs = null;
|
||||||
|
ReadOnlyCollection<string[]> filesCollection = IDirectory.GetFilesCollection(propertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
|
||||||
|
ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
|
||||||
|
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, propertyConfiguration.RootDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
|
||||||
|
return (count, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IDlibDotNet GetDlibDotNet() =>
|
||||||
|
throw new NotImplementedException();
|
||||||
|
|
||||||
|
private static (int, Models.Container[]) GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
|
||||||
|
{
|
||||||
|
List<Models.Container> results = [];
|
||||||
|
string directory;
|
||||||
|
List<Item>? items;
|
||||||
|
Models.Container container;
|
||||||
|
List<string> directories = [];
|
||||||
|
Dictionary<string, List<Item>> directoryToItems = [];
|
||||||
|
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
|
||||||
|
{
|
||||||
|
if (filePaths.Count == 0)
|
||||||
|
continue;
|
||||||
|
directory = filePaths[0].DirectoryFullPath;
|
||||||
|
if (directory is null)
|
||||||
|
continue;
|
||||||
|
if (!directories.Contains(directory))
|
||||||
|
directories.Add(directory);
|
||||||
|
if (!directoryToItems.TryGetValue(directory, out items))
|
||||||
|
{
|
||||||
|
directoryToItems.Add(directory, []);
|
||||||
|
if (!directoryToItems.TryGetValue(directory, out items))
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(string aResultsFullGroupDirectory, _) = dlibDotNet.GetResultsFullGroupDirectories();
|
||||||
|
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
|
||||||
|
if (!Directory.Exists(aPropertySingletonDirectory))
|
||||||
|
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
|
||||||
|
List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
|
||||||
|
foreach (FilePair filePair in filePairs)
|
||||||
|
{
|
||||||
|
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
|
||||||
|
{
|
||||||
|
directoryToItems.Add(filePair.FilePath.DirectoryFullPath, []);
|
||||||
|
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
items.Add(filePair.Item);
|
||||||
|
}
|
||||||
|
foreach (KeyValuePair<string, List<Item>> keyValuePair in directoryToItems)
|
||||||
|
{
|
||||||
|
if (keyValuePair.Value.Count == 0)
|
||||||
|
continue;
|
||||||
|
container = new(keyValuePair.Key, new(keyValuePair.Value));
|
||||||
|
results.Add(container);
|
||||||
|
}
|
||||||
|
return (filePairs.Count, results.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
|
||||||
|
{
|
||||||
|
Models.Container[] results;
|
||||||
|
const string directorySearchFilter = "*";
|
||||||
|
(_, results) = GetContainers(dlibDotNet, propertyConfiguration, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
|
||||||
|
if (keyValuePairs is not null)
|
||||||
|
DoGetFilePairsForRemaining(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filePathsCollection, directorySearchFilter);
|
||||||
|
return results.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DoGetFilePairsForRemaining(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
|
||||||
|
{
|
||||||
|
const string extension = ".json";
|
||||||
|
(_, string bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
|
||||||
|
IReadOnlyDictionary<string, List<string>> fileNamesToFiles = GetFilesKeyValuePairs(filePathsCollection);
|
||||||
|
string bMetaSingletonDirectory = Path.Combine(bResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
|
||||||
|
if (!Directory.Exists(bMetaSingletonDirectory))
|
||||||
|
_ = Directory.CreateDirectory(bMetaSingletonDirectory);
|
||||||
|
_ = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, bMetaSingletonDirectory, filePathsCollection, fileNamesToFiles);
|
||||||
|
(string cResultsFullGroupDirectory, _, string dResultsFullGroupDirectory, _) = dlibDotNet.GetResultsFullGroupDirectories("Original");
|
||||||
|
string cResizeSingletonDirectory = Path.Combine(cResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
|
||||||
|
if (!Directory.Exists(cResizeSingletonDirectory))
|
||||||
|
_ = Directory.CreateDirectory(cResizeSingletonDirectory);
|
||||||
|
_ = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, cResizeSingletonDirectory, filePathsCollection, fileNamesToFiles);
|
||||||
|
string dFaceCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, propertyConfiguration.ResultCollection);
|
||||||
|
if (!Directory.Exists(dFaceCollectionDirectory))
|
||||||
|
_ = Directory.CreateDirectory(dFaceCollectionDirectory);
|
||||||
|
_ = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, dFaceCollectionDirectory, filePathsCollection, fileNamesToFiles);
|
||||||
|
string dFaceContentDirectory = Path.Combine(dResultsFullGroupDirectory, propertyConfiguration.ResultContent);
|
||||||
|
if (!Directory.Exists(dFaceContentDirectory))
|
||||||
|
_ = Directory.CreateDirectory(dFaceContentDirectory);
|
||||||
|
AnyMovedFace(facesFileNameExtension, facesHiddenFileNameExtension, fileNamesToFiles, dFaceContentDirectory);
|
||||||
|
AnyMovedDistance(facesFileNameExtension, fileNamesToFiles, eDistanceContentDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
private static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<string[]> filesCollection)
|
private static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<string[]> filesCollection)
|
||||||
{
|
{
|
||||||
Dictionary<string, List<string>> results = [];
|
Dictionary<string, List<string>> results = [];
|
||||||
@ -82,6 +188,75 @@ internal abstract class Container
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
|
||||||
|
{
|
||||||
|
Dictionary<string, List<string>> results = [];
|
||||||
|
List<string>? collection;
|
||||||
|
string fileNameWithoutExtensionMinusOne;
|
||||||
|
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
|
||||||
|
{
|
||||||
|
foreach (FilePath filePath in filePaths)
|
||||||
|
{
|
||||||
|
fileNameWithoutExtensionMinusOne = filePath.NameWithoutExtension[..^1];
|
||||||
|
if (!results.TryGetValue(fileNameWithoutExtensionMinusOne, out collection))
|
||||||
|
{
|
||||||
|
results.Add(fileNameWithoutExtensionMinusOne, []);
|
||||||
|
if (!results.TryGetValue(fileNameWithoutExtensionMinusOne, out collection))
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
collection.Add(filePath.FullName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Shared.Models.FilePair> GetFilePairs(IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string jsonGroupDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles)
|
||||||
|
{
|
||||||
|
List<Shared.Models.FilePair>? results = null;
|
||||||
|
int renamed;
|
||||||
|
const bool useCeilingAverage = true;
|
||||||
|
ReadOnlyCollection<string[]>? jsonFilesCollection = null;
|
||||||
|
IReadOnlyDictionary<string, List<string>>? compareFileNamesToFiles = null;
|
||||||
|
for (int i = 0; i < short.MaxValue; i++)
|
||||||
|
{
|
||||||
|
renamed = 0;
|
||||||
|
jsonFilesCollection = IDirectory.GetFilesCollection(jsonGroupDirectory, directorySearchFilter, extension, useCeilingAverage);
|
||||||
|
compareFileNamesToFiles = GetFilesKeyValuePairs(jsonFilesCollection);
|
||||||
|
renamed += LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension);
|
||||||
|
results = IDirectory.GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, compareFileNamesToFiles);
|
||||||
|
renamed += IDirectory.MaybeMove(propertyConfiguration, results, jsonGroupDirectory, extension);
|
||||||
|
if (renamed == 0)
|
||||||
|
break;
|
||||||
|
if (i > 10)
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
if (results is null || jsonFilesCollection is null || compareFileNamesToFiles is null)
|
||||||
|
throw new NullReferenceException(nameof(results));
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int LookForAbandoned(ReadOnlyCollection<string[]> jsonFilesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
bool check;
|
||||||
|
bool moved = false;
|
||||||
|
List<string> renameCollection = [];
|
||||||
|
foreach (string[] files in jsonFilesCollection)
|
||||||
|
{
|
||||||
|
if (files.Length == 0)
|
||||||
|
continue;
|
||||||
|
check = AnyMoved(fileNamesToFiles, extension, renameCollection, files);
|
||||||
|
if (!moved && check)
|
||||||
|
moved = true;
|
||||||
|
}
|
||||||
|
if (renameCollection.Count > 0)
|
||||||
|
IDirectory.MoveFiles(renameCollection, "{}", "{abd}");
|
||||||
|
result = renameCollection.Count;
|
||||||
|
if (moved && result == 0)
|
||||||
|
result = 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private static bool AnyMoved(IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, List<string> renameCollection, string[] files)
|
private static bool AnyMoved(IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, List<string> renameCollection, string[] files)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
@ -139,125 +314,149 @@ internal abstract class Container
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int LookForAbandoned(ReadOnlyCollection<string[]> jsonFilesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension)
|
private static void AnyMovedFace(string extension, string hiddenExtension, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string jsonGroupDirectory)
|
||||||
{
|
|
||||||
int result;
|
|
||||||
bool check;
|
|
||||||
bool moved = false;
|
|
||||||
List<string> renameCollection = [];
|
|
||||||
foreach (string[] files in jsonFilesCollection)
|
|
||||||
{
|
|
||||||
if (files.Length == 0)
|
|
||||||
continue;
|
|
||||||
check = AnyMoved(fileNamesToFiles, extension, renameCollection, files);
|
|
||||||
if (!moved && check)
|
|
||||||
moved = true;
|
|
||||||
}
|
|
||||||
if (renameCollection.Count > 0)
|
|
||||||
IDirectory.MoveFiles(renameCollection, "{}", "{abd}");
|
|
||||||
result = renameCollection.Count;
|
|
||||||
if (moved && result == 0)
|
|
||||||
result = 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Shared.Models.FilePair> GetFilePairs(IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string jsonGroupDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles)
|
|
||||||
{
|
|
||||||
List<Shared.Models.FilePair>? results = null;
|
|
||||||
int renamed;
|
|
||||||
const bool useCeilingAverage = true;
|
|
||||||
ReadOnlyCollection<string[]>? jsonFilesCollection = null;
|
|
||||||
IReadOnlyDictionary<string, List<string>>? compareFileNamesToFiles = null;
|
|
||||||
for (int i = 0; i < short.MaxValue; i++)
|
|
||||||
{
|
|
||||||
renamed = 0;
|
|
||||||
jsonFilesCollection = IDirectory.GetFilesCollection(jsonGroupDirectory, directorySearchFilter, extension, useCeilingAverage);
|
|
||||||
compareFileNamesToFiles = GetFilesKeyValuePairs(jsonFilesCollection);
|
|
||||||
renamed += LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension);
|
|
||||||
results = IDirectory.GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, compareFileNamesToFiles);
|
|
||||||
renamed += IDirectory.MaybeMove(propertyConfiguration, results, jsonGroupDirectory, extension);
|
|
||||||
if (renamed == 0)
|
|
||||||
break;
|
|
||||||
if (i > 10)
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
if (results is null || jsonFilesCollection is null || compareFileNamesToFiles is null)
|
|
||||||
throw new NullReferenceException(nameof(results));
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Property? GetProperty(Shared.Models.FilePair filePair)
|
|
||||||
{
|
|
||||||
Property? result;
|
|
||||||
if (filePair.Match is null)
|
|
||||||
result = null;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string json = File.ReadAllText(filePair.Match);
|
|
||||||
if (string.IsNullOrEmpty(json))
|
|
||||||
result = null;
|
|
||||||
else
|
|
||||||
result = JsonSerializer.Deserialize(json, PropertyGenerationContext.Default.Property);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ExifDirectory? GetExifDirectory(Shared.Models.FilePair filePair)
|
|
||||||
{
|
|
||||||
ExifDirectory? result;
|
|
||||||
if (filePair.Match is null)
|
|
||||||
result = null;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string json = File.ReadAllText(filePair.Match);
|
|
||||||
if (string.IsNullOrEmpty(json))
|
|
||||||
result = null;
|
|
||||||
else
|
|
||||||
result = JsonSerializer.Deserialize(json, ExifDirectorySourceGenerationContext.Default.ExifDirectory);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, string fullFileName)
|
|
||||||
{
|
|
||||||
string[] segments = directory.Split(cei.Combined);
|
|
||||||
string? checkDirectory = segments.Length == 1 ?
|
|
||||||
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
|
||||||
segments.Length == 2 ?
|
|
||||||
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
|
||||||
null;
|
|
||||||
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
|
||||||
{
|
|
||||||
string checkFile = Path.Combine(checkDirectory, fileName);
|
|
||||||
if (File.Exists(checkFile))
|
|
||||||
File.Move(checkFile, fullFileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RenameFile(string extension, Shared.Models.FilePair filePair, FilePath filePath, char change, ReadOnlyCollection<FilePath> filePaths)
|
|
||||||
{
|
{
|
||||||
|
string directory;
|
||||||
string checkFile;
|
string checkFile;
|
||||||
if (filePath.DirectoryFullPath.Contains("Results") && filePath.DirectoryFullPath.Contains("Resize"))
|
string directoryName;
|
||||||
File.Delete(filePath.FullName);
|
List<string> files = [];
|
||||||
if (!string.IsNullOrEmpty(filePair.Match))
|
string[] fileNameSegments;
|
||||||
|
List<string> directories = [];
|
||||||
|
files.AddRange(Directory.GetFiles(jsonGroupDirectory, $"*{extension}", SearchOption.AllDirectories));
|
||||||
|
files.AddRange(Directory.GetFiles(jsonGroupDirectory, $"*{hiddenExtension}", SearchOption.AllDirectories));
|
||||||
|
foreach (string file in files)
|
||||||
{
|
{
|
||||||
string directory = Path.GetDirectoryName(filePair.Match) ?? throw new Exception();
|
directory = Path.GetDirectoryName(file) ?? throw new Exception();
|
||||||
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePair.Match);
|
if (!directories.Contains(directory))
|
||||||
string fileNameWithoutExtensionSecond = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(filePair.Match));
|
directories.Add(directory);
|
||||||
string extensionSecond = Path.GetExtension(fileNameWithoutExtension);
|
directoryName = Path.GetFileName(directory);
|
||||||
checkFile = Path.Combine(directory, $"{fileNameWithoutExtensionSecond[..^1]}{change}{extensionSecond}{extension}");
|
fileNameSegments = Path.GetFileName(file).Split('.');
|
||||||
if (!File.Exists(checkFile))
|
if (fileNameSegments[0] != directoryName)
|
||||||
File.Move(filePair.Match, checkFile);
|
{
|
||||||
|
fileNameSegments[0] = string.Empty;
|
||||||
|
checkFile = Path.Combine(directory, $"{directoryName}{string.Join('.', fileNameSegments)}");
|
||||||
|
if (!File.Exists(checkFile))
|
||||||
|
File.Move(file, checkFile);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (new FileInfo(file).LastWriteTime > new FileInfo(checkFile).LastWriteTime)
|
||||||
|
File.Delete(file);
|
||||||
|
else
|
||||||
|
File.Move(file, checkFile, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
foreach (FilePath f in filePaths)
|
if (directories.Count > 0)
|
||||||
|
AnyMovedFace(fileNamesToFiles, directories);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AnyMovedFace(IReadOnlyDictionary<string, List<string>> fileNamesToFiles, List<string> directories)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
string checkFile;
|
||||||
|
string subDirectory;
|
||||||
|
string directoryName;
|
||||||
|
string checkDirectory;
|
||||||
|
List<string>? collection;
|
||||||
|
string directoryNameWith;
|
||||||
|
string directoryNameMinusOne;
|
||||||
|
List<string> directoryNames = [];
|
||||||
|
foreach (string directory in directories)
|
||||||
{
|
{
|
||||||
checkFile = Path.Combine(f.DirectoryFullPath, $"{f.NameWithoutExtension[..^1]}{change}{f.ExtensionLowered}");
|
directoryNameMinusOne = Path.GetFileName(directory)[..^1];
|
||||||
if (File.Exists(checkFile))
|
if (!fileNamesToFiles.TryGetValue(directoryNameMinusOne, out collection))
|
||||||
|
throw new Exception();
|
||||||
|
directoryNames.Clear();
|
||||||
|
foreach (string f in collection)
|
||||||
|
directoryNames.Add(Path.GetFileName(Path.GetDirectoryName(f)) ?? throw new Exception());
|
||||||
|
if (directoryNames.Count == 0 || directoryNames.Distinct().Count() != 1)
|
||||||
continue;
|
continue;
|
||||||
File.Move(f.FullName, checkFile);
|
directoryName = Path.GetFileName(Path.GetDirectoryName(directory)) ?? throw new Exception();
|
||||||
|
if (directoryName != directoryNames[0])
|
||||||
|
{
|
||||||
|
subDirectory = Path.GetDirectoryName(Path.GetDirectoryName(directory)) ?? throw new Exception();
|
||||||
|
checkDirectory = Path.Combine(subDirectory, directoryNames[0]);
|
||||||
|
if (!Directory.Exists(checkDirectory))
|
||||||
|
_ = Directory.CreateDirectory(checkDirectory);
|
||||||
|
directoryNameWith = collection.Count > 1 ? directoryName : $"{Path.GetFileNameWithoutExtension(collection[0])}";
|
||||||
|
checkFile = Path.Combine(checkDirectory, directoryNameWith);
|
||||||
|
if (!result)
|
||||||
|
result = true;
|
||||||
|
if (!Directory.Exists(checkFile))
|
||||||
|
Directory.Move(directory, checkFile);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (new DirectoryInfo(directory).LastWriteTime > new DirectoryInfo(checkFile).LastWriteTime)
|
||||||
|
Directory.Delete(directory, recursive: true);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Directory.Delete(checkFile, recursive: true);
|
||||||
|
Directory.Move(directory, checkFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void AnyMovedDistance(string extension, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string jsonGroupDirectory)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
string fileName;
|
||||||
|
string checkFile;
|
||||||
|
string directory;
|
||||||
|
List<string>? collection;
|
||||||
|
string[] fileNameSegments;
|
||||||
|
List<string> fileNames = [];
|
||||||
|
string fileNameSegmentsZeroMinusOne;
|
||||||
|
string[] files = Directory.GetFiles(jsonGroupDirectory, $"*{extension}", SearchOption.AllDirectories);
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
fileName = Path.GetFileName(file);
|
||||||
|
fileNameSegments = fileName.Split('.');
|
||||||
|
fileNameSegmentsZeroMinusOne = fileNameSegments[0][..^1];
|
||||||
|
if (!fileNamesToFiles.TryGetValue(fileNameSegmentsZeroMinusOne, out collection))
|
||||||
|
continue;
|
||||||
|
fileNames.Clear();
|
||||||
|
foreach (string f in collection)
|
||||||
|
fileNames.Add(Path.GetFileNameWithoutExtension(f) ?? throw new Exception());
|
||||||
|
if (fileNames.Count == 0 || fileNames.Distinct().Count() != 1)
|
||||||
|
continue;
|
||||||
|
if (fileNameSegments[0] != fileNames[0])
|
||||||
|
{
|
||||||
|
fileNameSegments[0] = string.Empty;
|
||||||
|
directory = Path.GetDirectoryName(file) ?? throw new Exception();
|
||||||
|
checkFile = Path.Combine(directory, $"{fileNames[0]}{string.Join('.', fileNameSegments)}");
|
||||||
|
if (!result)
|
||||||
|
result = true;
|
||||||
|
if (!File.Exists(checkFile))
|
||||||
|
File.Move(file, checkFile);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (new FileInfo(file).LastWriteTime > new FileInfo(checkFile).LastWriteTime)
|
||||||
|
File.Delete(file);
|
||||||
|
else
|
||||||
|
File.Move(file, checkFile, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<FilePair> GetFilePairs(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
|
||||||
|
{
|
||||||
|
List<FilePair> results = [];
|
||||||
|
const string extension = ".json";
|
||||||
|
List<Shared.Models.FilePair> filePairs;
|
||||||
|
string jsonGroupDirectory = aPropertySingletonDirectory;
|
||||||
|
int maxDegreeOfParallelism = Environment.ProcessorCount;
|
||||||
|
int filesCollectionDirectoryLength = filesCollectionDirectory.Length;
|
||||||
|
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||||
|
IReadOnlyDictionary<string, List<string>> fileNamesToFiles = GetFilesKeyValuePairs(filePathsCollection);
|
||||||
|
filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, jsonGroupDirectory, filePathsCollection, fileNamesToFiles);
|
||||||
|
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) =>
|
||||||
|
ParallelFor(dlibDotNet, propertyConfiguration, jsonGroupDirectory, extension, keyValuePairs, splatNineIdentifiers, filesCollectionDirectoryLength, filePairs[i], results));
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
private static void ParallelFor(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, int rootDirectoryLength, Shared.Models.FilePair filePair, List<FilePair> results)
|
private static void ParallelFor(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, int rootDirectoryLength, Shared.Models.FilePair filePair, List<FilePair> results)
|
||||||
{
|
{
|
||||||
dlibDotNet?.Tick();
|
dlibDotNet?.Tick();
|
||||||
@ -276,8 +475,8 @@ internal abstract class Container
|
|||||||
char? change;
|
char? change;
|
||||||
ReadOnlyCollection<FilePath>? filePaths = null;
|
ReadOnlyCollection<FilePath>? filePaths = null;
|
||||||
char hasIgnoreKeyword = IId.GetHasIgnoreKeyword(filePath).ToString()[0];
|
char hasIgnoreKeyword = IId.GetHasIgnoreKeyword(filePath).ToString()[0];
|
||||||
char hasDateTimeOriginal = IId.GetHasDateTimeOriginal(filePath).ToString()[0];
|
char hasDateTimeOriginal = IId.GetHasDateTimeOriginal(propertyConfiguration, filePath).ToString()[0];
|
||||||
char missingDateTimeOriginal = IId.GetMissingDateTimeOriginal(filePath).ToString()[0];
|
char missingDateTimeOriginal = IId.GetMissingDateTimeOriginal(propertyConfiguration, filePath).ToString()[0];
|
||||||
if (shouldIgnore is not null && shouldIgnore.Value)
|
if (shouldIgnore is not null && shouldIgnore.Value)
|
||||||
{
|
{
|
||||||
if (filePath.NameWithoutExtension[^1] == hasIgnoreKeyword)
|
if (filePath.NameWithoutExtension[^1] == hasIgnoreKeyword)
|
||||||
@ -337,272 +536,76 @@ internal abstract class Container
|
|||||||
results.Add(new(filePair.IsUnique, filePair.Collection, filePath, item));
|
results.Add(new(filePair.IsUnique, filePair.Collection, filePath, item));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<FilePair> GetFilePairs(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
|
private static Property? GetProperty(Shared.Models.FilePair filePair)
|
||||||
{
|
{
|
||||||
List<FilePair> results = [];
|
Property? result;
|
||||||
const string extension = ".json";
|
if (filePair.Match is null)
|
||||||
List<Shared.Models.FilePair> filePairs;
|
result = null;
|
||||||
string jsonGroupDirectory = aPropertySingletonDirectory;
|
else
|
||||||
int maxDegreeOfParallelism = Environment.ProcessorCount;
|
{
|
||||||
int filesCollectionDirectoryLength = filesCollectionDirectory.Length;
|
string json = File.ReadAllText(filePair.Match);
|
||||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
if (string.IsNullOrEmpty(json))
|
||||||
IReadOnlyDictionary<string, List<string>> fileNamesToFiles = GetFilesKeyValuePairs(filePathsCollection);
|
result = null;
|
||||||
filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, jsonGroupDirectory, filePathsCollection, fileNamesToFiles);
|
else
|
||||||
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) =>
|
result = JsonSerializer.Deserialize(json, PropertyGenerationContext.Default.Property);
|
||||||
ParallelFor(dlibDotNet, propertyConfiguration, jsonGroupDirectory, extension, keyValuePairs, splatNineIdentifiers, filesCollectionDirectoryLength, filePairs[i], results));
|
}
|
||||||
return results;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (int, Models.Container[]) GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
|
private static ExifDirectory? GetExifDirectory(Shared.Models.FilePair filePair)
|
||||||
{
|
{
|
||||||
List<Models.Container> results = [];
|
ExifDirectory? result;
|
||||||
string directory;
|
if (filePair.Match is null)
|
||||||
List<Item>? items;
|
result = null;
|
||||||
Models.Container container;
|
else
|
||||||
List<string> directories = [];
|
|
||||||
Dictionary<string, List<Item>> directoryToItems = [];
|
|
||||||
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
|
|
||||||
{
|
{
|
||||||
if (filePaths.Count == 0)
|
string json = File.ReadAllText(filePair.Match);
|
||||||
continue;
|
if (string.IsNullOrEmpty(json))
|
||||||
directory = filePaths[0].DirectoryFullPath;
|
result = null;
|
||||||
if (directory is null)
|
else
|
||||||
continue;
|
result = JsonSerializer.Deserialize(json, ExifDirectorySourceGenerationContext.Default.ExifDirectory);
|
||||||
if (!directories.Contains(directory))
|
|
||||||
directories.Add(directory);
|
|
||||||
if (!directoryToItems.TryGetValue(directory, out items))
|
|
||||||
{
|
|
||||||
directoryToItems.Add(directory, []);
|
|
||||||
if (!directoryToItems.TryGetValue(directory, out items))
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
(string aResultsFullGroupDirectory, _) = dlibDotNet.GetResultsFullGroupDirectories();
|
return result;
|
||||||
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
|
|
||||||
if (!Directory.Exists(aPropertySingletonDirectory))
|
|
||||||
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
|
|
||||||
List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
|
|
||||||
foreach (FilePair filePair in filePairs)
|
|
||||||
{
|
|
||||||
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
|
|
||||||
{
|
|
||||||
directoryToItems.Add(filePair.FilePath.DirectoryFullPath, []);
|
|
||||||
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
items.Add(filePair.Item);
|
|
||||||
}
|
|
||||||
foreach (KeyValuePair<string, List<Item>> keyValuePair in directoryToItems)
|
|
||||||
{
|
|
||||||
if (keyValuePair.Value.Count == 0)
|
|
||||||
continue;
|
|
||||||
container = new(keyValuePair.Key, new(keyValuePair.Value));
|
|
||||||
results.Add(container);
|
|
||||||
}
|
|
||||||
return (filePairs.Count, results.ToArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AnyMovedFace(IReadOnlyDictionary<string, List<string>> fileNamesToFiles, List<string> directories)
|
private static void RenameFile(string extension, Shared.Models.FilePair filePair, FilePath filePath, char change, ReadOnlyCollection<FilePath> filePaths)
|
||||||
{
|
{
|
||||||
bool result = false;
|
|
||||||
string checkFile;
|
string checkFile;
|
||||||
string subDirectory;
|
if (filePath.DirectoryFullPath.Contains("Results") && filePath.DirectoryFullPath.Contains("Resize"))
|
||||||
string directoryName;
|
File.Delete(filePath.FullName);
|
||||||
string checkDirectory;
|
if (!string.IsNullOrEmpty(filePair.Match))
|
||||||
List<string>? collection;
|
|
||||||
string directoryNameWith;
|
|
||||||
string directoryNameMinusOne;
|
|
||||||
List<string> directoryNames = [];
|
|
||||||
foreach (string directory in directories)
|
|
||||||
{
|
{
|
||||||
directoryNameMinusOne = Path.GetFileName(directory)[..^1];
|
string directory = Path.GetDirectoryName(filePair.Match) ?? throw new Exception();
|
||||||
if (!fileNamesToFiles.TryGetValue(directoryNameMinusOne, out collection))
|
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePair.Match);
|
||||||
throw new Exception();
|
string fileNameWithoutExtensionSecond = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(filePair.Match));
|
||||||
directoryNames.Clear();
|
string extensionSecond = Path.GetExtension(fileNameWithoutExtension);
|
||||||
foreach (string f in collection)
|
checkFile = Path.Combine(directory, $"{fileNameWithoutExtensionSecond[..^1]}{change}{extensionSecond}{extension}");
|
||||||
directoryNames.Add(Path.GetFileName(Path.GetDirectoryName(f)) ?? throw new Exception());
|
if (!File.Exists(checkFile))
|
||||||
if (directoryNames.Count == 0 || directoryNames.Distinct().Count() != 1)
|
File.Move(filePair.Match, checkFile);
|
||||||
|
}
|
||||||
|
foreach (FilePath f in filePaths)
|
||||||
|
{
|
||||||
|
checkFile = Path.Combine(f.DirectoryFullPath, $"{f.NameWithoutExtension[..^1]}{change}{f.ExtensionLowered}");
|
||||||
|
if (File.Exists(checkFile))
|
||||||
continue;
|
continue;
|
||||||
directoryName = Path.GetFileName(Path.GetDirectoryName(directory)) ?? throw new Exception();
|
File.Move(f.FullName, checkFile);
|
||||||
if (directoryName != directoryNames[0])
|
|
||||||
{
|
|
||||||
subDirectory = Path.GetDirectoryName(Path.GetDirectoryName(directory)) ?? throw new Exception();
|
|
||||||
checkDirectory = Path.Combine(subDirectory, directoryNames[0]);
|
|
||||||
if (!Directory.Exists(checkDirectory))
|
|
||||||
_ = Directory.CreateDirectory(checkDirectory);
|
|
||||||
directoryNameWith = collection.Count > 1 ? directoryName : $"{Path.GetFileNameWithoutExtension(collection[0])}";
|
|
||||||
checkFile = Path.Combine(checkDirectory, directoryNameWith);
|
|
||||||
if (!result)
|
|
||||||
result = true;
|
|
||||||
if (!Directory.Exists(checkFile))
|
|
||||||
Directory.Move(directory, checkFile);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (new DirectoryInfo(directory).LastWriteTime > new DirectoryInfo(checkFile).LastWriteTime)
|
|
||||||
Directory.Delete(directory, recursive: true);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Directory.Delete(checkFile, recursive: true);
|
|
||||||
Directory.Move(directory, checkFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AnyMovedFace(string extension, string hiddenExtension, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string jsonGroupDirectory)
|
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, string fullFileName)
|
||||||
{
|
{
|
||||||
string directory;
|
string[] segments = directory.Split(cei.Combined);
|
||||||
string checkFile;
|
string? checkDirectory = segments.Length == 1 ?
|
||||||
string directoryName;
|
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
||||||
List<string> files = [];
|
segments.Length == 2 ?
|
||||||
string[] fileNameSegments;
|
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
||||||
List<string> directories = [];
|
null;
|
||||||
files.AddRange(Directory.GetFiles(jsonGroupDirectory, $"*{extension}", SearchOption.AllDirectories));
|
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
||||||
files.AddRange(Directory.GetFiles(jsonGroupDirectory, $"*{hiddenExtension}", SearchOption.AllDirectories));
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
{
|
||||||
directory = Path.GetDirectoryName(file) ?? throw new Exception();
|
string checkFile = Path.Combine(checkDirectory, fileName);
|
||||||
if (!directories.Contains(directory))
|
if (File.Exists(checkFile))
|
||||||
directories.Add(directory);
|
File.Move(checkFile, fullFileName);
|
||||||
directoryName = Path.GetFileName(directory);
|
|
||||||
fileNameSegments = Path.GetFileName(file).Split('.');
|
|
||||||
if (fileNameSegments[0] != directoryName)
|
|
||||||
{
|
|
||||||
fileNameSegments[0] = string.Empty;
|
|
||||||
checkFile = Path.Combine(directory, $"{directoryName}{string.Join('.', fileNameSegments)}");
|
|
||||||
if (!File.Exists(checkFile))
|
|
||||||
File.Move(file, checkFile);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (new FileInfo(file).LastWriteTime > new FileInfo(checkFile).LastWriteTime)
|
|
||||||
File.Delete(file);
|
|
||||||
else
|
|
||||||
File.Move(file, checkFile, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (directories.Count > 0)
|
|
||||||
AnyMovedFace(fileNamesToFiles, directories);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AnyMovedDistance(string extension, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string jsonGroupDirectory)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
string fileName;
|
|
||||||
string checkFile;
|
|
||||||
string directory;
|
|
||||||
List<string>? collection;
|
|
||||||
string[] fileNameSegments;
|
|
||||||
List<string> fileNames = [];
|
|
||||||
string fileNameSegmentsZeroMinusOne;
|
|
||||||
string[] files = Directory.GetFiles(jsonGroupDirectory, $"*{extension}", SearchOption.AllDirectories);
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
fileName = Path.GetFileName(file);
|
|
||||||
fileNameSegments = fileName.Split('.');
|
|
||||||
fileNameSegmentsZeroMinusOne = fileNameSegments[0][..^1];
|
|
||||||
if (!fileNamesToFiles.TryGetValue(fileNameSegmentsZeroMinusOne, out collection))
|
|
||||||
continue;
|
|
||||||
fileNames.Clear();
|
|
||||||
foreach (string f in collection)
|
|
||||||
fileNames.Add(Path.GetFileNameWithoutExtension(f) ?? throw new Exception());
|
|
||||||
if (fileNames.Count == 0 || fileNames.Distinct().Count() != 1)
|
|
||||||
continue;
|
|
||||||
if (fileNameSegments[0] != fileNames[0])
|
|
||||||
{
|
|
||||||
fileNameSegments[0] = string.Empty;
|
|
||||||
directory = Path.GetDirectoryName(file) ?? throw new Exception();
|
|
||||||
checkFile = Path.Combine(directory, $"{fileNames[0]}{string.Join('.', fileNameSegments)}");
|
|
||||||
if (!result)
|
|
||||||
result = true;
|
|
||||||
if (!File.Exists(checkFile))
|
|
||||||
File.Move(file, checkFile);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (new FileInfo(file).LastWriteTime > new FileInfo(checkFile).LastWriteTime)
|
|
||||||
File.Delete(file);
|
|
||||||
else
|
|
||||||
File.Move(file, checkFile, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DoGetFilePairsForRemaining(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, string directorySearchFilter)
|
|
||||||
{
|
|
||||||
const string extension = ".json";
|
|
||||||
(_, string bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
|
|
||||||
IReadOnlyDictionary<string, List<string>> fileNamesToFiles = GetFilesKeyValuePairs(filePathsCollection);
|
|
||||||
string bMetaSingletonDirectory = Path.Combine(bResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
|
|
||||||
if (!Directory.Exists(bMetaSingletonDirectory))
|
|
||||||
_ = Directory.CreateDirectory(bMetaSingletonDirectory);
|
|
||||||
_ = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, bMetaSingletonDirectory, filePathsCollection, fileNamesToFiles);
|
|
||||||
(string cResultsFullGroupDirectory, _, string dResultsFullGroupDirectory, _) = dlibDotNet.GetResultsFullGroupDirectories("Original");
|
|
||||||
string cResizeSingletonDirectory = Path.Combine(cResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
|
|
||||||
if (!Directory.Exists(cResizeSingletonDirectory))
|
|
||||||
_ = Directory.CreateDirectory(cResizeSingletonDirectory);
|
|
||||||
_ = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, cResizeSingletonDirectory, filePathsCollection, fileNamesToFiles);
|
|
||||||
string dFaceCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, propertyConfiguration.ResultCollection);
|
|
||||||
if (!Directory.Exists(dFaceCollectionDirectory))
|
|
||||||
_ = Directory.CreateDirectory(dFaceCollectionDirectory);
|
|
||||||
_ = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, dFaceCollectionDirectory, filePathsCollection, fileNamesToFiles);
|
|
||||||
string dFaceContentDirectory = Path.Combine(dResultsFullGroupDirectory, propertyConfiguration.ResultContent);
|
|
||||||
if (!Directory.Exists(dFaceContentDirectory))
|
|
||||||
_ = Directory.CreateDirectory(dFaceContentDirectory);
|
|
||||||
AnyMovedFace(facesFileNameExtension, facesHiddenFileNameExtension, fileNamesToFiles, dFaceContentDirectory);
|
|
||||||
AnyMovedDistance(facesFileNameExtension, fileNamesToFiles, eDistanceContentDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
|
|
||||||
{
|
|
||||||
Models.Container[] results;
|
|
||||||
const string directorySearchFilter = "*";
|
|
||||||
(_, results) = GetContainers(dlibDotNet, propertyConfiguration, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
|
|
||||||
if (keyValuePairs is not null)
|
|
||||||
DoGetFilePairsForRemaining(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filePathsCollection, directorySearchFilter);
|
|
||||||
return results.AsReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IDlibDotNet GetDlibDotNet() =>
|
|
||||||
throw new NotImplementedException();
|
|
||||||
|
|
||||||
internal static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string _)
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
Models.Container[] results;
|
|
||||||
const bool useCeilingAverage = true;
|
|
||||||
const string fileSearchFilter = "*";
|
|
||||||
IDlibDotNet dlibDotNet = GetDlibDotNet();
|
|
||||||
const string directorySearchFilter = "*";
|
|
||||||
ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs = null;
|
|
||||||
ReadOnlyCollection<string[]> filesCollection = IDirectory.GetFilesCollection(propertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
|
|
||||||
ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection = IDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
|
|
||||||
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, propertyConfiguration.RootDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, directorySearchFilter);
|
|
||||||
return (count, results);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static List<int> GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers)
|
|
||||||
{
|
|
||||||
List<int> results = [];
|
|
||||||
ReadOnlyCollection<Item> filteredItems;
|
|
||||||
foreach (Models.Container container in readOnlyContainers)
|
|
||||||
{
|
|
||||||
if (container.Items.Count == 0)
|
|
||||||
continue;
|
|
||||||
filteredItems = GetValidImageItems(propertyConfiguration, container);
|
|
||||||
if (filteredItems.Count == 0)
|
|
||||||
continue;
|
|
||||||
foreach (Item item in filteredItems)
|
|
||||||
{
|
|
||||||
if (item.Property?.Id is null || item.ResizedFileHolder is null)
|
|
||||||
continue;
|
|
||||||
if (results.Contains(item.Property.Id.Value))
|
|
||||||
continue;
|
|
||||||
results.Add(item.Property.Id.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<string> GetFilteredDistinctFileNameFirstSegments(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers)
|
internal static List<string> GetFilteredDistinctFileNameFirstSegments(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers)
|
||||||
|
@ -8,44 +8,52 @@ namespace View_by_Distance.Container.Models.Stateless.Methods;
|
|||||||
public interface IContainer
|
public interface IContainer
|
||||||
{
|
{
|
||||||
|
|
||||||
DateTime[] TestStatic_GetContainerDateTimes(ReadOnlyCollection<Item> items) =>
|
public static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
|
||||||
GetContainerDateTimes(items);
|
|
||||||
static DateTime[] GetContainerDateTimes(ReadOnlyCollection<Item> items) =>
|
|
||||||
Container.GetContainerDateTimes(items);
|
|
||||||
|
|
||||||
ReadOnlyCollection<Item> TestStatic_GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
|
||||||
GetValidImageItems(propertyConfiguration, container);
|
|
||||||
static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
|
||||||
Container.GetValidImageItems(propertyConfiguration, container);
|
|
||||||
|
|
||||||
(int, Models.Container[]) TestStatic_GetContainers(IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
|
||||||
GetContainers(propertyConfiguration, aPropertySingletonDirectory);
|
|
||||||
static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
|
||||||
GetContainers(propertyConfiguration, null, aPropertySingletonDirectory);
|
|
||||||
|
|
||||||
(int, Models.Container[]) TestStatic_GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
|
|
||||||
GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
|
|
||||||
static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
|
|
||||||
Container.GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
|
Container.GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
|
||||||
|
|
||||||
ReadOnlyCollection<Models.Container> TestStatic_GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
|
public static DateTime[] GetContainerDateTimes(ReadOnlyCollection<Item> items) =>
|
||||||
GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection);
|
Container.GetContainerDateTimes(items);
|
||||||
static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
|
|
||||||
Container.GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection);
|
|
||||||
|
|
||||||
List<int> TestStatic_GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
public static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
||||||
GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
Container.GetValidImageItems(propertyConfiguration, container);
|
||||||
static List<int> GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
|
||||||
|
public static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
||||||
|
GetContainers(propertyConfiguration, null, aPropertySingletonDirectory);
|
||||||
|
|
||||||
|
public static List<int> GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
||||||
Container.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
Container.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
||||||
|
|
||||||
List<string> TestStatic_GetFilteredDistinctFileNameFirstSegments(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
public static List<string> GetFilteredDistinctFileNameFirstSegments(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
||||||
GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
|
||||||
static List<string> GetFilteredDistinctFileNameFirstSegments(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
|
||||||
Container.GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
Container.GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
||||||
|
|
||||||
ReadOnlyCollection<Item> TestStatic_GetValidImageItems(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
|
public static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
|
||||||
GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
|
|
||||||
static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
|
|
||||||
Container.GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
|
Container.GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
|
||||||
|
|
||||||
|
public static ReadOnlyCollection<Models.Container> GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
|
||||||
|
Container.GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection);
|
||||||
|
|
||||||
|
internal DateTime[] TestStatic_GetContainerDateTimes(ReadOnlyCollection<Item> items) =>
|
||||||
|
GetContainerDateTimes(items);
|
||||||
|
|
||||||
|
internal ReadOnlyCollection<Item> TestStatic_GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
||||||
|
GetValidImageItems(propertyConfiguration, container);
|
||||||
|
|
||||||
|
internal (int, Models.Container[]) TestStatic_GetContainers(IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
||||||
|
GetContainers(propertyConfiguration, aPropertySingletonDirectory);
|
||||||
|
|
||||||
|
internal List<int> TestStatic_GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
||||||
|
GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
||||||
|
|
||||||
|
internal List<string> TestStatic_GetFilteredDistinctFileNameFirstSegments(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
||||||
|
GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
||||||
|
|
||||||
|
internal ReadOnlyCollection<Item> TestStatic_GetValidImageItems(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
|
||||||
|
GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
|
||||||
|
|
||||||
|
internal (int, Models.Container[]) TestStatic_GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
|
||||||
|
GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
|
||||||
|
|
||||||
|
internal ReadOnlyCollection<Models.Container> TestStatic_GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection) =>
|
||||||
|
GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection);
|
||||||
|
|
||||||
}
|
}
|
@ -95,6 +95,73 @@ public class D_Face : IFaceD
|
|||||||
_WriteIndentedAndWhenWritingNull = new JsonSerializerOptions { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull };
|
_WriteIndentedAndWhenWritingNull = new JsonSerializerOptions { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IFaceD.ReSaveFace(ExifDirectory exifDirectory, FilePath filePath, Shared.Models.Face face, bool mappedFile)
|
||||||
|
{
|
||||||
|
FileInfo fileInfo = new(filePath.FullName);
|
||||||
|
if (fileInfo.Exists)
|
||||||
|
{
|
||||||
|
string? json;
|
||||||
|
short type = 2;
|
||||||
|
string? model;
|
||||||
|
string? maker;
|
||||||
|
string checkFile = $"{filePath.FullName}.exif";
|
||||||
|
const int artist = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist;
|
||||||
|
// const int author = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagWinAuthor; // 40093
|
||||||
|
if (mappedFile)
|
||||||
|
{
|
||||||
|
json = IMetadata.GetOutputResolution(exifDirectory);
|
||||||
|
if (json is not null && json.Contains(nameof(DateTime)))
|
||||||
|
return;
|
||||||
|
(maker, model) = Get(json);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maker = IMetadata.GetMaker(exifDirectory);
|
||||||
|
model = IMetadata.GetModel(exifDirectory);
|
||||||
|
ExifDirectory? faceExifDirectory = IMetadata.GetExifDirectory(filePath);
|
||||||
|
json = IMetadata.GetOutputResolution(faceExifDirectory);
|
||||||
|
if (json is not null && json.Contains(nameof(DateTime)))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MetadataExtractor.GeoLocation? geoLocation = IMetadata.GeoLocation(exifDirectory);
|
||||||
|
FaceFile faceFile = new(face.Mapping?.MappingFromLocation?.AreaPermyriad,
|
||||||
|
face.Mapping?.MappingFromLocation?.ConfidencePercent,
|
||||||
|
geoLocation?.ToDmsString(),
|
||||||
|
face.DateTime,
|
||||||
|
null,
|
||||||
|
face.FaceParts,
|
||||||
|
face.Location,
|
||||||
|
maker,
|
||||||
|
null,
|
||||||
|
model,
|
||||||
|
face.OutputResolution);
|
||||||
|
string faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile);
|
||||||
|
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, [], null) ?? throw new Exception();
|
||||||
|
PropertyItem? propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(constructorInfo, artist, type, faceFileJson);
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
Bitmap bitmap = new(fileInfo.FullName);
|
||||||
|
bitmap.SetPropertyItem(propertyItem);
|
||||||
|
bitmap.Save(checkFile);
|
||||||
|
bitmap.Dispose();
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
File.SetLastWriteTime(checkFile, fileInfo.LastWriteTime);
|
||||||
|
File.Delete(fileInfo.FullName);
|
||||||
|
File.Move(checkFile, fileInfo.FullName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (string?, string?) Get(string? json)
|
||||||
|
{
|
||||||
|
string? model;
|
||||||
|
string? maker;
|
||||||
|
FaceFile? faceFile = json is null ? null : JsonSerializer.Deserialize(json, FaceFileGenerationContext.Default.FaceFile);
|
||||||
|
if (faceFile is null || faceFile.Location is null)
|
||||||
|
(maker, model) = (null, null);
|
||||||
|
else
|
||||||
|
(maker, model) = (faceFile.Maker, faceFile.Model);
|
||||||
|
return (maker, model);
|
||||||
|
}
|
||||||
|
|
||||||
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 });
|
||||||
@ -115,194 +182,50 @@ public class D_Face : IFaceD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (Model model, PredictorModel predictorModel, ModelParameter modelParameter) GetModel(string modelDirectory, string modelName, string predictorModelName)
|
public List<(Shared.Models.Face, FileHolder?, string, bool)> SaveFaces(FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces)
|
||||||
{
|
{
|
||||||
(Model, PredictorModel, ModelParameter) result;
|
List<(Shared.Models.Face, FileHolder?, string, bool Save)> results = [];
|
||||||
Array array;
|
bool save;
|
||||||
Model? model = null;
|
FileInfo fileInfo;
|
||||||
array = Enum.GetValues<Model>();
|
FileHolder fileHolder;
|
||||||
PredictorModel? predictorModel = null;
|
string deterministicHashCodeKey;
|
||||||
foreach (Model check in array)
|
string fileName = mappingFromItem.FilePath.NameWithoutExtension;
|
||||||
|
string[] changesFrom = [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();
|
||||||
|
CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
|
||||||
|
string directory = _ResultContentFileGroups[0][cei.Enum][cei.Index];
|
||||||
|
DirectoryInfo directoryInfo = new(Path.Combine(directory, fileName));
|
||||||
|
MoveIf(fileName, cei, directory, directoryInfo);
|
||||||
|
foreach (Shared.Models.Face face in faces)
|
||||||
{
|
{
|
||||||
if (modelName.Contains(check.ToString()))
|
save = false;
|
||||||
|
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
|
||||||
{
|
{
|
||||||
model = check;
|
results.Add(new(face, null, string.Empty, save));
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(filePath, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
|
||||||
|
fileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, $"{deterministicHashCodeKey}{mappingFromItem.FilePath.ExtensionLowered}{_FileNameExtension}"));
|
||||||
|
fileHolder = FileHolder.Get(fileInfo);
|
||||||
|
if (!directoryInfo.Exists)
|
||||||
|
save = true;
|
||||||
|
else if (_OverrideForFaceImages)
|
||||||
|
save = true;
|
||||||
|
else if (!fileHolder.Exists)
|
||||||
|
save = true;
|
||||||
|
else if (_CheckDFaceAndUpWriteDates && dateTimes.Count > 0 && dateTimes.Max() > fileInfo.LastWriteTime)
|
||||||
|
save = true;
|
||||||
|
results.Add(new(face, fileHolder, Path.Combine(directoryInfo.FullName, $"{deterministicHashCodeKey}{mappingFromItem.FilePath.ExtensionLowered}{_HiddenFileNameExtension}"), save));
|
||||||
}
|
}
|
||||||
if (model is null)
|
if (results.Any(l => l.Save))
|
||||||
throw new Exception("Destination directory must have Model name!");
|
|
||||||
model = model.Value;
|
|
||||||
array = Enum.GetValues<PredictorModel>();
|
|
||||||
foreach (PredictorModel check in array)
|
|
||||||
{
|
{
|
||||||
if (predictorModelName.Contains(check.ToString()))
|
if (!directoryInfo.Exists)
|
||||||
{
|
_ = Directory.CreateDirectory(directoryInfo.FullName);
|
||||||
predictorModel = check;
|
SaveFaces(mappingFromItem.ResizedFileHolder, exifDirectory, results);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (predictorModel is null)
|
|
||||||
throw new Exception("Destination directory must have Predictor Model name!");
|
|
||||||
predictorModel = predictorModel.Value;
|
|
||||||
ModelParameter modelParameter = new()
|
|
||||||
{
|
|
||||||
CnnFaceDetectorModel = File.ReadAllBytes(Path.Combine(modelDirectory, "mmod_human_face_detector.dat")),
|
|
||||||
FaceRecognitionModel = File.ReadAllBytes(Path.Combine(modelDirectory, "dlib_face_recognition_resnet_model_v1.dat")),
|
|
||||||
PosePredictor5FaceLandmarksModel = File.ReadAllBytes(Path.Combine(modelDirectory, "shape_predictor_5_face_landmarks.dat")),
|
|
||||||
PosePredictor68FaceLandmarksModel = File.ReadAllBytes(Path.Combine(modelDirectory, "shape_predictor_68_face_landmarks.dat"))
|
|
||||||
};
|
|
||||||
result = new(model.Value, predictorModel.Value, modelParameter);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning disable CA1416
|
|
||||||
|
|
||||||
private void SaveFaces(FileHolder resizedFileHolder, ExifDirectory exifDirectory, List<(Shared.Models.Face, FileHolder?, string, bool)> collection)
|
|
||||||
{
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
Bitmap bitmap;
|
|
||||||
short type = 2;
|
|
||||||
FaceFile faceFile;
|
|
||||||
Graphics graphics;
|
|
||||||
Location? location;
|
|
||||||
Rectangle rectangle;
|
|
||||||
string faceFileJson;
|
|
||||||
string faceEncodingJson;
|
|
||||||
PropertyItem? propertyItem;
|
|
||||||
string? maker = IMetadata.GetMaker(exifDirectory);
|
|
||||||
string? model = IMetadata.GetModel(exifDirectory);
|
|
||||||
using Bitmap source = new(resizedFileHolder.FullName);
|
|
||||||
MetadataExtractor.GeoLocation? geoLocation = IMetadata.GeoLocation(exifDirectory);
|
|
||||||
const int artist = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist; // 315
|
|
||||||
const int userComment = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagUserComment;
|
|
||||||
foreach ((Shared.Models.Face face, FileHolder? fileHolder, string fileName, bool save) in collection)
|
|
||||||
{
|
|
||||||
if (!save)
|
|
||||||
continue;
|
|
||||||
if (fileHolder is null)
|
|
||||||
continue;
|
|
||||||
if (face.FaceEncoding is null || face?.Location is null || face?.OutputResolution is null)
|
|
||||||
continue;
|
|
||||||
if (_OverrideForFaceImages && fileHolder.Exists)
|
|
||||||
{
|
|
||||||
IFaceD dFace = this;
|
|
||||||
FilePath filePath = FilePath.Get(_PropertyConfiguration, fileHolder, index: null);
|
|
||||||
dFace.ReSaveFace(exifDirectory, filePath, face, mappedFile: false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
location = Shared.Models.Stateless.Methods.ILocation.GetLocation(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, source.Height, source.Width, collection.Count);
|
|
||||||
if (location is null)
|
|
||||||
continue;
|
|
||||||
width = location.Right - location.Left;
|
|
||||||
height = location.Bottom - location.Top;
|
|
||||||
faceEncodingJson = JsonSerializer.Serialize(face.FaceEncoding);
|
|
||||||
rectangle = new Rectangle(location.Left, location.Top, width, height);
|
|
||||||
faceFile = new(face.Mapping?.MappingFromLocation?.AreaPermyriad,
|
|
||||||
face.Mapping?.MappingFromLocation?.ConfidencePercent,
|
|
||||||
geoLocation?.ToDmsString(),
|
|
||||||
face.DateTime,
|
|
||||||
null,
|
|
||||||
face.FaceParts,
|
|
||||||
face.Location,
|
|
||||||
maker,
|
|
||||||
null,
|
|
||||||
model,
|
|
||||||
face.OutputResolution);
|
|
||||||
faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile);
|
|
||||||
using (bitmap = new(width, height))
|
|
||||||
{
|
|
||||||
using (graphics = Graphics.FromImage(bitmap))
|
|
||||||
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
|
|
||||||
propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(_ConstructorInfo, artist, type, faceFileJson);
|
|
||||||
bitmap.SetPropertyItem(propertyItem);
|
|
||||||
propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(_ConstructorInfo, userComment, type, faceEncodingJson);
|
|
||||||
bitmap.SetPropertyItem(propertyItem);
|
|
||||||
bitmap.Save(fileHolder.FullName, _ImageCodecInfo, _EncoderParameters);
|
|
||||||
}
|
|
||||||
if (File.Exists(fileName))
|
|
||||||
File.Delete(fileName);
|
|
||||||
location = Shared.Models.Stateless.Methods.ILocation.GetLocation(_FaceDistanceHiddenImageFactor, face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, source.Height, source.Width, collection.Count);
|
|
||||||
if (location is null)
|
|
||||||
continue;
|
|
||||||
width = location.Right - location.Left;
|
|
||||||
height = location.Bottom - location.Top;
|
|
||||||
rectangle = new Rectangle(location.Left, location.Top, width, height);
|
|
||||||
using (bitmap = new(width, height))
|
|
||||||
{
|
|
||||||
using (graphics = Graphics.FromImage(bitmap))
|
|
||||||
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
|
|
||||||
bitmap.Save(fileName, _HiddenImageCodecInfo, _HiddenEncoderParameters);
|
|
||||||
}
|
|
||||||
File.SetAttributes(fileName, FileAttributes.Hidden);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Shared.Models.Face> GetFaces(string outputResolution, string cResultsFullGroupDirectory, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<Location> locations)
|
|
||||||
{
|
|
||||||
if (_PropertyConfiguration.NumberOfJitters is null)
|
|
||||||
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfJitters));
|
|
||||||
if (_PropertyConfiguration.NumberOfTimesToUpsample is null)
|
|
||||||
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfTimesToUpsample));
|
|
||||||
List<Shared.Models.Face> results = [];
|
|
||||||
FaceRecognitionDotNet.Image? unknownImage;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (mappingFromItem.ResizedFileHolder.ExtensionLowered != ".tif")
|
|
||||||
unknownImage = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int outputQuality = 100;
|
|
||||||
string extension = ".png";
|
|
||||||
string file = Path.Combine(cResultsFullGroupDirectory, $"{mappingFromItem.ResizedFileHolder.Name}{extension}");
|
|
||||||
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(extension, outputQuality);
|
|
||||||
#pragma warning disable CA1416
|
|
||||||
System.Drawing.Image image = System.Drawing.Image.FromFile(mappingFromItem.ResizedFileHolder.FullName);
|
|
||||||
image.Save(Path.Combine(cResultsFullGroupDirectory, $"{mappingFromItem.ResizedFileHolder.Name}{filenameExtension}"), imageCodecInfo, encoderParameters);
|
|
||||||
image.Dispose();
|
|
||||||
#pragma warning restore CA1416
|
|
||||||
unknownImage = FaceRecognition.LoadImageFile(file);
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{ unknownImage = null; }
|
|
||||||
if (unknownImage is not null)
|
|
||||||
{
|
|
||||||
(int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation) = Resize.Models.Stateless.Methods.IResize.Get(outputResolution, outputResolutionToResize);
|
|
||||||
List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
|
|
||||||
FaceRecognition faceRecognition = new(_PropertyConfiguration.NumberOfJitters.Value, _PropertyConfiguration.NumberOfTimesToUpsample.Value, _Model, _ModelParameter, _PredictorModel);
|
|
||||||
collection = faceRecognition.GetCollection(unknownImage, locations, includeFaceEncoding: true, includeFaceParts: true);
|
|
||||||
if (collection.Count == 0)
|
|
||||||
results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double[] rawEncoding;
|
|
||||||
Shared.Models.Face face;
|
|
||||||
Shared.Models.FaceEncoding convertedFaceEncoding;
|
|
||||||
foreach ((Location location, FaceRecognitionDotNet.FaceEncoding? faceEncoding, Dictionary<FacePart, FacePoint[]>? faceParts) in collection)
|
|
||||||
{
|
|
||||||
face = new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location);
|
|
||||||
if (faceEncoding is not null)
|
|
||||||
{
|
|
||||||
rawEncoding = faceEncoding.GetRawEncoding();
|
|
||||||
convertedFaceEncoding = new(rawEncoding, faceEncoding.Size);
|
|
||||||
face.SetFaceEncoding(convertedFaceEncoding);
|
|
||||||
}
|
|
||||||
if (faceParts is not null)
|
|
||||||
face.SetFaceParts(faceParts);
|
|
||||||
results.Add(face);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unknownImage.Dispose();
|
|
||||||
faceRecognition.Dispose();
|
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning restore CA1416
|
|
||||||
|
|
||||||
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
|
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
|
||||||
{
|
{
|
||||||
string[] segments = directory.Split(cei.Combined);
|
string[] segments = directory.Split(cei.Combined);
|
||||||
@ -322,6 +245,25 @@ public class D_Face : IFaceD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, DirectoryInfo directoryInfo)
|
||||||
|
{
|
||||||
|
string[] segments = directory.Split(cei.Combined);
|
||||||
|
string? checkDirectory = segments.Length == 1 ?
|
||||||
|
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
||||||
|
segments.Length == 2 ?
|
||||||
|
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
||||||
|
null;
|
||||||
|
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
||||||
|
{
|
||||||
|
string checkFile = Path.Combine(checkDirectory, fileName);
|
||||||
|
if (Directory.Exists(checkFile))
|
||||||
|
{
|
||||||
|
Directory.Move(checkFile, directoryInfo.FullName);
|
||||||
|
directoryInfo.Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public List<Shared.Models.Face> GetFaces(string outputResolution, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
|
public List<Shared.Models.Face> GetFaces(string outputResolution, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
|
||||||
{
|
{
|
||||||
List<Shared.Models.Face>? results;
|
List<Shared.Models.Face>? results;
|
||||||
@ -396,136 +338,190 @@ public class D_Face : IFaceD
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, DirectoryInfo directoryInfo)
|
private List<Shared.Models.Face> GetFaces(string outputResolution, string cResultsFullGroupDirectory, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<Location> locations)
|
||||||
{
|
{
|
||||||
string[] segments = directory.Split(cei.Combined);
|
if (_PropertyConfiguration.NumberOfJitters is null)
|
||||||
string? checkDirectory = segments.Length == 1 ?
|
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfJitters));
|
||||||
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
if (_PropertyConfiguration.NumberOfTimesToUpsample is null)
|
||||||
segments.Length == 2 ?
|
throw new NullReferenceException(nameof(_PropertyConfiguration.NumberOfTimesToUpsample));
|
||||||
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
List<Shared.Models.Face> results = [];
|
||||||
null;
|
FaceRecognitionDotNet.Image? unknownImage;
|
||||||
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
try
|
||||||
{
|
{
|
||||||
string checkFile = Path.Combine(checkDirectory, fileName);
|
if (mappingFromItem.ResizedFileHolder.ExtensionLowered != ".tif")
|
||||||
if (Directory.Exists(checkFile))
|
unknownImage = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Directory.Move(checkFile, directoryInfo.FullName);
|
int outputQuality = 100;
|
||||||
directoryInfo.Refresh();
|
string extension = ".png";
|
||||||
|
string file = Path.Combine(cResultsFullGroupDirectory, $"{mappingFromItem.ResizedFileHolder.Name}{extension}");
|
||||||
|
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(extension, outputQuality);
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
System.Drawing.Image image = System.Drawing.Image.FromFile(mappingFromItem.ResizedFileHolder.FullName);
|
||||||
|
image.Save(Path.Combine(cResultsFullGroupDirectory, $"{mappingFromItem.ResizedFileHolder.Name}{filenameExtension}"), imageCodecInfo, encoderParameters);
|
||||||
|
image.Dispose();
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
unknownImage = FaceRecognition.LoadImageFile(file);
|
||||||
|
File.Delete(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
catch (Exception)
|
||||||
|
{ unknownImage = null; }
|
||||||
public List<(Shared.Models.Face, FileHolder?, string, bool)> SaveFaces(FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces)
|
if (unknownImage is not null)
|
||||||
{
|
|
||||||
List<(Shared.Models.Face, FileHolder?, string, bool Save)> results = [];
|
|
||||||
bool save;
|
|
||||||
FileInfo fileInfo;
|
|
||||||
FileHolder fileHolder;
|
|
||||||
string deterministicHashCodeKey;
|
|
||||||
string fileName = mappingFromItem.FilePath.NameWithoutExtension;
|
|
||||||
string[] changesFrom = [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();
|
|
||||||
CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
|
|
||||||
string directory = _ResultContentFileGroups[0][cei.Enum][cei.Index];
|
|
||||||
DirectoryInfo directoryInfo = new(Path.Combine(directory, fileName));
|
|
||||||
MoveIf(fileName, cei, directory, directoryInfo);
|
|
||||||
foreach (Shared.Models.Face face in faces)
|
|
||||||
{
|
{
|
||||||
save = false;
|
(int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation) = Resize.Models.Stateless.Methods.IResize.Get(outputResolution, outputResolutionToResize);
|
||||||
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
|
List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
|
||||||
|
FaceRecognition faceRecognition = new(_PropertyConfiguration.NumberOfJitters.Value, _PropertyConfiguration.NumberOfTimesToUpsample.Value, _Model, _ModelParameter, _PredictorModel);
|
||||||
|
collection = faceRecognition.GetCollection(unknownImage, locations, includeFaceEncoding: true, includeFaceParts: true);
|
||||||
|
if (collection.Count == 0)
|
||||||
|
results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null));
|
||||||
|
else
|
||||||
{
|
{
|
||||||
results.Add(new(face, null, string.Empty, save));
|
double[] rawEncoding;
|
||||||
continue;
|
Shared.Models.Face face;
|
||||||
|
Shared.Models.FaceEncoding convertedFaceEncoding;
|
||||||
|
foreach ((Location location, FaceRecognitionDotNet.FaceEncoding? faceEncoding, Dictionary<FacePart, FacePoint[]>? faceParts) in collection)
|
||||||
|
{
|
||||||
|
face = new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location);
|
||||||
|
if (faceEncoding is not null)
|
||||||
|
{
|
||||||
|
rawEncoding = faceEncoding.GetRawEncoding();
|
||||||
|
convertedFaceEncoding = new(rawEncoding, faceEncoding.Size);
|
||||||
|
face.SetFaceEncoding(convertedFaceEncoding);
|
||||||
|
}
|
||||||
|
if (faceParts is not null)
|
||||||
|
face.SetFaceParts(faceParts);
|
||||||
|
results.Add(face);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(filePath, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
|
unknownImage.Dispose();
|
||||||
fileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, $"{deterministicHashCodeKey}{mappingFromItem.FilePath.ExtensionLowered}{_FileNameExtension}"));
|
faceRecognition.Dispose();
|
||||||
fileHolder = FileHolder.Get(fileInfo);
|
|
||||||
if (!directoryInfo.Exists)
|
|
||||||
save = true;
|
|
||||||
else if (_OverrideForFaceImages)
|
|
||||||
save = true;
|
|
||||||
else if (!fileHolder.Exists)
|
|
||||||
save = true;
|
|
||||||
else if (_CheckDFaceAndUpWriteDates && dateTimes.Count > 0 && dateTimes.Max() > fileInfo.LastWriteTime)
|
|
||||||
save = true;
|
|
||||||
results.Add(new(face, fileHolder, Path.Combine(directoryInfo.FullName, $"{deterministicHashCodeKey}{mappingFromItem.FilePath.ExtensionLowered}{_HiddenFileNameExtension}"), save));
|
|
||||||
}
|
|
||||||
if (results.Any(l => l.Save))
|
|
||||||
{
|
|
||||||
if (!directoryInfo.Exists)
|
|
||||||
_ = Directory.CreateDirectory(directoryInfo.FullName);
|
|
||||||
SaveFaces(mappingFromItem.ResizedFileHolder, exifDirectory, results);
|
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CA1416
|
private static (Model model, PredictorModel predictorModel, ModelParameter modelParameter) GetModel(string modelDirectory, string modelName, string predictorModelName)
|
||||||
|
|
||||||
private static (string?, string?) Get(string? json)
|
|
||||||
{
|
{
|
||||||
string? model;
|
(Model, PredictorModel, ModelParameter) result;
|
||||||
string? maker;
|
Array array;
|
||||||
FaceFile? faceFile = json is null ? null : JsonSerializer.Deserialize(json, FaceFileGenerationContext.Default.FaceFile);
|
Model? model = null;
|
||||||
if (faceFile is null || faceFile.Location is null)
|
array = Enum.GetValues<Model>();
|
||||||
(maker, model) = (null, null);
|
PredictorModel? predictorModel = null;
|
||||||
else
|
foreach (Model check in array)
|
||||||
(maker, model) = (faceFile.Maker, faceFile.Model);
|
{
|
||||||
return (maker, model);
|
if (modelName.Contains(check.ToString()))
|
||||||
|
{
|
||||||
|
model = check;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (model is null)
|
||||||
|
throw new Exception("Destination directory must have Model name!");
|
||||||
|
model = model.Value;
|
||||||
|
array = Enum.GetValues<PredictorModel>();
|
||||||
|
foreach (PredictorModel check in array)
|
||||||
|
{
|
||||||
|
if (predictorModelName.Contains(check.ToString()))
|
||||||
|
{
|
||||||
|
predictorModel = check;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (predictorModel is null)
|
||||||
|
throw new Exception("Destination directory must have Predictor Model name!");
|
||||||
|
predictorModel = predictorModel.Value;
|
||||||
|
ModelParameter modelParameter = new()
|
||||||
|
{
|
||||||
|
CnnFaceDetectorModel = File.ReadAllBytes(Path.Combine(modelDirectory, "mmod_human_face_detector.dat")),
|
||||||
|
FaceRecognitionModel = File.ReadAllBytes(Path.Combine(modelDirectory, "dlib_face_recognition_resnet_model_v1.dat")),
|
||||||
|
PosePredictor5FaceLandmarksModel = File.ReadAllBytes(Path.Combine(modelDirectory, "shape_predictor_5_face_landmarks.dat")),
|
||||||
|
PosePredictor68FaceLandmarksModel = File.ReadAllBytes(Path.Combine(modelDirectory, "shape_predictor_68_face_landmarks.dat"))
|
||||||
|
};
|
||||||
|
result = new(model.Value, predictorModel.Value, modelParameter);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFaceD.ReSaveFace(ExifDirectory exifDirectory, FilePath filePath, Shared.Models.Face face, bool mappedFile)
|
private void SaveFaces(FileHolder resizedFileHolder, ExifDirectory exifDirectory, List<(Shared.Models.Face, FileHolder?, string, bool)> collection)
|
||||||
{
|
{
|
||||||
FileInfo fileInfo = new(filePath.FullName);
|
int width;
|
||||||
if (fileInfo.Exists)
|
int height;
|
||||||
|
Bitmap bitmap;
|
||||||
|
short type = 2;
|
||||||
|
FaceFile faceFile;
|
||||||
|
Graphics graphics;
|
||||||
|
Location? location;
|
||||||
|
Rectangle rectangle;
|
||||||
|
string faceFileJson;
|
||||||
|
string faceEncodingJson;
|
||||||
|
PropertyItem? propertyItem;
|
||||||
|
string? maker = IMetadata.GetMaker(exifDirectory);
|
||||||
|
string? model = IMetadata.GetModel(exifDirectory);
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
using Bitmap source = new(resizedFileHolder.FullName);
|
||||||
|
MetadataExtractor.GeoLocation? geoLocation = IMetadata.GeoLocation(exifDirectory);
|
||||||
|
const int artist = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist; // 315
|
||||||
|
const int userComment = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagUserComment;
|
||||||
|
foreach ((Shared.Models.Face face, FileHolder? fileHolder, string fileName, bool save) in collection)
|
||||||
{
|
{
|
||||||
string? json;
|
if (!save)
|
||||||
short type = 2;
|
continue;
|
||||||
string? model;
|
if (fileHolder is null)
|
||||||
string? maker;
|
continue;
|
||||||
string checkFile = $"{filePath.FullName}.exif";
|
if (face.FaceEncoding is null || face?.Location is null || face?.OutputResolution is null)
|
||||||
const int artist = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist;
|
continue;
|
||||||
// const int author = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagWinAuthor; // 40093
|
if (_OverrideForFaceImages && fileHolder.Exists)
|
||||||
if (mappedFile)
|
|
||||||
{
|
{
|
||||||
json = IMetadata.GetOutputResolution(exifDirectory);
|
IFaceD dFace = this;
|
||||||
if (json is not null && json.Contains(nameof(DateTime)))
|
FilePath filePath = FilePath.Get(_PropertyConfiguration, fileHolder, index: null);
|
||||||
return;
|
dFace.ReSaveFace(exifDirectory, filePath, face, mappedFile: false);
|
||||||
(maker, model) = Get(json);
|
continue;
|
||||||
}
|
}
|
||||||
else
|
location = Shared.Models.Stateless.Methods.ILocation.GetLocation(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, source.Height, source.Width, collection.Count);
|
||||||
|
if (location is null)
|
||||||
|
continue;
|
||||||
|
width = location.Right - location.Left;
|
||||||
|
height = location.Bottom - location.Top;
|
||||||
|
faceEncodingJson = JsonSerializer.Serialize(face.FaceEncoding);
|
||||||
|
rectangle = new Rectangle(location.Left, location.Top, width, height);
|
||||||
|
faceFile = new(face.Mapping?.MappingFromLocation?.AreaPermyriad,
|
||||||
|
face.Mapping?.MappingFromLocation?.ConfidencePercent,
|
||||||
|
geoLocation?.ToDmsString(),
|
||||||
|
face.DateTime,
|
||||||
|
null,
|
||||||
|
face.FaceParts,
|
||||||
|
face.Location,
|
||||||
|
maker,
|
||||||
|
null,
|
||||||
|
model,
|
||||||
|
face.OutputResolution);
|
||||||
|
faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile);
|
||||||
|
using (bitmap = new(width, height))
|
||||||
{
|
{
|
||||||
maker = IMetadata.GetMaker(exifDirectory);
|
using (graphics = Graphics.FromImage(bitmap))
|
||||||
model = IMetadata.GetModel(exifDirectory);
|
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
|
||||||
ExifDirectory? faceExifDirectory = IMetadata.GetExifDirectory(filePath);
|
propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(_ConstructorInfo, artist, type, faceFileJson);
|
||||||
json = IMetadata.GetOutputResolution(faceExifDirectory);
|
bitmap.SetPropertyItem(propertyItem);
|
||||||
if (json is not null && json.Contains(nameof(DateTime)))
|
propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(_ConstructorInfo, userComment, type, faceEncodingJson);
|
||||||
return;
|
bitmap.SetPropertyItem(propertyItem);
|
||||||
|
bitmap.Save(fileHolder.FullName, _ImageCodecInfo, _EncoderParameters);
|
||||||
}
|
}
|
||||||
MetadataExtractor.GeoLocation? geoLocation = IMetadata.GeoLocation(exifDirectory);
|
if (File.Exists(fileName))
|
||||||
FaceFile faceFile = new(face.Mapping?.MappingFromLocation?.AreaPermyriad,
|
File.Delete(fileName);
|
||||||
face.Mapping?.MappingFromLocation?.ConfidencePercent,
|
location = Shared.Models.Stateless.Methods.ILocation.GetLocation(_FaceDistanceHiddenImageFactor, face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, source.Height, source.Width, collection.Count);
|
||||||
geoLocation?.ToDmsString(),
|
if (location is null)
|
||||||
face.DateTime,
|
continue;
|
||||||
null,
|
width = location.Right - location.Left;
|
||||||
face.FaceParts,
|
height = location.Bottom - location.Top;
|
||||||
face.Location,
|
rectangle = new Rectangle(location.Left, location.Top, width, height);
|
||||||
maker,
|
using (bitmap = new(width, height))
|
||||||
null,
|
{
|
||||||
model,
|
using (graphics = Graphics.FromImage(bitmap))
|
||||||
face.OutputResolution);
|
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
|
||||||
string faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile);
|
bitmap.Save(fileName, _HiddenImageCodecInfo, _HiddenEncoderParameters);
|
||||||
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, [], null) ?? throw new Exception();
|
}
|
||||||
PropertyItem? propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(constructorInfo, artist, type, faceFileJson);
|
#pragma warning restore CA1416
|
||||||
Bitmap bitmap = new(fileInfo.FullName);
|
File.SetAttributes(fileName, FileAttributes.Hidden);
|
||||||
bitmap.SetPropertyItem(propertyItem);
|
|
||||||
bitmap.Save(checkFile);
|
|
||||||
bitmap.Dispose();
|
|
||||||
File.SetLastWriteTime(checkFile, fileInfo.LastWriteTime);
|
|
||||||
File.Delete(fileInfo.FullName);
|
|
||||||
File.Move(checkFile, fileInfo.FullName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning restore CA1416
|
|
||||||
|
|
||||||
}
|
}
|
@ -65,160 +65,18 @@ public class D2_FaceParts
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum)
|
public void SaveFaceLandmarkImages(string d2ResultsFullGroupDirectory, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces)
|
||||||
{
|
{
|
||||||
xMinimum = points[0].X;
|
bool any = false;
|
||||||
xMaximum = xMinimum;
|
foreach (Shared.Models.Face face in faces)
|
||||||
yMinimum = points[0].Y;
|
|
||||||
yMaximum = yMinimum;
|
|
||||||
foreach (PointF point in points)
|
|
||||||
{
|
{
|
||||||
if (xMinimum > point.X)
|
if (face.Location is null || face.FaceEncoding is null || face.FaceParts is null || face.FaceParts.Count == 0)
|
||||||
xMinimum = point.X;
|
|
||||||
if (xMaximum < point.X)
|
|
||||||
xMaximum = point.X;
|
|
||||||
if (yMinimum > point.Y)
|
|
||||||
yMinimum = point.Y;
|
|
||||||
if (yMaximum < point.Y)
|
|
||||||
yMaximum = point.Y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning disable CA1416
|
|
||||||
|
|
||||||
private static Bitmap RotateBitmap(Bitmap bitmap, float angle)
|
|
||||||
{
|
|
||||||
Bitmap result;
|
|
||||||
#if Linux
|
|
||||||
throw new Exception("Built on Linux!");
|
|
||||||
#elif OSX
|
|
||||||
throw new Exception("Built on macOS!");
|
|
||||||
#elif Windows
|
|
||||||
// Make save Matrix to represent rotation
|
|
||||||
// by this angle.
|
|
||||||
Matrix rotate_at_origin = new();
|
|
||||||
rotate_at_origin.Rotate(angle);
|
|
||||||
|
|
||||||
// Rotate the image's corners to see how big
|
|
||||||
// it will be after rotation.
|
|
||||||
PointF[] points =
|
|
||||||
[
|
|
||||||
new(0, 0),
|
|
||||||
new(bitmap.Width, 0),
|
|
||||||
new(bitmap.Width, bitmap.Height),
|
|
||||||
new(0, bitmap.Height),
|
|
||||||
];
|
|
||||||
rotate_at_origin.TransformPoints(points);
|
|
||||||
float xMinimum, xMaximum, yMinimum, yMaximum;
|
|
||||||
GetPointBounds(points, out xMinimum, out xMaximum, out yMinimum, out yMaximum);
|
|
||||||
|
|
||||||
// Make save bitmap to hold the rotated result.
|
|
||||||
int wid = (int)Math.Round(xMaximum - xMinimum);
|
|
||||||
int hgt = (int)Math.Round(yMaximum - yMinimum);
|
|
||||||
result = new Bitmap(wid, hgt);
|
|
||||||
|
|
||||||
// Create the real rotation transformation.
|
|
||||||
Matrix rotate_at_center = new();
|
|
||||||
rotate_at_center.RotateAt(angle,
|
|
||||||
new PointF(wid / 2f, hgt / 2f));
|
|
||||||
|
|
||||||
// Draw the image onto the new bitmap rotated.
|
|
||||||
using (Graphics gr = Graphics.FromImage(result))
|
|
||||||
{
|
|
||||||
// Use smooth image interpolation.
|
|
||||||
gr.InterpolationMode = InterpolationMode.High;
|
|
||||||
|
|
||||||
// Clear with the color in the image's upper left corner.
|
|
||||||
gr.Clear(bitmap.GetPixel(0, 0));
|
|
||||||
|
|
||||||
// For debugging. (It's easier to see the background.)
|
|
||||||
// gr.Clear(Color.LightBlue);
|
|
||||||
|
|
||||||
// Set up the transformation to rotate.
|
|
||||||
gr.Transform = rotate_at_center;
|
|
||||||
|
|
||||||
// Draw the image centered on the bitmap.
|
|
||||||
int x = (wid - bitmap.Width) / 2;
|
|
||||||
int y = (hgt - bitmap.Height) / 2;
|
|
||||||
gr.DrawImage(bitmap, x, y);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// Return the result bitmap.
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Bitmap RotateBitmap(Image image, float angle)
|
|
||||||
{
|
|
||||||
Bitmap result;
|
|
||||||
Bitmap bitmap = new(image);
|
|
||||||
result = RotateBitmap(bitmap, angle);
|
|
||||||
bitmap?.Dispose();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveRotated(MappingFromItem mappingFromItem, List<(Shared.Models.Face, string, string)> collection)
|
|
||||||
{
|
|
||||||
double? α;
|
|
||||||
Bitmap rotated;
|
|
||||||
foreach ((Shared.Models.Face face, string _, string rotatedFileName) in collection)
|
|
||||||
{
|
|
||||||
if (face.FaceParts is null)
|
|
||||||
continue;
|
continue;
|
||||||
(_, α) = Shared.Models.Stateless.Methods.IFace.GetEyeα(face.FaceParts);
|
if (!any)
|
||||||
if (α is null)
|
any = true;
|
||||||
continue;
|
|
||||||
using Image image = Image.FromFile(mappingFromItem.ResizedFileHolder.FullName);
|
|
||||||
rotated = RotateBitmap(image, (float)α.Value);
|
|
||||||
if (rotated is not null)
|
|
||||||
{
|
|
||||||
rotated.Save(rotatedFileName, _ImageCodecInfo, _EncoderParameters);
|
|
||||||
rotated.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetSeasonDirectory(string d2ResultsFullGroupDirectory, MappingFromItem mappingFromItem, bool any)
|
|
||||||
{
|
|
||||||
string result;
|
|
||||||
string minimumDateYear = mappingFromItem.MinimumDateTime.ToString("yyyy");
|
|
||||||
DateTime dateTime = mappingFromItem.DateTimeOriginal is null ? mappingFromItem.MinimumDateTime : mappingFromItem.DateTimeOriginal.Value;
|
|
||||||
(int season, string seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
|
|
||||||
string year = mappingFromItem.DateTimeOriginal is null ? $"{minimumDateYear[1..]}{minimumDateYear[0]}" : mappingFromItem.DateTimeOriginal.Value.ToString("yyyy");
|
|
||||||
string directory = Path.Combine(d2ResultsFullGroupDirectory, $"[{_PropertyConfiguration.ResultContent}]", $"{year}.{season} {seasonName}");
|
|
||||||
result = any ? Path.Combine(directory, "---") : Path.Combine(directory, "Complete");
|
|
||||||
if (!Directory.Exists(result))
|
|
||||||
_ = Directory.CreateDirectory(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveImage(MappingFromItem mappingFromItem, string directory, Image image, List<FaceFile> faceFiles)
|
|
||||||
{
|
|
||||||
short type = 2;
|
|
||||||
string faceFileJson;
|
|
||||||
PropertyItem? propertyItem;
|
|
||||||
const int artist = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist; // 315
|
|
||||||
string fileName = Path.Combine(directory, $"{mappingFromItem.FilePath.Name}{_FileNameExtension}");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (int propertyId in image.PropertyIdList)
|
|
||||||
{
|
|
||||||
if (propertyId == MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation)
|
|
||||||
continue;
|
|
||||||
image.RemovePropertyItem(propertyId);
|
|
||||||
}
|
|
||||||
faceFileJson = JsonSerializer.Serialize(faceFiles.ToArray(), FaceFileCollectionGenerationContext.Default.FaceFileArray);
|
|
||||||
propertyItem = IProperty.GetPropertyItem(_ConstructorInfo, artist, type, faceFileJson);
|
|
||||||
image.SetPropertyItem(propertyItem);
|
|
||||||
image.Save(fileName, _ImageCodecInfo, _EncoderParameters);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (ex is not null && !string.IsNullOrEmpty(fileName) && File.Exists(fileName))
|
|
||||||
File.Delete(fileName);
|
|
||||||
faceFileJson = JsonSerializer.Serialize(faceFiles.ToArray(), FaceFileCollectionGenerationContext.Default.FaceFileArray);
|
|
||||||
if (!string.IsNullOrEmpty(faceFileJson))
|
|
||||||
File.WriteAllText($"{fileName}.json", faceFileJson);
|
|
||||||
}
|
}
|
||||||
|
if (any)
|
||||||
|
SaveAllFaceParts(d2ResultsFullGroupDirectory, mappingFromItem, exifDirectory, faces);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveAllFaceParts(string d2ResultsFullGroupDirectory, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces)
|
private void SaveAllFaceParts(string d2ResultsFullGroupDirectory, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces)
|
||||||
@ -237,6 +95,7 @@ public class D2_FaceParts
|
|||||||
string? maker = IMetadata.GetMaker(exifDirectory);
|
string? maker = IMetadata.GetMaker(exifDirectory);
|
||||||
string? model = IMetadata.GetModel(exifDirectory);
|
string? model = IMetadata.GetModel(exifDirectory);
|
||||||
MetadataExtractor.GeoLocation? geoLocation = IMetadata.GeoLocation(exifDirectory);
|
MetadataExtractor.GeoLocation? geoLocation = IMetadata.GeoLocation(exifDirectory);
|
||||||
|
#pragma warning disable CA1416
|
||||||
using Image image = Image.FromFile(mappingFromItem.ResizedFileHolder.FullName);
|
using Image image = Image.FromFile(mappingFromItem.ResizedFileHolder.FullName);
|
||||||
using Graphics graphics = Graphics.FromImage(image);
|
using Graphics graphics = Graphics.FromImage(image);
|
||||||
foreach (Shared.Models.Face face in faces)
|
foreach (Shared.Models.Face face in faces)
|
||||||
@ -277,95 +136,11 @@ public class D2_FaceParts
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = graphics.Save();
|
_ = graphics.Save();
|
||||||
|
#pragma warning restore CA1416
|
||||||
string directory = GetSeasonDirectory(d2ResultsFullGroupDirectory, mappingFromItem, any);
|
string directory = GetSeasonDirectory(d2ResultsFullGroupDirectory, mappingFromItem, any);
|
||||||
SaveImage(mappingFromItem, directory, image, faceFiles);
|
SaveImage(mappingFromItem, directory, image, faceFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveImage(string fileName, Image image, FaceFile faceFile)
|
|
||||||
{
|
|
||||||
short type = 2;
|
|
||||||
string faceFileJson;
|
|
||||||
PropertyItem? propertyItem;
|
|
||||||
const int artist = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist; // 315
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (int propertyId in image.PropertyIdList)
|
|
||||||
{
|
|
||||||
if (propertyId == MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation)
|
|
||||||
continue;
|
|
||||||
image.RemovePropertyItem(propertyId);
|
|
||||||
}
|
|
||||||
faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile);
|
|
||||||
propertyItem = IProperty.GetPropertyItem(_ConstructorInfo, artist, type, faceFileJson);
|
|
||||||
image.SetPropertyItem(propertyItem);
|
|
||||||
image.Save(fileName, _ImageCodecInfo, _EncoderParameters);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (ex is not null && !string.IsNullOrEmpty(fileName) && File.Exists(fileName))
|
|
||||||
File.Delete(fileName);
|
|
||||||
faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile);
|
|
||||||
if (!string.IsNullOrEmpty(faceFileJson))
|
|
||||||
File.WriteAllText($"{fileName}.json", faceFileJson);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveFaceParts(MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<(Shared.Models.Face, string, string)> collection)
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
Brush brush;
|
|
||||||
int pointSize;
|
|
||||||
FaceFile faceFile;
|
|
||||||
MappingFromPerson? mappingFromPerson;
|
|
||||||
string? maker = IMetadata.GetMaker(exifDirectory);
|
|
||||||
string? model = IMetadata.GetModel(exifDirectory);
|
|
||||||
MetadataExtractor.GeoLocation? geoLocation = IMetadata.GeoLocation(exifDirectory);
|
|
||||||
foreach ((Shared.Models.Face face, string fileName, string _) in collection)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (face.Location is null || face.FaceEncoding is null || face.FaceParts is null || face.FaceParts.Count == 0)
|
|
||||||
continue;
|
|
||||||
using Image image = Image.FromFile(mappingFromItem.ResizedFileHolder.FullName);
|
|
||||||
mappingFromPerson = face.Mapping?.MappingFromPerson;
|
|
||||||
brush = mappingFromPerson is null ? Brushes.Red : Brushes.GreenYellow;
|
|
||||||
faceFile = new(face.Mapping?.MappingFromLocation?.AreaPermyriad,
|
|
||||||
face.Mapping?.MappingFromLocation?.ConfidencePercent,
|
|
||||||
geoLocation?.ToDmsString(),
|
|
||||||
face.DateTime,
|
|
||||||
face.FaceEncoding,
|
|
||||||
face.FaceParts,
|
|
||||||
face.Location,
|
|
||||||
maker,
|
|
||||||
mappingFromPerson,
|
|
||||||
model,
|
|
||||||
face.OutputResolution);
|
|
||||||
using Graphics graphics = Graphics.FromImage(image);
|
|
||||||
pointSize = GetPointSize(face.FaceParts, defaultPointSize: 2);
|
|
||||||
foreach ((FacePart facePart, FacePoint[] facePoints) in face.FaceParts)
|
|
||||||
{
|
|
||||||
foreach (FacePoint facePoint in facePoints)
|
|
||||||
graphics.FillEllipse(brush, facePoint.X - pointSize, facePoint.Y - pointSize, pointSize * 2, pointSize * 2);
|
|
||||||
if (facePart == FacePart.Chin)
|
|
||||||
continue;
|
|
||||||
if (facePoints.Length < 3)
|
|
||||||
continue;
|
|
||||||
x = (int)(from l in facePoints select l.X).Average();
|
|
||||||
y = (int)(from l in facePoints select l.Y).Average();
|
|
||||||
graphics.FillEllipse(Brushes.Purple, x - pointSize, y - pointSize, pointSize * 2, pointSize * 2);
|
|
||||||
}
|
|
||||||
_ = graphics.Save();
|
|
||||||
SaveImage(fileName, image, faceFile);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
if (File.Exists(fileName))
|
|
||||||
File.Delete(fileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetPointSize(Dictionary<FacePart, FacePoint[]> faceParts, int defaultPointSize)
|
private int GetPointSize(Dictionary<FacePart, FacePoint[]> faceParts, int defaultPointSize)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
@ -382,28 +157,53 @@ public class D2_FaceParts
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning restore CA1416
|
private string GetSeasonDirectory(string d2ResultsFullGroupDirectory, MappingFromItem mappingFromItem, bool any)
|
||||||
|
|
||||||
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, DirectoryInfo directoryInfo)
|
|
||||||
{
|
{
|
||||||
string[] segments = directory.Split(cei.Combined);
|
string result;
|
||||||
string? checkDirectory = segments.Length == 1 ?
|
string minimumDateYear = mappingFromItem.MinimumDateTime.ToString("yyyy");
|
||||||
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
DateTime dateTime = mappingFromItem.DateTimeOriginal is null ? mappingFromItem.MinimumDateTime : mappingFromItem.DateTimeOriginal.Value;
|
||||||
segments.Length == 2 ?
|
(int season, string seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
|
||||||
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
string year = mappingFromItem.DateTimeOriginal is null ? $"{minimumDateYear[1..]}{minimumDateYear[0]}" : mappingFromItem.DateTimeOriginal.Value.ToString("yyyy");
|
||||||
null;
|
string directory = Path.Combine(d2ResultsFullGroupDirectory, $"[{_PropertyConfiguration.ResultContent}]", $"{year}.{season} {seasonName}");
|
||||||
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
result = any ? Path.Combine(directory, "---") : Path.Combine(directory, "Complete");
|
||||||
|
if (!Directory.Exists(result))
|
||||||
|
_ = Directory.CreateDirectory(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveImage(MappingFromItem mappingFromItem, string directory, Image image, List<FaceFile> faceFiles)
|
||||||
|
{
|
||||||
|
short type = 2;
|
||||||
|
string faceFileJson;
|
||||||
|
PropertyItem? propertyItem;
|
||||||
|
const int artist = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist; // 315
|
||||||
|
string fileName = Path.Combine(directory, $"{mappingFromItem.FilePath.Name}{_FileNameExtension}");
|
||||||
|
try
|
||||||
{
|
{
|
||||||
string checkFile = Path.Combine(checkDirectory, fileName);
|
#pragma warning disable CA1416
|
||||||
if (Directory.Exists(checkFile))
|
foreach (int propertyId in image.PropertyIdList)
|
||||||
{
|
{
|
||||||
Directory.Move(checkFile, directoryInfo.FullName);
|
if (propertyId == MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation)
|
||||||
directoryInfo.Refresh();
|
continue;
|
||||||
|
image.RemovePropertyItem(propertyId);
|
||||||
}
|
}
|
||||||
|
faceFileJson = JsonSerializer.Serialize(faceFiles.ToArray(), FaceFileCollectionGenerationContext.Default.FaceFileArray);
|
||||||
|
propertyItem = IProperty.GetPropertyItem(_ConstructorInfo, artist, type, faceFileJson);
|
||||||
|
image.SetPropertyItem(propertyItem);
|
||||||
|
image.Save(fileName, _ImageCodecInfo, _EncoderParameters);
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (ex is not null && !string.IsNullOrEmpty(fileName) && File.Exists(fileName))
|
||||||
|
File.Delete(fileName);
|
||||||
|
faceFileJson = JsonSerializer.Serialize(faceFiles.ToArray(), FaceFileCollectionGenerationContext.Default.FaceFileArray);
|
||||||
|
if (!string.IsNullOrEmpty(faceFileJson))
|
||||||
|
File.WriteAllText($"{fileName}.json", faceFileJson);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveFaceLandmarkImages(Property.Models.Configuration configuration, string d2ResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces, bool saveRotated)
|
public void SaveFaceLandmarkImages(Configuration configuration, string d2ResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces, bool saveRotated)
|
||||||
{
|
{
|
||||||
FileInfo fileInfo;
|
FileInfo fileInfo;
|
||||||
bool check = false;
|
bool check = false;
|
||||||
@ -461,6 +261,118 @@ public class D2_FaceParts
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, DirectoryInfo directoryInfo)
|
||||||
|
{
|
||||||
|
string[] segments = directory.Split(cei.Combined);
|
||||||
|
string? checkDirectory = segments.Length == 1 ?
|
||||||
|
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
||||||
|
segments.Length == 2 ?
|
||||||
|
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
||||||
|
null;
|
||||||
|
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
||||||
|
{
|
||||||
|
string checkFile = Path.Combine(checkDirectory, fileName);
|
||||||
|
if (Directory.Exists(checkFile))
|
||||||
|
{
|
||||||
|
Directory.Move(checkFile, directoryInfo.FullName);
|
||||||
|
directoryInfo.Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bitmap RotateBitmap(Image image, float angle)
|
||||||
|
{
|
||||||
|
Bitmap result;
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
Bitmap bitmap = new(image);
|
||||||
|
result = RotateBitmap(bitmap, angle);
|
||||||
|
bitmap?.Dispose();
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bitmap RotateBitmap(Bitmap bitmap, float angle)
|
||||||
|
{
|
||||||
|
Bitmap result;
|
||||||
|
#if Linux
|
||||||
|
throw new Exception("Built on Linux!");
|
||||||
|
#elif OSX
|
||||||
|
throw new Exception("Built on macOS!");
|
||||||
|
#elif Windows
|
||||||
|
// Make save Matrix to represent rotation
|
||||||
|
// by this angle.
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
Matrix rotate_at_origin = new();
|
||||||
|
rotate_at_origin.Rotate(angle);
|
||||||
|
|
||||||
|
// Rotate the image's corners to see how big
|
||||||
|
// it will be after rotation.
|
||||||
|
PointF[] points =
|
||||||
|
[
|
||||||
|
new(0, 0),
|
||||||
|
new(bitmap.Width, 0),
|
||||||
|
new(bitmap.Width, bitmap.Height),
|
||||||
|
new(0, bitmap.Height),
|
||||||
|
];
|
||||||
|
rotate_at_origin.TransformPoints(points);
|
||||||
|
float xMinimum, xMaximum, yMinimum, yMaximum;
|
||||||
|
GetPointBounds(points, out xMinimum, out xMaximum, out yMinimum, out yMaximum);
|
||||||
|
|
||||||
|
// Make save bitmap to hold the rotated result.
|
||||||
|
int wid = (int)Math.Round(xMaximum - xMinimum);
|
||||||
|
int hgt = (int)Math.Round(yMaximum - yMinimum);
|
||||||
|
result = new Bitmap(wid, hgt);
|
||||||
|
|
||||||
|
// Create the real rotation transformation.
|
||||||
|
Matrix rotate_at_center = new();
|
||||||
|
rotate_at_center.RotateAt(angle,
|
||||||
|
new PointF(wid / 2f, hgt / 2f));
|
||||||
|
|
||||||
|
// Draw the image onto the new bitmap rotated.
|
||||||
|
using (Graphics gr = Graphics.FromImage(result))
|
||||||
|
{
|
||||||
|
// Use smooth image interpolation.
|
||||||
|
gr.InterpolationMode = InterpolationMode.High;
|
||||||
|
|
||||||
|
// Clear with the color in the image's upper left corner.
|
||||||
|
gr.Clear(bitmap.GetPixel(0, 0));
|
||||||
|
|
||||||
|
// For debugging. (It's easier to see the background.)
|
||||||
|
// gr.Clear(Color.LightBlue);
|
||||||
|
|
||||||
|
// Set up the transformation to rotate.
|
||||||
|
gr.Transform = rotate_at_center;
|
||||||
|
|
||||||
|
// Draw the image centered on the bitmap.
|
||||||
|
int x = (wid - bitmap.Width) / 2;
|
||||||
|
int y = (hgt - bitmap.Height) / 2;
|
||||||
|
gr.DrawImage(bitmap, x, y);
|
||||||
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
#endif
|
||||||
|
// Return the result bitmap.
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum)
|
||||||
|
{
|
||||||
|
xMinimum = points[0].X;
|
||||||
|
xMaximum = xMinimum;
|
||||||
|
yMinimum = points[0].Y;
|
||||||
|
yMaximum = yMinimum;
|
||||||
|
foreach (PointF point in points)
|
||||||
|
{
|
||||||
|
if (xMinimum > point.X)
|
||||||
|
xMinimum = point.X;
|
||||||
|
if (xMaximum < point.X)
|
||||||
|
xMaximum = point.X;
|
||||||
|
if (yMinimum > point.Y)
|
||||||
|
yMinimum = point.Y;
|
||||||
|
if (yMaximum < point.Y)
|
||||||
|
yMaximum = point.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static bool GetNotMapped(string facePartsCollectionDirectory, List<(Shared.Models.Face Face, FileHolder?, string, bool)> faceCollection)
|
private static bool GetNotMapped(string facePartsCollectionDirectory, List<(Shared.Models.Face Face, FileHolder?, string, bool)> faceCollection)
|
||||||
{
|
{
|
||||||
bool results = false;
|
bool results = false;
|
||||||
@ -494,18 +406,116 @@ public class D2_FaceParts
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveFaceLandmarkImages(string d2ResultsFullGroupDirectory, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<Shared.Models.Face> faces)
|
private void SaveImage(string fileName, Image image, FaceFile faceFile)
|
||||||
{
|
{
|
||||||
bool any = false;
|
short type = 2;
|
||||||
foreach (Shared.Models.Face face in faces)
|
string faceFileJson;
|
||||||
|
PropertyItem? propertyItem;
|
||||||
|
const int artist = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist; // 315
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (face.Location is null || face.FaceEncoding is null || face.FaceParts is null || face.FaceParts.Count == 0)
|
#pragma warning disable CA1416
|
||||||
continue;
|
foreach (int propertyId in image.PropertyIdList)
|
||||||
if (!any)
|
{
|
||||||
any = true;
|
if (propertyId == MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation)
|
||||||
|
continue;
|
||||||
|
image.RemovePropertyItem(propertyId);
|
||||||
|
}
|
||||||
|
faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile);
|
||||||
|
propertyItem = IProperty.GetPropertyItem(_ConstructorInfo, artist, type, faceFileJson);
|
||||||
|
image.SetPropertyItem(propertyItem);
|
||||||
|
image.Save(fileName, _ImageCodecInfo, _EncoderParameters);
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (ex is not null && !string.IsNullOrEmpty(fileName) && File.Exists(fileName))
|
||||||
|
File.Delete(fileName);
|
||||||
|
faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile);
|
||||||
|
if (!string.IsNullOrEmpty(faceFileJson))
|
||||||
|
File.WriteAllText($"{fileName}.json", faceFileJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveRotated(MappingFromItem mappingFromItem, List<(Shared.Models.Face, string, string)> collection)
|
||||||
|
{
|
||||||
|
double? α;
|
||||||
|
Bitmap rotated;
|
||||||
|
foreach ((Shared.Models.Face face, string _, string rotatedFileName) in collection)
|
||||||
|
{
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
if (face.FaceParts is null)
|
||||||
|
continue;
|
||||||
|
(_, α) = Shared.Models.Stateless.Methods.IFace.GetEyeα(face.FaceParts);
|
||||||
|
if (α is null)
|
||||||
|
continue;
|
||||||
|
using Image image = Image.FromFile(mappingFromItem.ResizedFileHolder.FullName);
|
||||||
|
rotated = RotateBitmap(image, (float)α.Value);
|
||||||
|
if (rotated is not null)
|
||||||
|
{
|
||||||
|
rotated.Save(rotatedFileName, _ImageCodecInfo, _EncoderParameters);
|
||||||
|
rotated.Dispose();
|
||||||
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveFaceParts(MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<(Shared.Models.Face, string, string)> collection)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
Brush brush;
|
||||||
|
int pointSize;
|
||||||
|
FaceFile faceFile;
|
||||||
|
MappingFromPerson? mappingFromPerson;
|
||||||
|
string? maker = IMetadata.GetMaker(exifDirectory);
|
||||||
|
string? model = IMetadata.GetModel(exifDirectory);
|
||||||
|
MetadataExtractor.GeoLocation? geoLocation = IMetadata.GeoLocation(exifDirectory);
|
||||||
|
foreach ((Shared.Models.Face face, string fileName, string _) in collection)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
if (face.Location is null || face.FaceEncoding is null || face.FaceParts is null || face.FaceParts.Count == 0)
|
||||||
|
continue;
|
||||||
|
using Image image = Image.FromFile(mappingFromItem.ResizedFileHolder.FullName);
|
||||||
|
mappingFromPerson = face.Mapping?.MappingFromPerson;
|
||||||
|
brush = mappingFromPerson is null ? Brushes.Red : Brushes.GreenYellow;
|
||||||
|
faceFile = new(face.Mapping?.MappingFromLocation?.AreaPermyriad,
|
||||||
|
face.Mapping?.MappingFromLocation?.ConfidencePercent,
|
||||||
|
geoLocation?.ToDmsString(),
|
||||||
|
face.DateTime,
|
||||||
|
face.FaceEncoding,
|
||||||
|
face.FaceParts,
|
||||||
|
face.Location,
|
||||||
|
maker,
|
||||||
|
mappingFromPerson,
|
||||||
|
model,
|
||||||
|
face.OutputResolution);
|
||||||
|
using Graphics graphics = Graphics.FromImage(image);
|
||||||
|
pointSize = GetPointSize(face.FaceParts, defaultPointSize: 2);
|
||||||
|
foreach ((FacePart facePart, FacePoint[] facePoints) in face.FaceParts)
|
||||||
|
{
|
||||||
|
foreach (FacePoint facePoint in facePoints)
|
||||||
|
graphics.FillEllipse(brush, facePoint.X - pointSize, facePoint.Y - pointSize, pointSize * 2, pointSize * 2);
|
||||||
|
if (facePart == FacePart.Chin)
|
||||||
|
continue;
|
||||||
|
if (facePoints.Length < 3)
|
||||||
|
continue;
|
||||||
|
x = (int)(from l in facePoints select l.X).Average();
|
||||||
|
y = (int)(from l in facePoints select l.Y).Average();
|
||||||
|
graphics.FillEllipse(Brushes.Purple, x - pointSize, y - pointSize, pointSize * 2, pointSize * 2);
|
||||||
|
}
|
||||||
|
_ = graphics.Save();
|
||||||
|
SaveImage(fileName, image, faceFile);
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
if (File.Exists(fileName))
|
||||||
|
File.Delete(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (any)
|
|
||||||
SaveAllFaceParts(d2ResultsFullGroupDirectory, mappingFromItem, exifDirectory, faces);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -25,327 +25,6 @@ internal abstract class DistanceLogic
|
|||||||
bool? IsLocationContainerDebugDirectory,
|
bool? IsLocationContainerDebugDirectory,
|
||||||
float? TotalDays);
|
float? TotalDays);
|
||||||
|
|
||||||
private static void MoveTo(string actionDirectory, TicksDirectory ticksDirectory, string directory, string personKeyFormatted, string yearDirectoryName, string alphaDirectoryName, string[] files, string[] facesFileNames)
|
|
||||||
{
|
|
||||||
string checkFile;
|
|
||||||
string actionDirectoryName = Path.GetFileName(actionDirectory);
|
|
||||||
string checkDirectory = actionDirectoryName.StartsWith("y", StringComparison.CurrentCultureIgnoreCase) ? Path.Combine(ticksDirectory.Directory, personKeyFormatted, yearDirectoryName, alphaDirectoryName) : Path.Combine(directory, actionDirectoryName);
|
|
||||||
if (!Directory.Exists(checkDirectory))
|
|
||||||
_ = Directory.CreateDirectory(checkDirectory);
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
if (facesFileNames.Contains(file))
|
|
||||||
{
|
|
||||||
checkFile = Path.Combine(checkDirectory, Path.GetFileName(file));
|
|
||||||
if (File.Exists(checkFile))
|
|
||||||
continue;
|
|
||||||
File.Move(file, checkFile);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void MoveFiles(string personKeyFormatted, string personKeyDirectory, string newestPersonKeyFormatted, string newestPersonKeyDirectory)
|
|
||||||
{
|
|
||||||
string[] files;
|
|
||||||
string checkFile;
|
|
||||||
string? checkDirectory;
|
|
||||||
string[] directories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly);
|
|
||||||
foreach (string directory in directories)
|
|
||||||
{
|
|
||||||
checkDirectory = Path.Combine(newestPersonKeyDirectory, Path.GetFileName(directory));
|
|
||||||
if (!Directory.Exists(checkDirectory))
|
|
||||||
Directory.Move(directory, checkDirectory);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
if (file.Split(personKeyFormatted).Length != 2 || file.Contains(newestPersonKeyFormatted))
|
|
||||||
continue;
|
|
||||||
checkFile = file.Replace(personKeyFormatted, newestPersonKeyFormatted);
|
|
||||||
checkDirectory = Path.GetDirectoryName(checkFile);
|
|
||||||
if (checkDirectory is null)
|
|
||||||
continue;
|
|
||||||
if (File.Exists(checkFile))
|
|
||||||
continue;
|
|
||||||
if (!Directory.Exists(checkDirectory))
|
|
||||||
_ = Directory.CreateDirectory(checkDirectory);
|
|
||||||
File.Move(file, checkFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ = IPath.DeleteEmptyDirectories(personKeyDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<TicksDirectory> UpdateDateVerifyAndGetTicksDirectories(Configuration configuration, string eDistanceContentDirectory)
|
|
||||||
{
|
|
||||||
List<TicksDirectory> results = [];
|
|
||||||
float? totalDays;
|
|
||||||
long? next = null;
|
|
||||||
string? checkDirectory;
|
|
||||||
DateTime directoryDateTime;
|
|
||||||
DirectoryInfo directoryInfo;
|
|
||||||
TicksDirectory ticksDirectory;
|
|
||||||
long? lastDirectoryTicks = null;
|
|
||||||
DateTime dateTime = DateTime.Now;
|
|
||||||
DateTime alternateDirectoryDateTime;
|
|
||||||
string ticksDirectoryNameFirstSegment;
|
|
||||||
bool? isLocationContainerDebugDirectory;
|
|
||||||
long month = dateTime.AddMonths(1).Ticks - dateTime.Ticks;
|
|
||||||
for (int i = 1; i < 5; i++)
|
|
||||||
_ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
|
|
||||||
if (!Directory.Exists(eDistanceContentDirectory))
|
|
||||||
_ = Directory.CreateDirectory(eDistanceContentDirectory);
|
|
||||||
string[] ticksFullPaths = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly);
|
|
||||||
foreach (string ticksFullPath in ticksFullPaths)
|
|
||||||
{
|
|
||||||
ticksDirectoryNameFirstSegment = Path.GetFileName(ticksFullPath).Split('.')[0];
|
|
||||||
if (ticksDirectoryNameFirstSegment.Length < 3)
|
|
||||||
continue;
|
|
||||||
if (!long.TryParse(ticksDirectoryNameFirstSegment, out long directoryTicks))
|
|
||||||
throw new NotSupportedException();
|
|
||||||
if (next is null)
|
|
||||||
next = new DateTime(directoryTicks).Ticks;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
next += month;
|
|
||||||
checkDirectory = Path.GetDirectoryName(ticksFullPath);
|
|
||||||
if (string.IsNullOrEmpty(checkDirectory))
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(checkDirectory))
|
|
||||||
continue;
|
|
||||||
checkDirectory = Path.Combine(checkDirectory, next.Value.ToString());
|
|
||||||
if (ticksFullPath == checkDirectory || !checkDirectory.EndsWith(configuration.LocationContainerDirectoryPattern))
|
|
||||||
continue;
|
|
||||||
Directory.Move(ticksFullPath, checkDirectory);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
directoryInfo = new(ticksFullPath);
|
|
||||||
directoryDateTime = new DateTime(directoryTicks);
|
|
||||||
if (directoryInfo.CreationTime.Ticks != directoryTicks)
|
|
||||||
Directory.SetCreationTime(ticksFullPath, new DateTime(directoryTicks));
|
|
||||||
if (directoryInfo.LastWriteTime.Ticks != directoryTicks)
|
|
||||||
Directory.SetLastWriteTime(ticksFullPath, new DateTime(directoryTicks));
|
|
||||||
alternateDirectoryDateTime = new DateTime(directoryDateTime.Year, directoryDateTime.Month, directoryDateTime.Day).AddMonths(1);
|
|
||||||
isLocationContainerDebugDirectory = configuration.LocationContainerDebugDirectory is null ? null : ticksDirectoryNameFirstSegment.EndsWith(configuration.LocationContainerDebugDirectory);
|
|
||||||
totalDays = lastDirectoryTicks is null || new TimeSpan(dateTime.Ticks - directoryTicks).TotalDays < 1 ? null : (float)new TimeSpan(directoryTicks - lastDirectoryTicks.Value).TotalDays;
|
|
||||||
ticksDirectory = new(alternateDirectoryDateTime, ticksFullPath, new(directoryTicks), isLocationContainerDebugDirectory, totalDays);
|
|
||||||
results.Add(ticksDirectory);
|
|
||||||
if (directoryDateTime.Hour == 0 && directoryDateTime.Minute == 0 && directoryDateTime.Second == 0)
|
|
||||||
continue;
|
|
||||||
lastDirectoryTicks = directoryTicks;
|
|
||||||
}
|
|
||||||
string[] compare = (from l in results where l.TotalDays is not null and < 9.95f select l.Directory).ToArray();
|
|
||||||
if (compare.Length > 0 && configuration.ReMap)
|
|
||||||
throw new Exception($"Please Consolidate <{string.Join(Environment.NewLine, compare)}>");
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Individually(Configuration configuration, TicksDirectory ticksDirectory, string directory)
|
|
||||||
{
|
|
||||||
bool isDefault;
|
|
||||||
string[] files;
|
|
||||||
FileInfo[] collection;
|
|
||||||
string[] facesFileNames;
|
|
||||||
string yearDirectoryName;
|
|
||||||
string[] yearDirectories;
|
|
||||||
string alphaDirectoryName;
|
|
||||||
string matchDirectoryName;
|
|
||||||
string personKeyFormatted;
|
|
||||||
string[] alphaDirectories;
|
|
||||||
string[] matchDirectories;
|
|
||||||
string[] actionDirectories;
|
|
||||||
string personDisplayDirectory;
|
|
||||||
string[] personKeyDirectories;
|
|
||||||
string[] segmentCDirectories = Directory.GetDirectories(directory, "*", SearchOption.TopDirectoryOnly);
|
|
||||||
foreach (string segmentCDirectory in segmentCDirectories)
|
|
||||||
{
|
|
||||||
personKeyDirectories = Directory.GetDirectories(segmentCDirectory, "*", SearchOption.TopDirectoryOnly);
|
|
||||||
foreach (string personKeyDirectory in personKeyDirectories)
|
|
||||||
{
|
|
||||||
personKeyFormatted = Path.GetFileName(personKeyDirectory);
|
|
||||||
yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly);
|
|
||||||
foreach (string yearDirectory in yearDirectories)
|
|
||||||
{
|
|
||||||
yearDirectoryName = Path.GetFileName(yearDirectory);
|
|
||||||
if (yearDirectoryName.StartsWith('='))
|
|
||||||
Directory.Move(yearDirectory, yearDirectory.Replace('=', '~'));
|
|
||||||
}
|
|
||||||
yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly);
|
|
||||||
foreach (string yearDirectory in yearDirectories)
|
|
||||||
{
|
|
||||||
yearDirectoryName = Path.GetFileName(yearDirectory);
|
|
||||||
matchDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly);
|
|
||||||
alphaDirectories = matchDirectories.Where(l => !long.TryParse(Path.GetFileName(l), out long a)).ToArray();
|
|
||||||
if (alphaDirectories.Length == 0)
|
|
||||||
continue;
|
|
||||||
alphaDirectoryName = Path.GetFileName(alphaDirectories[0]);
|
|
||||||
foreach (string matchDirectory in matchDirectories)
|
|
||||||
{
|
|
||||||
matchDirectoryName = Path.GetFileName(matchDirectory);
|
|
||||||
files = Directory.GetFiles(matchDirectory, "*", SearchOption.TopDirectoryOnly);
|
|
||||||
if (files.Length != 4)
|
|
||||||
continue;
|
|
||||||
collection = files.Select(l => new FileInfo(l)).ToArray();
|
|
||||||
isDefault = IPerson.IsDefaultName(alphaDirectoryName) && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]);
|
|
||||||
if (isDefault)
|
|
||||||
facesFileNames = (from l in collection where l.Extension == configuration.FacesFileNameExtension select l.FullName).ToArray();
|
|
||||||
else
|
|
||||||
facesFileNames = (from l in collection where l.Extension == configuration.FacesFileNameExtension && l.Name.Contains(matchDirectoryName) select l.FullName).ToArray();
|
|
||||||
if (facesFileNames.Length == 0)
|
|
||||||
continue;
|
|
||||||
personDisplayDirectory = Path.Combine(matchDirectory, alphaDirectoryName);
|
|
||||||
if (!Directory.Exists(personDisplayDirectory) || !Directory.Exists(matchDirectory))
|
|
||||||
continue;
|
|
||||||
_ = Process.Start("explorer", matchDirectory);
|
|
||||||
for (int i = 0; i < int.MaxValue; i++)
|
|
||||||
{
|
|
||||||
Thread.Sleep(500);
|
|
||||||
actionDirectories = Directory.GetDirectories(matchDirectory, "*", SearchOption.TopDirectoryOnly).Where(l => l != personDisplayDirectory && !l.EndsWith("Maybe")).ToArray();
|
|
||||||
if (actionDirectories.Length > 0)
|
|
||||||
{
|
|
||||||
MoveTo(actionDirectories[0], ticksDirectory, directory, personKeyFormatted, yearDirectoryName, alphaDirectoryName, files, facesFileNames);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetCheckFile(TicksDirectory ticksDirectory, string @enum, string fileName, string file)
|
|
||||||
{
|
|
||||||
string result;
|
|
||||||
string checkDirectory;
|
|
||||||
string directory = file;
|
|
||||||
List<string> collection = [];
|
|
||||||
for (int i = 0; i < file.Length; i++)
|
|
||||||
{
|
|
||||||
directory = Path.GetDirectoryName(directory) ?? throw new Exception();
|
|
||||||
if (directory == ticksDirectory.Directory)
|
|
||||||
break;
|
|
||||||
collection.Add(Path.GetFileName(directory));
|
|
||||||
}
|
|
||||||
collection.Reverse();
|
|
||||||
checkDirectory = $"{ticksDirectory.Directory}.{@enum}";
|
|
||||||
foreach (string directoryName in collection)
|
|
||||||
checkDirectory = Path.Combine(checkDirectory, directoryName);
|
|
||||||
if (!Directory.Exists(checkDirectory))
|
|
||||||
_ = Directory.CreateDirectory(checkDirectory);
|
|
||||||
result = Path.Combine(checkDirectory, fileName);
|
|
||||||
if (File.Exists(result))
|
|
||||||
throw new Exception($"File <{fileName}> already exists!");
|
|
||||||
File.Move(file, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Record> GetRecords(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, TicksDirectory ticksDirectory, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, int? linksCount, List<string> distinct, string? personDisplayDirectoryName)
|
|
||||||
{
|
|
||||||
List<Record> results = [];
|
|
||||||
string @enum;
|
|
||||||
Record record;
|
|
||||||
string fileName;
|
|
||||||
string checkFile;
|
|
||||||
FilePath filePath;
|
|
||||||
FileHolder fileHolder;
|
|
||||||
int? wholePercentages;
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
if (file.EndsWith(".lnk"))
|
|
||||||
continue;
|
|
||||||
fileHolder = IFileHolder.Get(file);
|
|
||||||
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
|
|
||||||
if (filePath.Id is null)
|
|
||||||
continue;
|
|
||||||
wholePercentages = IMapping.GetWholePercentages(configuration.FacesFileNameExtension, filePath);
|
|
||||||
if (wholePercentages is null)
|
|
||||||
continue;
|
|
||||||
fileName = Path.GetFileName(file);
|
|
||||||
if (distinct.Contains(fileName))
|
|
||||||
{
|
|
||||||
checkFile = $"{file}.dup";
|
|
||||||
if (File.Exists(checkFile))
|
|
||||||
continue;
|
|
||||||
File.Move(file, checkFile);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (file.StartsWith(ticksDirectory.Directory))
|
|
||||||
{
|
|
||||||
@enum = IPath.GetEnum(filePath).ToString();
|
|
||||||
if (!ticksDirectory.Directory.EndsWith(@enum))
|
|
||||||
{
|
|
||||||
checkFile = GetCheckFile(ticksDirectory, @enum, fileName, file);
|
|
||||||
fileHolder = IFileHolder.Get(checkFile);
|
|
||||||
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
|
|
||||||
if (filePath.Id is null)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
distinct.Add(fileName);
|
|
||||||
record = new(DirectoryNumber: directoryNumber,
|
|
||||||
IsDefault: isDefault,
|
|
||||||
LinksCount: linksCount,
|
|
||||||
MappedFaceFilePath: filePath,
|
|
||||||
PersonDisplayDirectoryName: personDisplayDirectoryName,
|
|
||||||
PersonKeyFormatted: personKeyFormatted);
|
|
||||||
results.Add(record);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string[] RenameBirth(string[] files)
|
|
||||||
{
|
|
||||||
List<string> results = [];
|
|
||||||
string checkFile;
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
if (file.EndsWith(".brt"))
|
|
||||||
{
|
|
||||||
results.Add(file);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
checkFile = $"{file}.brt";
|
|
||||||
if (File.Exists(checkFile))
|
|
||||||
{
|
|
||||||
results.Add(file);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
File.Move(file, checkFile);
|
|
||||||
results.Add(checkFile);
|
|
||||||
}
|
|
||||||
return results.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void MovedToNewestPersonKeyFormatted(string personKeyFormatted, string newestPersonKeyFormatted, TicksDirectory ticksDirectory, string personKeyDirectory)
|
|
||||||
{
|
|
||||||
string newestPersonKeyDirectory = Path.Combine(ticksDirectory.Directory, newestPersonKeyFormatted);
|
|
||||||
if (Directory.Exists(newestPersonKeyDirectory))
|
|
||||||
MoveFiles(personKeyFormatted, personKeyDirectory, newestPersonKeyFormatted, newestPersonKeyDirectory);
|
|
||||||
else
|
|
||||||
Directory.Move(personKeyDirectory, newestPersonKeyDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int? GetLinksCount(string yearDirectory)
|
|
||||||
{
|
|
||||||
int? result;
|
|
||||||
string[] yearDirectoryNameSegments = Path.GetFileName(yearDirectory).Split('-');
|
|
||||||
if (yearDirectoryNameSegments.Length != 3)
|
|
||||||
result = null;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string lastSegment = yearDirectoryNameSegments[^1];
|
|
||||||
if (lastSegment.Length != 3 || !lastSegment.All(l => l == lastSegment[0]))
|
|
||||||
result = null;
|
|
||||||
else
|
|
||||||
result = lastSegment[0] - 65;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static List<Record> DeleteEmptyDirectoriesAndGetCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, string eDistanceContentDirectory, ReadOnlyDictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted, ReadOnlyCollection<string> personKeyFormattedCollection)
|
internal static List<Record> DeleteEmptyDirectoriesAndGetCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, string eDistanceContentDirectory, ReadOnlyDictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted, ReadOnlyCollection<string> personKeyFormattedCollection)
|
||||||
{
|
{
|
||||||
List<Record> results = [];
|
List<Record> results = [];
|
||||||
@ -529,4 +208,325 @@ internal abstract class DistanceLogic
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<TicksDirectory> UpdateDateVerifyAndGetTicksDirectories(Configuration configuration, string eDistanceContentDirectory)
|
||||||
|
{
|
||||||
|
List<TicksDirectory> results = [];
|
||||||
|
float? totalDays;
|
||||||
|
long? next = null;
|
||||||
|
string? checkDirectory;
|
||||||
|
DateTime directoryDateTime;
|
||||||
|
DirectoryInfo directoryInfo;
|
||||||
|
TicksDirectory ticksDirectory;
|
||||||
|
long? lastDirectoryTicks = null;
|
||||||
|
DateTime dateTime = DateTime.Now;
|
||||||
|
DateTime alternateDirectoryDateTime;
|
||||||
|
string ticksDirectoryNameFirstSegment;
|
||||||
|
bool? isLocationContainerDebugDirectory;
|
||||||
|
long month = dateTime.AddMonths(1).Ticks - dateTime.Ticks;
|
||||||
|
for (int i = 1; i < 5; i++)
|
||||||
|
_ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
|
||||||
|
if (!Directory.Exists(eDistanceContentDirectory))
|
||||||
|
_ = Directory.CreateDirectory(eDistanceContentDirectory);
|
||||||
|
string[] ticksFullPaths = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
foreach (string ticksFullPath in ticksFullPaths)
|
||||||
|
{
|
||||||
|
ticksDirectoryNameFirstSegment = Path.GetFileName(ticksFullPath).Split('.')[0];
|
||||||
|
if (ticksDirectoryNameFirstSegment.Length < 3)
|
||||||
|
continue;
|
||||||
|
if (!long.TryParse(ticksDirectoryNameFirstSegment, out long directoryTicks))
|
||||||
|
throw new NotSupportedException();
|
||||||
|
if (next is null)
|
||||||
|
next = new DateTime(directoryTicks).Ticks;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
next += month;
|
||||||
|
checkDirectory = Path.GetDirectoryName(ticksFullPath);
|
||||||
|
if (string.IsNullOrEmpty(checkDirectory))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(checkDirectory))
|
||||||
|
continue;
|
||||||
|
checkDirectory = Path.Combine(checkDirectory, next.Value.ToString());
|
||||||
|
if (ticksFullPath == checkDirectory || !checkDirectory.EndsWith(configuration.LocationContainerDirectoryPattern))
|
||||||
|
continue;
|
||||||
|
Directory.Move(ticksFullPath, checkDirectory);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
directoryInfo = new(ticksFullPath);
|
||||||
|
directoryDateTime = new DateTime(directoryTicks);
|
||||||
|
if (directoryInfo.CreationTime.Ticks != directoryTicks)
|
||||||
|
Directory.SetCreationTime(ticksFullPath, new DateTime(directoryTicks));
|
||||||
|
if (directoryInfo.LastWriteTime.Ticks != directoryTicks)
|
||||||
|
Directory.SetLastWriteTime(ticksFullPath, new DateTime(directoryTicks));
|
||||||
|
alternateDirectoryDateTime = new DateTime(directoryDateTime.Year, directoryDateTime.Month, directoryDateTime.Day).AddMonths(1);
|
||||||
|
isLocationContainerDebugDirectory = configuration.LocationContainerDebugDirectory is null ? null : ticksDirectoryNameFirstSegment.EndsWith(configuration.LocationContainerDebugDirectory);
|
||||||
|
totalDays = lastDirectoryTicks is null || new TimeSpan(dateTime.Ticks - directoryTicks).TotalDays < 1 ? null : (float)new TimeSpan(directoryTicks - lastDirectoryTicks.Value).TotalDays;
|
||||||
|
ticksDirectory = new(alternateDirectoryDateTime, ticksFullPath, new(directoryTicks), isLocationContainerDebugDirectory, totalDays);
|
||||||
|
results.Add(ticksDirectory);
|
||||||
|
if (directoryDateTime.Hour == 0 && directoryDateTime.Minute == 0 && directoryDateTime.Second == 0)
|
||||||
|
continue;
|
||||||
|
lastDirectoryTicks = directoryTicks;
|
||||||
|
}
|
||||||
|
string[] compare = (from l in results where l.TotalDays is not null and < 9.95f select l.Directory).ToArray();
|
||||||
|
if (compare.Length > 0 && configuration.ReMap)
|
||||||
|
throw new Exception($"Please Consolidate <{string.Join(Environment.NewLine, compare)}>");
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Individually(Configuration configuration, TicksDirectory ticksDirectory, string directory)
|
||||||
|
{
|
||||||
|
bool isDefault;
|
||||||
|
string[] files;
|
||||||
|
FileInfo[] collection;
|
||||||
|
string[] facesFileNames;
|
||||||
|
string yearDirectoryName;
|
||||||
|
string[] yearDirectories;
|
||||||
|
string alphaDirectoryName;
|
||||||
|
string matchDirectoryName;
|
||||||
|
string personKeyFormatted;
|
||||||
|
string[] alphaDirectories;
|
||||||
|
string[] matchDirectories;
|
||||||
|
string[] actionDirectories;
|
||||||
|
string personDisplayDirectory;
|
||||||
|
string[] personKeyDirectories;
|
||||||
|
string[] segmentCDirectories = Directory.GetDirectories(directory, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
foreach (string segmentCDirectory in segmentCDirectories)
|
||||||
|
{
|
||||||
|
personKeyDirectories = Directory.GetDirectories(segmentCDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
foreach (string personKeyDirectory in personKeyDirectories)
|
||||||
|
{
|
||||||
|
personKeyFormatted = Path.GetFileName(personKeyDirectory);
|
||||||
|
yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
foreach (string yearDirectory in yearDirectories)
|
||||||
|
{
|
||||||
|
yearDirectoryName = Path.GetFileName(yearDirectory);
|
||||||
|
if (yearDirectoryName.StartsWith('='))
|
||||||
|
Directory.Move(yearDirectory, yearDirectory.Replace('=', '~'));
|
||||||
|
}
|
||||||
|
yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
foreach (string yearDirectory in yearDirectories)
|
||||||
|
{
|
||||||
|
yearDirectoryName = Path.GetFileName(yearDirectory);
|
||||||
|
matchDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
alphaDirectories = matchDirectories.Where(l => !long.TryParse(Path.GetFileName(l), out long a)).ToArray();
|
||||||
|
if (alphaDirectories.Length == 0)
|
||||||
|
continue;
|
||||||
|
alphaDirectoryName = Path.GetFileName(alphaDirectories[0]);
|
||||||
|
foreach (string matchDirectory in matchDirectories)
|
||||||
|
{
|
||||||
|
matchDirectoryName = Path.GetFileName(matchDirectory);
|
||||||
|
files = Directory.GetFiles(matchDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
if (files.Length != 4)
|
||||||
|
continue;
|
||||||
|
collection = files.Select(l => new FileInfo(l)).ToArray();
|
||||||
|
isDefault = IPerson.IsDefaultName(alphaDirectoryName) && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]);
|
||||||
|
if (isDefault)
|
||||||
|
facesFileNames = (from l in collection where l.Extension == configuration.FacesFileNameExtension select l.FullName).ToArray();
|
||||||
|
else
|
||||||
|
facesFileNames = (from l in collection where l.Extension == configuration.FacesFileNameExtension && l.Name.Contains(matchDirectoryName) select l.FullName).ToArray();
|
||||||
|
if (facesFileNames.Length == 0)
|
||||||
|
continue;
|
||||||
|
personDisplayDirectory = Path.Combine(matchDirectory, alphaDirectoryName);
|
||||||
|
if (!Directory.Exists(personDisplayDirectory) || !Directory.Exists(matchDirectory))
|
||||||
|
continue;
|
||||||
|
_ = Process.Start("explorer", matchDirectory);
|
||||||
|
for (int i = 0; i < int.MaxValue; i++)
|
||||||
|
{
|
||||||
|
Thread.Sleep(500);
|
||||||
|
actionDirectories = Directory.GetDirectories(matchDirectory, "*", SearchOption.TopDirectoryOnly).Where(l => l != personDisplayDirectory && !l.EndsWith("Maybe")).ToArray();
|
||||||
|
if (actionDirectories.Length > 0)
|
||||||
|
{
|
||||||
|
MoveTo(actionDirectories[0], ticksDirectory, directory, personKeyFormatted, yearDirectoryName, alphaDirectoryName, files, facesFileNames);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MoveTo(string actionDirectory, TicksDirectory ticksDirectory, string directory, string personKeyFormatted, string yearDirectoryName, string alphaDirectoryName, string[] files, string[] facesFileNames)
|
||||||
|
{
|
||||||
|
string checkFile;
|
||||||
|
string actionDirectoryName = Path.GetFileName(actionDirectory);
|
||||||
|
string checkDirectory = actionDirectoryName.StartsWith("y", StringComparison.CurrentCultureIgnoreCase) ? Path.Combine(ticksDirectory.Directory, personKeyFormatted, yearDirectoryName, alphaDirectoryName) : Path.Combine(directory, actionDirectoryName);
|
||||||
|
if (!Directory.Exists(checkDirectory))
|
||||||
|
_ = Directory.CreateDirectory(checkDirectory);
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
if (facesFileNames.Contains(file))
|
||||||
|
{
|
||||||
|
checkFile = Path.Combine(checkDirectory, Path.GetFileName(file));
|
||||||
|
if (File.Exists(checkFile))
|
||||||
|
continue;
|
||||||
|
File.Move(file, checkFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int? GetLinksCount(string yearDirectory)
|
||||||
|
{
|
||||||
|
int? result;
|
||||||
|
string[] yearDirectoryNameSegments = Path.GetFileName(yearDirectory).Split('-');
|
||||||
|
if (yearDirectoryNameSegments.Length != 3)
|
||||||
|
result = null;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string lastSegment = yearDirectoryNameSegments[^1];
|
||||||
|
if (lastSegment.Length != 3 || !lastSegment.All(l => l == lastSegment[0]))
|
||||||
|
result = null;
|
||||||
|
else
|
||||||
|
result = lastSegment[0] - 65;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string[] RenameBirth(string[] files)
|
||||||
|
{
|
||||||
|
List<string> results = [];
|
||||||
|
string checkFile;
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
if (file.EndsWith(".brt"))
|
||||||
|
{
|
||||||
|
results.Add(file);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
checkFile = $"{file}.brt";
|
||||||
|
if (File.Exists(checkFile))
|
||||||
|
{
|
||||||
|
results.Add(file);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
File.Move(file, checkFile);
|
||||||
|
results.Add(checkFile);
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MovedToNewestPersonKeyFormatted(string personKeyFormatted, string newestPersonKeyFormatted, TicksDirectory ticksDirectory, string personKeyDirectory)
|
||||||
|
{
|
||||||
|
string newestPersonKeyDirectory = Path.Combine(ticksDirectory.Directory, newestPersonKeyFormatted);
|
||||||
|
if (Directory.Exists(newestPersonKeyDirectory))
|
||||||
|
MoveFiles(personKeyFormatted, personKeyDirectory, newestPersonKeyFormatted, newestPersonKeyDirectory);
|
||||||
|
else
|
||||||
|
Directory.Move(personKeyDirectory, newestPersonKeyDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MoveFiles(string personKeyFormatted, string personKeyDirectory, string newestPersonKeyFormatted, string newestPersonKeyDirectory)
|
||||||
|
{
|
||||||
|
string[] files;
|
||||||
|
string checkFile;
|
||||||
|
string? checkDirectory;
|
||||||
|
string[] directories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
foreach (string directory in directories)
|
||||||
|
{
|
||||||
|
checkDirectory = Path.Combine(newestPersonKeyDirectory, Path.GetFileName(directory));
|
||||||
|
if (!Directory.Exists(checkDirectory))
|
||||||
|
Directory.Move(directory, checkDirectory);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
if (file.Split(personKeyFormatted).Length != 2 || file.Contains(newestPersonKeyFormatted))
|
||||||
|
continue;
|
||||||
|
checkFile = file.Replace(personKeyFormatted, newestPersonKeyFormatted);
|
||||||
|
checkDirectory = Path.GetDirectoryName(checkFile);
|
||||||
|
if (checkDirectory is null)
|
||||||
|
continue;
|
||||||
|
if (File.Exists(checkFile))
|
||||||
|
continue;
|
||||||
|
if (!Directory.Exists(checkDirectory))
|
||||||
|
_ = Directory.CreateDirectory(checkDirectory);
|
||||||
|
File.Move(file, checkFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = IPath.DeleteEmptyDirectories(personKeyDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Record> GetRecords(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, TicksDirectory ticksDirectory, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, int? linksCount, List<string> distinct, string? personDisplayDirectoryName)
|
||||||
|
{
|
||||||
|
List<Record> results = [];
|
||||||
|
string @enum;
|
||||||
|
Record record;
|
||||||
|
string fileName;
|
||||||
|
string checkFile;
|
||||||
|
FilePath filePath;
|
||||||
|
FileHolder fileHolder;
|
||||||
|
int? wholePercentages;
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
if (file.EndsWith(".lnk"))
|
||||||
|
continue;
|
||||||
|
fileHolder = IFileHolder.Get(file);
|
||||||
|
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
|
||||||
|
if (filePath.Id is null)
|
||||||
|
continue;
|
||||||
|
wholePercentages = IMapping.GetWholePercentages(configuration.FacesFileNameExtension, filePath);
|
||||||
|
if (wholePercentages is null)
|
||||||
|
continue;
|
||||||
|
fileName = Path.GetFileName(file);
|
||||||
|
if (distinct.Contains(fileName))
|
||||||
|
{
|
||||||
|
checkFile = $"{file}.dup";
|
||||||
|
if (File.Exists(checkFile))
|
||||||
|
continue;
|
||||||
|
File.Move(file, checkFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (file.StartsWith(ticksDirectory.Directory))
|
||||||
|
{
|
||||||
|
@enum = IPath.GetEnum(filePath).ToString();
|
||||||
|
if (!ticksDirectory.Directory.EndsWith(@enum))
|
||||||
|
{
|
||||||
|
checkFile = GetCheckFile(ticksDirectory, @enum, fileName, file);
|
||||||
|
fileHolder = IFileHolder.Get(checkFile);
|
||||||
|
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
|
||||||
|
if (filePath.Id is null)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
distinct.Add(fileName);
|
||||||
|
record = new(DirectoryNumber: directoryNumber,
|
||||||
|
IsDefault: isDefault,
|
||||||
|
LinksCount: linksCount,
|
||||||
|
MappedFaceFilePath: filePath,
|
||||||
|
PersonDisplayDirectoryName: personDisplayDirectoryName,
|
||||||
|
PersonKeyFormatted: personKeyFormatted);
|
||||||
|
results.Add(record);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetCheckFile(TicksDirectory ticksDirectory, string @enum, string fileName, string file)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
string checkDirectory;
|
||||||
|
string directory = file;
|
||||||
|
List<string> collection = [];
|
||||||
|
for (int i = 0; i < file.Length; i++)
|
||||||
|
{
|
||||||
|
directory = Path.GetDirectoryName(directory) ?? throw new Exception();
|
||||||
|
if (directory == ticksDirectory.Directory)
|
||||||
|
break;
|
||||||
|
collection.Add(Path.GetFileName(directory));
|
||||||
|
}
|
||||||
|
collection.Reverse();
|
||||||
|
checkDirectory = $"{ticksDirectory.Directory}.{@enum}";
|
||||||
|
foreach (string directoryName in collection)
|
||||||
|
checkDirectory = Path.Combine(checkDirectory, directoryName);
|
||||||
|
if (!Directory.Exists(checkDirectory))
|
||||||
|
_ = Directory.CreateDirectory(checkDirectory);
|
||||||
|
result = Path.Combine(checkDirectory, fileName);
|
||||||
|
if (File.Exists(result))
|
||||||
|
throw new Exception($"File <{fileName}> already exists!");
|
||||||
|
File.Move(file, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
@ -7,69 +7,93 @@ namespace View_by_Distance.Map.Models.Stateless.Methods;
|
|||||||
public interface IMapLogic
|
public interface IMapLogic
|
||||||
{
|
{
|
||||||
|
|
||||||
ReadOnlyDictionary<int, List<long>> TestStatic_GetIdToPersonKeys(ReadOnlyDictionary<long, List<int>> personKeyToIds) =>
|
static string Get(bool saveIndividually, string forceSingleImageHumanized, int by, bool isDefaultName) =>
|
||||||
GetIdToPersonKeys(personKeyToIds);
|
$"{by switch
|
||||||
static ReadOnlyDictionary<int, List<long>> GetIdToPersonKeys(ReadOnlyDictionary<long, List<int>> personKeyToIds) =>
|
{
|
||||||
MapLogic.GetIdToPersonKeys(personKeyToIds);
|
Shared.Models.Stateless.IMapLogic.Mapping => nameof(Shared.Models.Stateless.IMapLogic.Mapping),
|
||||||
|
Shared.Models.Stateless.IMapLogic.Sorting => saveIndividually ?
|
||||||
|
nameof(Shared.Models.Stateless.IMapLogic.Individually) :
|
||||||
|
nameof(Shared.Models.Stateless.IMapLogic.Sorting),
|
||||||
|
Shared.Models.Stateless.IMapLogic.ForceSingleImage => forceSingleImageHumanized,
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
}}{(!isDefaultName ? "-A" : "-Z")}";
|
||||||
|
|
||||||
ReadOnlyCollection<Face> TestStatic_GetFaces(ReadOnlyCollection<Item> items) =>
|
public static Mapping[] GetSelectedMappingCollection(ReadOnlyCollection<Item> items) =>
|
||||||
GetFaces(items);
|
|
||||||
static ReadOnlyCollection<Face> GetFaces(ReadOnlyCollection<Item> items) =>
|
|
||||||
MapLogic.GetFaces(items);
|
|
||||||
|
|
||||||
Mapping[] TestStatic_GetSelectedMappingCollection(ReadOnlyCollection<Item> items) =>
|
|
||||||
GetSelectedMappingCollection(items);
|
|
||||||
static Mapping[] GetSelectedMappingCollection(ReadOnlyCollection<Item> items) =>
|
|
||||||
MapLogic.GetSelectedMappingCollection(items);
|
MapLogic.GetSelectedMappingCollection(items);
|
||||||
|
|
||||||
Mapping[] TestStatic_GetSelectedMappingCollection(ReadOnlyCollection<Face> faces) =>
|
public static Mapping[] GetSelectedMappingCollection(ReadOnlyCollection<Face> faces) =>
|
||||||
GetSelectedMappingCollection(faces);
|
|
||||||
static Mapping[] GetSelectedMappingCollection(ReadOnlyCollection<Face> faces) =>
|
|
||||||
MapLogic.GetSelectedMappingCollection(faces);
|
MapLogic.GetSelectedMappingCollection(faces);
|
||||||
|
|
||||||
ReadOnlyDictionary<int, ReadOnlyDictionary<int, Mapping>> TestStatic_GetIdToWholePercentagesToFace(ReadOnlyCollection<Mapping> distinctValidImageMappingCollection) =>
|
public static bool? CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, int wholePercentages) =>
|
||||||
GetIdToWholePercentagesToFace(distinctValidImageMappingCollection);
|
|
||||||
static ReadOnlyDictionary<int, ReadOnlyDictionary<int, Mapping>> GetIdToWholePercentagesToFace(ReadOnlyCollection<Mapping> distinctValidImageMappingCollection) =>
|
|
||||||
MapLogic.GetIdToWholePercentagesToFace(distinctValidImageMappingCollection);
|
|
||||||
|
|
||||||
List<(string, long)> TestStatic_GetJLinkDirectories(string genealogicalDataCommunicationFile, string[] jLinks, string personBirthdayFormat, char[] personCharacters, string a2PeopleSingletonDirectory, string a2PeopleContentDirectory) =>
|
|
||||||
GetJLinkDirectories(genealogicalDataCommunicationFile, jLinks, personBirthdayFormat, personCharacters, a2PeopleSingletonDirectory, a2PeopleContentDirectory);
|
|
||||||
static List<(string, long)> GetJLinkDirectories(string genealogicalDataCommunicationFile, string[] jLinks, string personBirthdayFormat, char[] personCharacters, string a2PeopleSingletonDirectory, string a2PeopleContentDirectory) =>
|
|
||||||
MapLogic.GetJLinkDirectories(genealogicalDataCommunicationFile, jLinks, personBirthdayFormat, personCharacters, a2PeopleSingletonDirectory, a2PeopleContentDirectory);
|
|
||||||
|
|
||||||
void TestStatic_SetCreationTime(MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer> locationContainers) =>
|
|
||||||
SetCreationTime(mappingFromItem, locationContainers);
|
|
||||||
static void SetCreationTime(MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer> locationContainers) =>
|
|
||||||
DecadeLogic.SetCreationTime(mappingFromItem, locationContainers);
|
|
||||||
|
|
||||||
void TestStatic_MoveToDecade(Property.Models.Configuration propertyConfiguration, MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer> locationContainers) =>
|
|
||||||
MoveToDecade(propertyConfiguration, mappingFromItem, locationContainers);
|
|
||||||
static void MoveToDecade(Property.Models.Configuration propertyConfiguration, MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer> locationContainers) =>
|
|
||||||
DecadeLogic.MoveToDecade(propertyConfiguration, mappingFromItem, locationContainers);
|
|
||||||
|
|
||||||
bool? TestStatic_CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, MappingFromLocation mappingFromLocation) =>
|
|
||||||
CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);
|
|
||||||
static bool? CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, MappingFromLocation mappingFromLocation) =>
|
|
||||||
MapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation.WholePercentages);
|
|
||||||
|
|
||||||
bool? TestStatic_CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, int wholePercentages) =>
|
|
||||||
CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, wholePercentages);
|
|
||||||
static bool? CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, int wholePercentages) =>
|
|
||||||
MapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, wholePercentages);
|
MapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, wholePercentages);
|
||||||
|
|
||||||
string TestStatic_GetDecade(MappingFromItem mappingFromItem) =>
|
public static bool? CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, MappingFromLocation mappingFromLocation) =>
|
||||||
GetDecade(mappingFromItem);
|
MapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation.WholePercentages);
|
||||||
static string GetDecade(MappingFromItem mappingFromItem) =>
|
|
||||||
|
public static string GetDecade(MappingFromItem mappingFromItem) =>
|
||||||
DecadeLogic.GetDecade(mappingFromItem, null);
|
DecadeLogic.GetDecade(mappingFromItem, null);
|
||||||
|
|
||||||
ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> TestStatic_GetMappedFiles(int maxDegreeOfParallelism, Property.Models.Configuration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) =>
|
public static ReadOnlyCollection<Face> GetFaces(ReadOnlyCollection<Item> items) =>
|
||||||
GetMapped(maxDegreeOfParallelism, propertyConfiguration, configuration, ticks, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
MapLogic.GetFaces(items);
|
||||||
static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetMapped(int maxDegreeOfParallelism, Property.Models.Configuration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) =>
|
|
||||||
FaceFileLogic.GetMapped(maxDegreeOfParallelism, propertyConfiguration, configuration, ticks, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
|
||||||
|
|
||||||
List<LocationContainer> TestStatic_GetAvailable(int maxDegreeOfParallelism, Configuration configuration, IFaceD dFace, long ticks, ReadOnlyCollection<FilePath> filePaths) =>
|
public static ReadOnlyDictionary<int, List<long>> GetIdToPersonKeys(ReadOnlyDictionary<long, List<int>> personKeyToIds) =>
|
||||||
GetAvailable(maxDegreeOfParallelism, configuration, dFace, ticks, filePaths);
|
MapLogic.GetIdToPersonKeys(personKeyToIds);
|
||||||
static List<LocationContainer> GetAvailable(int maxDegreeOfParallelism, Configuration configuration, IFaceD dFace, long ticks, ReadOnlyCollection<FilePath> filePaths) =>
|
|
||||||
|
public static void SetCreationTime(MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer> locationContainers) =>
|
||||||
|
DecadeLogic.SetCreationTime(mappingFromItem, locationContainers);
|
||||||
|
|
||||||
|
public static ReadOnlyDictionary<int, ReadOnlyDictionary<int, Mapping>> GetIdToWholePercentagesToFace(ReadOnlyCollection<Mapping> distinctValidImageMappingCollection) =>
|
||||||
|
MapLogic.GetIdToWholePercentagesToFace(distinctValidImageMappingCollection);
|
||||||
|
|
||||||
|
public static List<LocationContainer> GetAvailable(int maxDegreeOfParallelism, Configuration configuration, IFaceD dFace, long ticks, ReadOnlyCollection<FilePath> filePaths) =>
|
||||||
FaceFileLogic.GetAvailable(maxDegreeOfParallelism, configuration, dFace, ticks, filePaths);
|
FaceFileLogic.GetAvailable(maxDegreeOfParallelism, configuration, dFace, ticks, filePaths);
|
||||||
|
|
||||||
|
public static void MoveToDecade(Property.Models.Configuration propertyConfiguration, MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer> locationContainers) =>
|
||||||
|
DecadeLogic.MoveToDecade(propertyConfiguration, mappingFromItem, locationContainers);
|
||||||
|
|
||||||
|
public static List<(string, long)> GetJLinkDirectories(string genealogicalDataCommunicationFile, string[] jLinks, string personBirthdayFormat, char[] personCharacters, string a2PeopleSingletonDirectory, string a2PeopleContentDirectory) =>
|
||||||
|
MapLogic.GetJLinkDirectories(genealogicalDataCommunicationFile, jLinks, personBirthdayFormat, personCharacters, a2PeopleSingletonDirectory, a2PeopleContentDirectory);
|
||||||
|
|
||||||
|
public static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetMapped(int maxDegreeOfParallelism, Property.Models.Configuration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) =>
|
||||||
|
FaceFileLogic.GetMapped(maxDegreeOfParallelism, propertyConfiguration, configuration, ticks, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
||||||
|
|
||||||
|
internal string TestStatic_GetDecade(MappingFromItem mappingFromItem) =>
|
||||||
|
GetDecade(mappingFromItem);
|
||||||
|
|
||||||
|
internal ReadOnlyCollection<Face> TestStatic_GetFaces(ReadOnlyCollection<Item> items) =>
|
||||||
|
GetFaces(items);
|
||||||
|
|
||||||
|
internal Mapping[] TestStatic_GetSelectedMappingCollection(ReadOnlyCollection<Item> items) =>
|
||||||
|
GetSelectedMappingCollection(items);
|
||||||
|
|
||||||
|
internal Mapping[] TestStatic_GetSelectedMappingCollection(ReadOnlyCollection<Face> faces) =>
|
||||||
|
GetSelectedMappingCollection(faces);
|
||||||
|
|
||||||
|
internal ReadOnlyDictionary<int, List<long>> TestStatic_GetIdToPersonKeys(ReadOnlyDictionary<long, List<int>> personKeyToIds) =>
|
||||||
|
GetIdToPersonKeys(personKeyToIds);
|
||||||
|
|
||||||
|
internal void TestStatic_SetCreationTime(MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer> locationContainers) =>
|
||||||
|
SetCreationTime(mappingFromItem, locationContainers);
|
||||||
|
|
||||||
|
internal ReadOnlyDictionary<int, ReadOnlyDictionary<int, Mapping>> TestStatic_GetIdToWholePercentagesToFace(ReadOnlyCollection<Mapping> distinctValidImageMappingCollection) =>
|
||||||
|
GetIdToWholePercentagesToFace(distinctValidImageMappingCollection);
|
||||||
|
|
||||||
|
internal List<LocationContainer> TestStatic_GetAvailable(int maxDegreeOfParallelism, Configuration configuration, IFaceD dFace, long ticks, ReadOnlyCollection<FilePath> filePaths) =>
|
||||||
|
GetAvailable(maxDegreeOfParallelism, configuration, dFace, ticks, filePaths);
|
||||||
|
|
||||||
|
internal void TestStatic_MoveToDecade(Property.Models.Configuration propertyConfiguration, MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer> locationContainers) =>
|
||||||
|
MoveToDecade(propertyConfiguration, mappingFromItem, locationContainers);
|
||||||
|
|
||||||
|
internal bool? TestStatic_CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, int wholePercentages) =>
|
||||||
|
CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, wholePercentages);
|
||||||
|
|
||||||
|
internal bool? TestStatic_CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, MappingFromLocation mappingFromLocation) =>
|
||||||
|
CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);
|
||||||
|
|
||||||
|
internal List<(string, long)> TestStatic_GetJLinkDirectories(string genealogicalDataCommunicationFile, string[] jLinks, string personBirthdayFormat, char[] personCharacters, string a2PeopleSingletonDirectory, string a2PeopleContentDirectory) =>
|
||||||
|
GetJLinkDirectories(genealogicalDataCommunicationFile, jLinks, personBirthdayFormat, personCharacters, a2PeopleSingletonDirectory, a2PeopleContentDirectory);
|
||||||
|
|
||||||
|
internal ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> TestStatic_GetMappedFiles(int maxDegreeOfParallelism, Property.Models.Configuration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) =>
|
||||||
|
GetMapped(maxDegreeOfParallelism, propertyConfiguration, configuration, ticks, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
||||||
|
|
||||||
}
|
}
|
@ -8,36 +8,48 @@ namespace View_by_Distance.Map.Models.Stateless;
|
|||||||
internal abstract class RelationLogic
|
internal abstract class RelationLogic
|
||||||
{
|
{
|
||||||
|
|
||||||
internal record Group(string Key, long PersonKey, ReadOnlyCollection<LocationContainer> RelationContainersCollection);
|
internal record Group(string Key,
|
||||||
|
long PersonKey,
|
||||||
|
ReadOnlyCollection<LocationContainer> RelationContainersCollection);
|
||||||
|
|
||||||
private static Dictionary<long, Dictionary<int, List<LocationContainer>>> GetPersonKeyTo(Configuration configuration, List<LocationContainer> locationContainers)
|
internal static void SaveMappedRelations(Configuration configuration, Shared.Models.Methods.IDistance distance, string a2PeopleContentDirectory, string eDistanceContentDirectory, long ticks, List<LocationContainer> locationContainers, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection)
|
||||||
{
|
{
|
||||||
List<LocationContainer>? collection;
|
int take;
|
||||||
Dictionary<int, List<LocationContainer>>? yearTo;
|
string directory;
|
||||||
Dictionary<long, Dictionary<int, List<LocationContainer>>> personKeyTo = [];
|
bool isCounterPersonYear;
|
||||||
foreach (LocationContainer locationContainer in locationContainers)
|
string personKeyFormatted;
|
||||||
|
string? displayDirectoryName;
|
||||||
|
Uri uri = new(eDistanceContentDirectory);
|
||||||
|
ReadOnlyDictionary<string, string> movedFiles;
|
||||||
|
ReadOnlyCollection<RelationContainer> relationContainers;
|
||||||
|
ReadOnlyCollection<Group> groups = GetGroups(configuration, locationContainers);
|
||||||
|
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||||
|
string message = $") Save Mapped Relations - {totalSeconds} total second(s)";
|
||||||
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||||
|
using ProgressBar progressBar = new(groups.Count, message, options);
|
||||||
|
foreach (Group group in groups)
|
||||||
{
|
{
|
||||||
if (locationContainer.PersonKey is null)
|
if (configuration.LocationContainerDistanceTolerance is null)
|
||||||
|
break;
|
||||||
|
progressBar.Tick();
|
||||||
|
if (group.RelationContainersCollection.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
if (!locationContainer.FromDistanceContent)
|
take = GetTake(configuration.LocationContainerDistanceTake, group.RelationContainersCollection.Count);
|
||||||
continue;
|
isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(new DateTime(group.PersonKey).Year);
|
||||||
if (!locationContainer.FilePath.FullName.Contains(configuration.LocationContainerDirectoryPattern))
|
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, group.PersonKey);
|
||||||
continue;
|
displayDirectoryName = GetDisplayDirectoryName(readOnlyPersonKeyToPersonContainerCollection, readOnlyPersonKeyFormattedToPersonContainer, group.PersonKey, personKeyFormatted);
|
||||||
if (!personKeyTo.TryGetValue(locationContainer.PersonKey.Value, out yearTo))
|
directory = Path.Combine(a2PeopleContentDirectory, $"{ticks}-{configuration.LocationContainerDistanceTolerance.Value}", personKeyFormatted, group.Key);
|
||||||
{
|
if (!Directory.Exists(directory))
|
||||||
personKeyTo.Add(locationContainer.PersonKey.Value, []);
|
_ = Directory.CreateDirectory(directory);
|
||||||
if (!personKeyTo.TryGetValue(locationContainer.PersonKey.Value, out yearTo))
|
WriteVsCodeFiles(eDistanceContentDirectory, displayDirectoryName, directory);
|
||||||
throw new Exception();
|
relationContainers = distance.GetRelationContainers(configuration.DistanceLimits, configuration.FaceDistancePermyriad, configuration.LocationContainerDistanceTake, configuration.LocationContainerDistanceTolerance.Value, group.RelationContainersCollection);
|
||||||
}
|
movedFiles = GetMoveFiles(configuration, group.Key, take, isCounterPersonYear, displayDirectoryName, relationContainers);
|
||||||
if (!yearTo.TryGetValue(locationContainer.CreationDateOnly.Year, out collection))
|
WriteFile(take, group.PersonKey, isCounterPersonYear, personKeyFormatted, displayDirectoryName, directory, ticks, uri, relationContainers, movedFiles);
|
||||||
{
|
|
||||||
yearTo.Add(locationContainer.CreationDateOnly.Year, []);
|
|
||||||
if (!yearTo.TryGetValue(locationContainer.CreationDateOnly.Year, out collection))
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
collection.Add(locationContainer);
|
|
||||||
}
|
}
|
||||||
return personKeyTo;
|
if (string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory))
|
||||||
|
_ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
|
||||||
|
else
|
||||||
|
AddDisplayDirectoryNames(configuration, eDistanceContentDirectory, readOnlyPersonKeyFormattedToPersonContainer, readOnlyPersonKeyToPersonContainerCollection, groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadOnlyCollection<Group> GetGroups(Configuration configuration, List<LocationContainer> locationContainers)
|
private static ReadOnlyCollection<Group> GetGroups(Configuration configuration, List<LocationContainer> locationContainers)
|
||||||
@ -90,6 +102,121 @@ internal abstract class RelationLogic
|
|||||||
return results.AsReadOnly();
|
return results.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Dictionary<long, Dictionary<int, List<LocationContainer>>> GetPersonKeyTo(Configuration configuration, List<LocationContainer> locationContainers)
|
||||||
|
{
|
||||||
|
List<LocationContainer>? collection;
|
||||||
|
Dictionary<int, List<LocationContainer>>? yearTo;
|
||||||
|
Dictionary<long, Dictionary<int, List<LocationContainer>>> personKeyTo = [];
|
||||||
|
foreach (LocationContainer locationContainer in locationContainers)
|
||||||
|
{
|
||||||
|
if (locationContainer.PersonKey is null)
|
||||||
|
continue;
|
||||||
|
if (!locationContainer.FromDistanceContent)
|
||||||
|
continue;
|
||||||
|
if (!locationContainer.FilePath.FullName.Contains(configuration.LocationContainerDirectoryPattern))
|
||||||
|
continue;
|
||||||
|
if (!personKeyTo.TryGetValue(locationContainer.PersonKey.Value, out yearTo))
|
||||||
|
{
|
||||||
|
personKeyTo.Add(locationContainer.PersonKey.Value, []);
|
||||||
|
if (!personKeyTo.TryGetValue(locationContainer.PersonKey.Value, out yearTo))
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
if (!yearTo.TryGetValue(locationContainer.CreationDateOnly.Year, out collection))
|
||||||
|
{
|
||||||
|
yearTo.Add(locationContainer.CreationDateOnly.Year, []);
|
||||||
|
if (!yearTo.TryGetValue(locationContainer.CreationDateOnly.Year, out collection))
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
collection.Add(locationContainer);
|
||||||
|
}
|
||||||
|
return personKeyTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetTake(int locationContainerDistanceTake, int count)
|
||||||
|
{
|
||||||
|
int result = locationContainerDistanceTake;
|
||||||
|
int subtract = (int)(locationContainerDistanceTake * .05);
|
||||||
|
if (subtract < 1)
|
||||||
|
subtract = 1;
|
||||||
|
if (count > 9000)
|
||||||
|
result -= subtract;
|
||||||
|
if (count > 8000)
|
||||||
|
result -= subtract;
|
||||||
|
if (count > 7000)
|
||||||
|
result -= subtract;
|
||||||
|
if (count > 6000)
|
||||||
|
result -= subtract;
|
||||||
|
if (count > 5000)
|
||||||
|
result -= subtract;
|
||||||
|
if (count > 4000)
|
||||||
|
result -= subtract;
|
||||||
|
if (count > 3000)
|
||||||
|
result -= subtract;
|
||||||
|
if (count > 2000)
|
||||||
|
result -= subtract;
|
||||||
|
if (count > 1000)
|
||||||
|
result -= subtract;
|
||||||
|
if (result < 3)
|
||||||
|
result = 3;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string? GetDisplayDirectoryName(ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, long personKey, string personKeyFormatted)
|
||||||
|
{
|
||||||
|
string? result;
|
||||||
|
PersonContainer? personContainer;
|
||||||
|
List<PersonContainer>? collection;
|
||||||
|
_ = readOnlyPersonKeyToPersonContainerCollection.TryGetValue(personKey, out collection);
|
||||||
|
if (collection is not null)
|
||||||
|
result = collection[0].DisplayDirectoryName;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!readOnlyPersonKeyFormattedToPersonContainer.TryGetValue(personKeyFormatted, out personContainer))
|
||||||
|
result = null;
|
||||||
|
else
|
||||||
|
result = personContainer.DisplayDirectoryName;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteVsCodeFiles(string eDistanceContentDirectory, string? displayDirectoryName, string directory)
|
||||||
|
{
|
||||||
|
string json;
|
||||||
|
string vsCodeDirectory = Path.Combine(directory, ".vscode");
|
||||||
|
if (!Directory.Exists(vsCodeDirectory))
|
||||||
|
_ = Directory.CreateDirectory(vsCodeDirectory);
|
||||||
|
if (displayDirectoryName is not null)
|
||||||
|
File.WriteAllText(Path.Combine(directory, $"_ {displayDirectoryName}.txt"), string.Empty);
|
||||||
|
json = /*lang=json*/ """{ "[markdown]": { "editor.wordWrap": "off" }, "foam.links.hover.enable": false, "foam.graph.style": { "background": "#202020", "node": { "note": "#f2cb1d", "distance": "green", "image": "orange", "placeholder": "white", } } }""";
|
||||||
|
_ = IPath.WriteAllText(Path.Combine(vsCodeDirectory, "settings.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
||||||
|
json = string.Concat("{ \"version\": \"2.0.0\", \"tasks\": [ { \"label\": \"MKLink\", \"type\": \"shell\", \"command\": \"New-Item\", \"args\": [ \"-ItemType\", \"Junction\", \"-Path\", \"'", directory.Replace('\\', '/'), "/()'\", \"-Target\", \"'", eDistanceContentDirectory.Replace('\\', '/'), "'\" ], \"problemMatcher\": [] } ] }");
|
||||||
|
_ = IPath.WriteAllText(Path.Combine(vsCodeDirectory, "tasks.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyDictionary<string, string> GetMoveFiles(Configuration configuration, string key, int take, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers)
|
||||||
|
{
|
||||||
|
ReadOnlyDictionary<string, string> results;
|
||||||
|
List<List<string>> linked = [];
|
||||||
|
for (int i = 0; i < 25; i++)
|
||||||
|
linked.Add([]);
|
||||||
|
foreach ((FileHolder fileHolder, ReadOnlyCollection<Relation> relations) in relationContainers)
|
||||||
|
{
|
||||||
|
foreach (Relation relation in relations.Take(take))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 25; i++)
|
||||||
|
{
|
||||||
|
if (!linked[i].Contains(relation.File))
|
||||||
|
{
|
||||||
|
linked[i].Add(relation.File);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results = MoveFiles(configuration, key, isCounterPersonYear, displayDirectoryName, relationContainers, linked);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
private static ReadOnlyDictionary<string, string> MoveFiles(Configuration configuration, string key, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers, List<List<string>> linked)
|
private static ReadOnlyDictionary<string, string> MoveFiles(Configuration configuration, string key, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers, List<List<string>> linked)
|
||||||
{
|
{
|
||||||
Dictionary<string, string> results = [];
|
Dictionary<string, string> results = [];
|
||||||
@ -205,91 +332,6 @@ internal abstract class RelationLogic
|
|||||||
return results.AsReadOnly();
|
return results.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string? GetDisplayDirectoryName(ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, long personKey, string personKeyFormatted)
|
|
||||||
{
|
|
||||||
string? result;
|
|
||||||
PersonContainer? personContainer;
|
|
||||||
List<PersonContainer>? collection;
|
|
||||||
_ = readOnlyPersonKeyToPersonContainerCollection.TryGetValue(personKey, out collection);
|
|
||||||
if (collection is not null)
|
|
||||||
result = collection[0].DisplayDirectoryName;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!readOnlyPersonKeyFormattedToPersonContainer.TryGetValue(personKeyFormatted, out personContainer))
|
|
||||||
result = null;
|
|
||||||
else
|
|
||||||
result = personContainer.DisplayDirectoryName;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetTake(int locationContainerDistanceTake, int count)
|
|
||||||
{
|
|
||||||
int result = locationContainerDistanceTake;
|
|
||||||
int subtract = (int)(locationContainerDistanceTake * .05);
|
|
||||||
if (subtract < 1)
|
|
||||||
subtract = 1;
|
|
||||||
if (count > 9000)
|
|
||||||
result -= subtract;
|
|
||||||
if (count > 8000)
|
|
||||||
result -= subtract;
|
|
||||||
if (count > 7000)
|
|
||||||
result -= subtract;
|
|
||||||
if (count > 6000)
|
|
||||||
result -= subtract;
|
|
||||||
if (count > 5000)
|
|
||||||
result -= subtract;
|
|
||||||
if (count > 4000)
|
|
||||||
result -= subtract;
|
|
||||||
if (count > 3000)
|
|
||||||
result -= subtract;
|
|
||||||
if (count > 2000)
|
|
||||||
result -= subtract;
|
|
||||||
if (count > 1000)
|
|
||||||
result -= subtract;
|
|
||||||
if (result < 3)
|
|
||||||
result = 3;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteVsCodeFiles(string eDistanceContentDirectory, string? displayDirectoryName, string directory)
|
|
||||||
{
|
|
||||||
string json;
|
|
||||||
string vsCodeDirectory = Path.Combine(directory, ".vscode");
|
|
||||||
if (!Directory.Exists(vsCodeDirectory))
|
|
||||||
_ = Directory.CreateDirectory(vsCodeDirectory);
|
|
||||||
if (displayDirectoryName is not null)
|
|
||||||
File.WriteAllText(Path.Combine(directory, $"_ {displayDirectoryName}.txt"), string.Empty);
|
|
||||||
json = /*lang=json*/ """{ "[markdown]": { "editor.wordWrap": "off" }, "foam.links.hover.enable": false, "foam.graph.style": { "background": "#202020", "node": { "note": "#f2cb1d", "distance": "green", "image": "orange", "placeholder": "white", } } }""";
|
|
||||||
_ = IPath.WriteAllText(Path.Combine(vsCodeDirectory, "settings.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
|
||||||
json = string.Concat("{ \"version\": \"2.0.0\", \"tasks\": [ { \"label\": \"MKLink\", \"type\": \"shell\", \"command\": \"New-Item\", \"args\": [ \"-ItemType\", \"Junction\", \"-Path\", \"'", directory.Replace('\\', '/'), "/()'\", \"-Target\", \"'", eDistanceContentDirectory.Replace('\\', '/'), "'\" ], \"problemMatcher\": [] } ] }");
|
|
||||||
_ = IPath.WriteAllText(Path.Combine(vsCodeDirectory, "tasks.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyDictionary<string, string> GetMoveFiles(Configuration configuration, string key, int take, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers)
|
|
||||||
{
|
|
||||||
ReadOnlyDictionary<string, string> results;
|
|
||||||
List<List<string>> linked = [];
|
|
||||||
for (int i = 0; i < 25; i++)
|
|
||||||
linked.Add([]);
|
|
||||||
foreach ((FileHolder fileHolder, ReadOnlyCollection<Relation> relations) in relationContainers)
|
|
||||||
{
|
|
||||||
foreach (Relation relation in relations.Take(take))
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 25; i++)
|
|
||||||
{
|
|
||||||
if (!linked[i].Contains(relation.File))
|
|
||||||
{
|
|
||||||
linked[i].Add(relation.File);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
results = MoveFiles(configuration, key, isCounterPersonYear, displayDirectoryName, relationContainers, linked);
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteFile(int take, long personKey, bool isCounterPersonYear, string personKeyFormatted, string? displayDirectoryName, string directory, long ticks, Uri uri, ReadOnlyCollection<RelationContainer> relationContainers, ReadOnlyDictionary<string, string> movedFiles)
|
private static void WriteFile(int take, long personKey, bool isCounterPersonYear, string personKeyFormatted, string? displayDirectoryName, string directory, long ticks, Uri uri, ReadOnlyCollection<RelationContainer> relationContainers, ReadOnlyDictionary<string, string> movedFiles)
|
||||||
{
|
{
|
||||||
string a;
|
string a;
|
||||||
@ -398,44 +440,4 @@ internal abstract class RelationLogic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SaveMappedRelations(Configuration configuration, Shared.Models.Methods.IDistance distance, string a2PeopleContentDirectory, string eDistanceContentDirectory, long ticks, List<LocationContainer> locationContainers, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection)
|
|
||||||
{
|
|
||||||
int take;
|
|
||||||
string directory;
|
|
||||||
bool isCounterPersonYear;
|
|
||||||
string personKeyFormatted;
|
|
||||||
string? displayDirectoryName;
|
|
||||||
Uri uri = new(eDistanceContentDirectory);
|
|
||||||
ReadOnlyDictionary<string, string> movedFiles;
|
|
||||||
ReadOnlyCollection<RelationContainer> relationContainers;
|
|
||||||
ReadOnlyCollection<Group> groups = GetGroups(configuration, locationContainers);
|
|
||||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
|
||||||
string message = $") Save Mapped Relations - {totalSeconds} total second(s)";
|
|
||||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
|
||||||
using ProgressBar progressBar = new(groups.Count, message, options);
|
|
||||||
foreach (Group group in groups)
|
|
||||||
{
|
|
||||||
if (configuration.LocationContainerDistanceTolerance is null)
|
|
||||||
break;
|
|
||||||
progressBar.Tick();
|
|
||||||
if (group.RelationContainersCollection.Count == 0)
|
|
||||||
continue;
|
|
||||||
take = GetTake(configuration.LocationContainerDistanceTake, group.RelationContainersCollection.Count);
|
|
||||||
isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(new DateTime(group.PersonKey).Year);
|
|
||||||
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, group.PersonKey);
|
|
||||||
displayDirectoryName = GetDisplayDirectoryName(readOnlyPersonKeyToPersonContainerCollection, readOnlyPersonKeyFormattedToPersonContainer, group.PersonKey, personKeyFormatted);
|
|
||||||
directory = Path.Combine(a2PeopleContentDirectory, $"{ticks}-{configuration.LocationContainerDistanceTolerance.Value}", personKeyFormatted, group.Key);
|
|
||||||
if (!Directory.Exists(directory))
|
|
||||||
_ = Directory.CreateDirectory(directory);
|
|
||||||
WriteVsCodeFiles(eDistanceContentDirectory, displayDirectoryName, directory);
|
|
||||||
relationContainers = distance.GetRelationContainers(configuration.DistanceLimits, configuration.FaceDistancePermyriad, configuration.LocationContainerDistanceTake, configuration.LocationContainerDistanceTolerance.Value, group.RelationContainersCollection);
|
|
||||||
movedFiles = GetMoveFiles(configuration, group.Key, take, isCounterPersonYear, displayDirectoryName, relationContainers);
|
|
||||||
WriteFile(take, group.PersonKey, isCounterPersonYear, personKeyFormatted, displayDirectoryName, directory, ticks, uri, relationContainers, movedFiles);
|
|
||||||
}
|
|
||||||
if (string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory))
|
|
||||||
_ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
|
|
||||||
else
|
|
||||||
AddDisplayDirectoryNames(configuration, eDistanceContentDirectory, readOnlyPersonKeyFormattedToPersonContainer, readOnlyPersonKeyToPersonContainerCollection, groups);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -51,22 +51,110 @@ public class A_Property
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
|
public void SetAngleBracketCollection(string aResultsFullGroupDirectory, string sourceDirectory, bool anyNullOrNoIsUniqueFileName = true)
|
||||||
{
|
{
|
||||||
string[] segments = directory.Split(cei.Combined);
|
_AngleBracketCollection.Clear();
|
||||||
string? checkDirectory = segments.Length == 1 ?
|
if (!anyNullOrNoIsUniqueFileName)
|
||||||
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
_AngleBracketCollection.AddRange([Path.Combine(aResultsFullGroupDirectory, "<>")]);
|
||||||
segments.Length == 2 ?
|
else
|
||||||
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
_AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(_PropertyConfiguration,
|
||||||
null;
|
sourceDirectory,
|
||||||
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
aResultsFullGroupDirectory,
|
||||||
|
contentDescription: string.Empty,
|
||||||
|
singletonDescription: "Properties for each image",
|
||||||
|
collectionDescription: string.Empty,
|
||||||
|
converted: false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SavePropertyParallelWork(long ticks, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, int t, Container.Models.Container[] containers)
|
||||||
|
{
|
||||||
|
int total = 0;
|
||||||
|
string message;
|
||||||
|
int totalSeconds;
|
||||||
|
bool anyNullOrNoIsUniqueFileName;
|
||||||
|
List<Exception> exceptions = [];
|
||||||
|
Container.Models.Container container;
|
||||||
|
int containersLength = containers.Length;
|
||||||
|
const string outputResolution = "Original";
|
||||||
|
List<Tuple<string, DateTime>> sourceDirectoryChanges = [];
|
||||||
|
string propertyRoot = IResult.GetResultsGroupDirectory(_PropertyConfiguration, nameof(A_Property));
|
||||||
|
for (int i = 0; i < containers.Length; i++)
|
||||||
{
|
{
|
||||||
string checkFile = Path.Combine(checkDirectory, fileName);
|
container = containers[i];
|
||||||
if (File.Exists(checkFile))
|
if (container.Items.Count == 0)
|
||||||
{
|
continue;
|
||||||
File.Move(checkFile, fileInfo.FullName);
|
sourceDirectoryChanges.Clear();
|
||||||
fileInfo.Refresh();
|
if (container.Items.Count == 0)
|
||||||
}
|
continue;
|
||||||
|
anyNullOrNoIsUniqueFileName = container.Items.Any(l => !l.IsUniqueFileName);
|
||||||
|
SetAngleBracketCollection(container.SourceDirectory, anyNullOrNoIsUniqueFileName);
|
||||||
|
totalSeconds = (int)Math.Truncate(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||||
|
message = $"{i + 1:000} [{container.Items.Count:000}] / {containersLength:000} - {total} / {t} total - {totalSeconds} total second(s) - {outputResolution} - {container.SourceDirectory}";
|
||||||
|
SavePropertyParallelWork(_MaxDegreeOfParallelism, metadata, exceptions, sourceDirectoryChanges, container, container.Items, message);
|
||||||
|
if (exceptions.Count == container.Items.Count)
|
||||||
|
throw new Exception(string.Concat("All in [", container.SourceDirectory, "]failed!"));
|
||||||
|
if (exceptions.Count != 0)
|
||||||
|
_ExceptionsDirectories.Add(container.SourceDirectory);
|
||||||
|
total += container.Items.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetAngleBracketCollection(string sourceDirectory, bool anyNullOrNoIsUniqueFileName)
|
||||||
|
{
|
||||||
|
_AngleBracketCollection.Clear();
|
||||||
|
string aResultsFullGroupDirectory = IResult.GetResultsFullGroupDirectory(_PropertyConfiguration,
|
||||||
|
nameof(A_Property),
|
||||||
|
string.Empty,
|
||||||
|
includeResizeGroup: false,
|
||||||
|
includeModel: false,
|
||||||
|
includePredictorModel: false);
|
||||||
|
SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SavePropertyParallelWork(int maxDegreeOfParallelism, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, Container.Models.Container container, ReadOnlyCollection<Item> items, string message)
|
||||||
|
{
|
||||||
|
List<Tuple<string, DateTime>> sourceDirectoryFileTuples = [];
|
||||||
|
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||||
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||||
|
using ProgressBar progressBar = new(items.Count, message, options);
|
||||||
|
_ = Parallel.For(0, items.Count, parallelOptions, (i, state) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
long ticks = DateTime.Now.Ticks;
|
||||||
|
DateTime dateTime = DateTime.Now;
|
||||||
|
List<Tuple<string, DateTime>> collection;
|
||||||
|
SavePropertyParallelForWork(metadata, container.SourceDirectory, sourceDirectoryChanges, sourceDirectoryFileTuples, items[i]);
|
||||||
|
if (i == 0 || sourceDirectoryChanges.Count != 0)
|
||||||
|
progressBar.Tick();
|
||||||
|
lock (sourceDirectoryFileTuples)
|
||||||
|
collection = (from l in sourceDirectoryFileTuples where l.Item2 > dateTime select l).ToList();
|
||||||
|
lock (sourceDirectoryChanges)
|
||||||
|
sourceDirectoryChanges.AddRange(collection);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
lock (exceptions)
|
||||||
|
exceptions.Add(ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SavePropertyParallelForWork(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, string sourceDirectory, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item item)
|
||||||
|
{
|
||||||
|
Shared.Models.Property property;
|
||||||
|
List<string> parseExceptions = [];
|
||||||
|
bool isIgnoreExtension = item.IsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(item.FilePath.ExtensionLowered);
|
||||||
|
string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{item.FilePath.NameWithoutExtension}{item.FilePath.ExtensionLowered}");
|
||||||
|
if (item.IsValidImageFormatExtension && item.FilePath.FullName.Length == filteredSourceDirectoryFileExtensionLowered.Length && item.FilePath.FullName != filteredSourceDirectoryFileExtensionLowered)
|
||||||
|
File.Move(item.FilePath.FullName, filteredSourceDirectoryFileExtensionLowered);
|
||||||
|
if (item.FileSizeChanged is null || item.FileSizeChanged.Value || item.LastWriteTimeChanged is null || item.LastWriteTimeChanged.Value || item.Property is null)
|
||||||
|
{
|
||||||
|
property = GetImageProperty(metadata, item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension);
|
||||||
|
lock (sourceDirectoryChanges)
|
||||||
|
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
|
||||||
|
lock (item)
|
||||||
|
item.Update(property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,110 +282,22 @@ public class A_Property
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAngleBracketCollection(string aResultsFullGroupDirectory, string sourceDirectory, bool anyNullOrNoIsUniqueFileName = true)
|
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
|
||||||
{
|
{
|
||||||
_AngleBracketCollection.Clear();
|
string[] segments = directory.Split(cei.Combined);
|
||||||
if (!anyNullOrNoIsUniqueFileName)
|
string? checkDirectory = segments.Length == 1 ?
|
||||||
_AngleBracketCollection.AddRange([Path.Combine(aResultsFullGroupDirectory, "<>")]);
|
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
||||||
else
|
segments.Length == 2 ?
|
||||||
_AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(_PropertyConfiguration,
|
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
||||||
sourceDirectory,
|
null;
|
||||||
aResultsFullGroupDirectory,
|
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
||||||
contentDescription: string.Empty,
|
|
||||||
singletonDescription: "Properties for each image",
|
|
||||||
collectionDescription: string.Empty,
|
|
||||||
converted: false));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SavePropertyParallelForWork(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, string sourceDirectory, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item item)
|
|
||||||
{
|
|
||||||
Shared.Models.Property property;
|
|
||||||
List<string> parseExceptions = [];
|
|
||||||
bool isIgnoreExtension = item.IsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(item.FilePath.ExtensionLowered);
|
|
||||||
string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{item.FilePath.NameWithoutExtension}{item.FilePath.ExtensionLowered}");
|
|
||||||
if (item.IsValidImageFormatExtension && item.FilePath.FullName.Length == filteredSourceDirectoryFileExtensionLowered.Length && item.FilePath.FullName != filteredSourceDirectoryFileExtensionLowered)
|
|
||||||
File.Move(item.FilePath.FullName, filteredSourceDirectoryFileExtensionLowered);
|
|
||||||
if (item.FileSizeChanged is null || item.FileSizeChanged.Value || item.LastWriteTimeChanged is null || item.LastWriteTimeChanged.Value || item.Property is null)
|
|
||||||
{
|
{
|
||||||
property = GetImageProperty(metadata, item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension);
|
string checkFile = Path.Combine(checkDirectory, fileName);
|
||||||
lock (sourceDirectoryChanges)
|
if (File.Exists(checkFile))
|
||||||
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
|
{
|
||||||
lock (item)
|
File.Move(checkFile, fileInfo.FullName);
|
||||||
item.Update(property);
|
fileInfo.Refresh();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void SetAngleBracketCollection(string sourceDirectory, bool anyNullOrNoIsUniqueFileName)
|
|
||||||
{
|
|
||||||
_AngleBracketCollection.Clear();
|
|
||||||
string aResultsFullGroupDirectory = IResult.GetResultsFullGroupDirectory(_PropertyConfiguration,
|
|
||||||
nameof(A_Property),
|
|
||||||
string.Empty,
|
|
||||||
includeResizeGroup: false,
|
|
||||||
includeModel: false,
|
|
||||||
includePredictorModel: false);
|
|
||||||
SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SavePropertyParallelWork(int maxDegreeOfParallelism, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, Container.Models.Container container, ReadOnlyCollection<Item> items, string message)
|
|
||||||
{
|
|
||||||
List<Tuple<string, DateTime>> sourceDirectoryFileTuples = [];
|
|
||||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
|
||||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
|
||||||
using ProgressBar progressBar = new(items.Count, message, options);
|
|
||||||
_ = Parallel.For(0, items.Count, parallelOptions, (i, state) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
long ticks = DateTime.Now.Ticks;
|
|
||||||
DateTime dateTime = DateTime.Now;
|
|
||||||
List<Tuple<string, DateTime>> collection;
|
|
||||||
SavePropertyParallelForWork(metadata, container.SourceDirectory, sourceDirectoryChanges, sourceDirectoryFileTuples, items[i]);
|
|
||||||
if (i == 0 || sourceDirectoryChanges.Count != 0)
|
|
||||||
progressBar.Tick();
|
|
||||||
lock (sourceDirectoryFileTuples)
|
|
||||||
collection = (from l in sourceDirectoryFileTuples where l.Item2 > dateTime select l).ToList();
|
|
||||||
lock (sourceDirectoryChanges)
|
|
||||||
sourceDirectoryChanges.AddRange(collection);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
lock (exceptions)
|
|
||||||
exceptions.Add(ex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SavePropertyParallelWork(long ticks, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, int t, Container.Models.Container[] containers)
|
|
||||||
{
|
|
||||||
int total = 0;
|
|
||||||
string message;
|
|
||||||
int totalSeconds;
|
|
||||||
bool anyNullOrNoIsUniqueFileName;
|
|
||||||
List<Exception> exceptions = [];
|
|
||||||
Container.Models.Container container;
|
|
||||||
int containersLength = containers.Length;
|
|
||||||
const string outputResolution = "Original";
|
|
||||||
List<Tuple<string, DateTime>> sourceDirectoryChanges = [];
|
|
||||||
string propertyRoot = IResult.GetResultsGroupDirectory(_PropertyConfiguration, nameof(A_Property));
|
|
||||||
for (int i = 0; i < containers.Length; i++)
|
|
||||||
{
|
|
||||||
container = containers[i];
|
|
||||||
if (container.Items.Count == 0)
|
|
||||||
continue;
|
|
||||||
sourceDirectoryChanges.Clear();
|
|
||||||
if (container.Items.Count == 0)
|
|
||||||
continue;
|
|
||||||
anyNullOrNoIsUniqueFileName = container.Items.Any(l => !l.IsUniqueFileName);
|
|
||||||
SetAngleBracketCollection(container.SourceDirectory, anyNullOrNoIsUniqueFileName);
|
|
||||||
totalSeconds = (int)Math.Truncate(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
|
||||||
message = $"{i + 1:000} [{container.Items.Count:000}] / {containersLength:000} - {total} / {t} total - {totalSeconds} total second(s) - {outputResolution} - {container.SourceDirectory}";
|
|
||||||
SavePropertyParallelWork(_MaxDegreeOfParallelism, metadata, exceptions, sourceDirectoryChanges, container, container.Items, message);
|
|
||||||
if (exceptions.Count == container.Items.Count)
|
|
||||||
throw new Exception(string.Concat("All in [", container.SourceDirectory, "]failed!"));
|
|
||||||
if (exceptions.Count != 0)
|
|
||||||
_ExceptionsDirectories.Add(container.SourceDirectory);
|
|
||||||
total += container.Items.Count;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,69 +10,80 @@ namespace View_by_Distance.Property.Models.Stateless;
|
|||||||
public interface IProperty
|
public interface IProperty
|
||||||
{
|
{
|
||||||
|
|
||||||
string TestStatic_DateTimeFormat() =>
|
const string DateTimeFormat = "yyyy:MM:dd HH:mm:ss";
|
||||||
DateTimeFormat();
|
|
||||||
static string DateTimeFormat() =>
|
|
||||||
"yyyy:MM:dd HH:mm:ss";
|
|
||||||
|
|
||||||
byte[] TestStatic_GetBytes(string value) =>
|
// public
|
||||||
GetBytes(value);
|
|
||||||
static byte[] GetBytes(string value) =>
|
|
||||||
Property.GetBytes(value);
|
|
||||||
|
|
||||||
DateTime? TestStatic_GetDateTime(string dateTimeFormat, string? value) =>
|
|
||||||
GetDateTime(dateTimeFormat, value);
|
|
||||||
static DateTime? GetDateTime(string dateTimeFormat, string? value) =>
|
|
||||||
Property.GetDateTime(dateTimeFormat, value);
|
|
||||||
|
|
||||||
PropertyItem TestStatic_GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value) =>
|
|
||||||
GetPropertyItem(constructorInfo, id, type, value);
|
|
||||||
static PropertyItem GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value) =>
|
|
||||||
Property.GetPropertyItem(constructorInfo, id, type, value);
|
|
||||||
|
|
||||||
(string?, DateTime[], Shared.Models.Property) TestStatic_GetProperty(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, Shared.Models.Property? property, bool isIgnoreExtension, bool isValidImageFormatExtension, int? id, ASCIIEncoding asciiEncoding) =>
|
|
||||||
GetProperty(populateId, metadata, filePath, property, isIgnoreExtension, isValidImageFormatExtension, id, asciiEncoding);
|
|
||||||
static (string?, DateTime[], Shared.Models.Property) GetProperty(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, Shared.Models.Property? property, bool isIgnoreExtension, bool isValidImageFormatExtension, int? id, ASCIIEncoding asciiEncoding) =>
|
|
||||||
Property.GetProperty(populateId, metadata, filePath, property, isIgnoreExtension, isValidImageFormatExtension, id, asciiEncoding);
|
|
||||||
|
|
||||||
(DateTime?, DateTime[], int?, string?) TestStatic_Get(IPropertyConfiguration propertyConfiguration, bool populateId, FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
|
||||||
Get(propertyConfiguration, populateId, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
|
||||||
static (DateTime?, DateTime[], int?, string?) Get(IPropertyConfiguration propertyConfiguration, bool populateId, FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
|
||||||
Property.Get(populateId, null, FilePath.Get(propertyConfiguration, fileHolder, index: null), isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
|
||||||
|
|
||||||
(DateTime?, DateTime[], int?, string?) TestStatic_Get(bool populateId, FilePath filePath, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
|
||||||
Get(populateId, filePath, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
|
||||||
static (DateTime?, DateTime[], int?, string?) Get(bool populateId, FilePath filePath, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
|
||||||
Property.Get(populateId, null, filePath, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
|
||||||
|
|
||||||
(DateTime?, DateTime[], int?, string?) TestStatic_Get(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
|
||||||
Get(populateId, metadata, filePath, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
|
||||||
static (DateTime?, DateTime[], int?, string?) Get(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
static (DateTime?, DateTime[], int?, string?) Get(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
||||||
Property.Get(populateId, metadata, filePath, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
Property.Get(populateId, metadata, filePath, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
||||||
|
|
||||||
(DateTime?, DateTime[], int?, string?) TestStatic_Get(IPropertyConfiguration propertyConfiguration, bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
// public
|
||||||
Get(propertyConfiguration, populateId, metadata, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
static (DateTime?, DateTime[], int?, string?) Get(IPropertyConfiguration propertyConfiguration, bool populateId, FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
||||||
static (DateTime?, DateTime[], int?, string?) Get(IPropertyConfiguration propertyConfiguration, bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
Property.Get(populateId, null, FilePath.Get(propertyConfiguration, fileHolder, index: null), isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
||||||
Property.Get(populateId, metadata, FilePath.Get(propertyConfiguration, fileHolder, index: null), isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
|
||||||
|
|
||||||
TimeSpan TestStatic_GetThreeStandardDeviationHigh(int minimum, Container.Models.Container container) =>
|
public static byte[] GetBytes(string value) =>
|
||||||
GetThreeStandardDeviationHigh(minimum, container);
|
Property.GetBytes(value);
|
||||||
static TimeSpan GetThreeStandardDeviationHigh(int minimum, Container.Models.Container container) =>
|
|
||||||
Property.GetThreeStandardDeviationHigh(minimum, container);
|
|
||||||
|
|
||||||
(int, List<DateTime>, List<Shared.Models.Item>) TestStatic_Get(Container.Models.Container container, TimeSpan threeStandardDeviationHigh, int i) =>
|
public static DateTime? GetDateTime(string dateTimeFormat, string? value) =>
|
||||||
Get(container, threeStandardDeviationHigh, i);
|
Property.GetDateTime(dateTimeFormat, value);
|
||||||
static (int, List<DateTime>, List<Shared.Models.Item>) Get(Container.Models.Container container, TimeSpan threeStandardDeviationHigh, int i) =>
|
|
||||||
Property.Get(container, threeStandardDeviationHigh, i);
|
|
||||||
|
|
||||||
bool TestStatic_Any(Container.Models.Container[] propertyHolderCollections) =>
|
public static double GetStandardDeviation(List<long> values, double average) =>
|
||||||
Any(propertyHolderCollections);
|
|
||||||
static bool Any(Container.Models.Container[] propertyHolderCollections) =>
|
|
||||||
Property.Any(propertyHolderCollections);
|
|
||||||
|
|
||||||
double TestStatic_GetStandardDeviation(List<long> values, double average) =>
|
|
||||||
GetStandardDeviation(values, average);
|
|
||||||
static double GetStandardDeviation(List<long> values, double average) =>
|
|
||||||
Property.GetStandardDeviation(values, average);
|
Property.GetStandardDeviation(values, average);
|
||||||
|
|
||||||
|
public static bool Any(Container.Models.Container[] propertyHolderCollections) =>
|
||||||
|
Property.Any(propertyHolderCollections);
|
||||||
|
|
||||||
|
public static TimeSpan GetThreeStandardDeviationHigh(int minimum, Container.Models.Container container) =>
|
||||||
|
Property.GetThreeStandardDeviationHigh(minimum, container);
|
||||||
|
|
||||||
|
public static PropertyItem GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value) =>
|
||||||
|
Property.GetPropertyItem(constructorInfo, id, type, value);
|
||||||
|
|
||||||
|
public static (int, List<DateTime>, List<Item>) Get(Container.Models.Container container, TimeSpan threeStandardDeviationHigh, int i) =>
|
||||||
|
Property.Get(container, threeStandardDeviationHigh, i);
|
||||||
|
|
||||||
|
public static (DateTime?, DateTime[], int?, string?) Get(bool populateId, FilePath filePath, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
||||||
|
Property.Get(populateId, null, filePath, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
||||||
|
|
||||||
|
public static (DateTime?, DateTime[], int?, string?) Get(IPropertyConfiguration propertyConfiguration, bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
||||||
|
Property.Get(populateId, metadata, FilePath.Get(propertyConfiguration, fileHolder, index: null), isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
||||||
|
|
||||||
|
public static (string?, DateTime[], Shared.Models.Property) GetProperty(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, Shared.Models.Property? property, bool isIgnoreExtension, bool isValidImageFormatExtension, int? id, ASCIIEncoding asciiEncoding) =>
|
||||||
|
Property.GetProperty(populateId, metadata, filePath, property, isIgnoreExtension, isValidImageFormatExtension, id, asciiEncoding);
|
||||||
|
|
||||||
|
internal byte[] TestStatic_GetBytes(string value) =>
|
||||||
|
GetBytes(value);
|
||||||
|
|
||||||
|
internal DateTime? TestStatic_GetDateTime(string dateTimeFormat, string? value) =>
|
||||||
|
GetDateTime(dateTimeFormat, value);
|
||||||
|
|
||||||
|
internal double TestStatic_GetStandardDeviation(List<long> values, double average) =>
|
||||||
|
GetStandardDeviation(values, average);
|
||||||
|
|
||||||
|
internal bool TestStatic_Any(Container.Models.Container[] propertyHolderCollections) =>
|
||||||
|
Any(propertyHolderCollections);
|
||||||
|
|
||||||
|
internal TimeSpan TestStatic_GetThreeStandardDeviationHigh(int minimum, Container.Models.Container container) =>
|
||||||
|
GetThreeStandardDeviationHigh(minimum, container);
|
||||||
|
|
||||||
|
internal PropertyItem TestStatic_GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value) =>
|
||||||
|
GetPropertyItem(constructorInfo, id, type, value);
|
||||||
|
|
||||||
|
internal (int, List<DateTime>, List<Item>) TestStatic_Get(Container.Models.Container container, TimeSpan threeStandardDeviationHigh, int i) =>
|
||||||
|
Get(container, threeStandardDeviationHigh, i);
|
||||||
|
|
||||||
|
internal (DateTime?, DateTime[], int?, string?) TestStatic_Get(bool populateId, FilePath filePath, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
||||||
|
Get(populateId, filePath, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
||||||
|
|
||||||
|
internal (DateTime?, DateTime[], int?, string?) TestStatic_Get(IPropertyConfiguration propertyConfiguration, bool populateId, FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
||||||
|
Get(propertyConfiguration, populateId, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
||||||
|
|
||||||
|
internal (DateTime?, DateTime[], int?, string?) TestStatic_Get(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
||||||
|
Get(populateId, metadata, filePath, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
||||||
|
|
||||||
|
internal (DateTime?, DateTime[], int?, string?) TestStatic_Get(IPropertyConfiguration propertyConfiguration, bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
|
||||||
|
Get(propertyConfiguration, populateId, metadata, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
||||||
|
|
||||||
|
internal (string?, DateTime[], Shared.Models.Property) TestStatic_GetProperty(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, Shared.Models.Property? property, bool isIgnoreExtension, bool isValidImageFormatExtension, int? id, ASCIIEncoding asciiEncoding) =>
|
||||||
|
GetProperty(populateId, metadata, filePath, property, isIgnoreExtension, isValidImageFormatExtension, id, asciiEncoding);
|
||||||
|
|
||||||
}
|
}
|
@ -3,44 +3,52 @@ namespace View_by_Distance.Property.Models.Stateless;
|
|||||||
public interface IResult
|
public interface IResult
|
||||||
{
|
{
|
||||||
|
|
||||||
string TestStatic_GetRelativePath(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string path) =>
|
public static string GetRelativePath(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string path) =>
|
||||||
GetRelativePath(propertyConfiguration, path);
|
|
||||||
static string GetRelativePath(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string path) =>
|
|
||||||
Result.GetRelativePath(propertyConfiguration, path);
|
Result.GetRelativePath(propertyConfiguration, path);
|
||||||
|
|
||||||
string TestStatic_GetResultsGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, bool create) =>
|
public static string GetResultsGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description) =>
|
||||||
GetResultsGroupDirectory(propertyConfiguration, description, create);
|
|
||||||
static string GetResultsGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, bool create) =>
|
|
||||||
Result.GetResultsGroupDirectory(propertyConfiguration, description, create);
|
|
||||||
|
|
||||||
string TestStatic_GetResultsGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description) =>
|
|
||||||
GetResultsGroupDirectory(propertyConfiguration, description);
|
|
||||||
static string GetResultsGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description) =>
|
|
||||||
Result.GetResultsGroupDirectory(propertyConfiguration, description, create: true);
|
Result.GetResultsGroupDirectory(propertyConfiguration, description, create: true);
|
||||||
|
|
||||||
string TestStatic_GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description) =>
|
public static string GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description) =>
|
||||||
GetResultsDateGroupDirectory(propertyConfiguration, description);
|
|
||||||
static string GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description) =>
|
|
||||||
Result.GetResultsDateGroupDirectory(propertyConfiguration, description);
|
Result.GetResultsDateGroupDirectory(propertyConfiguration, description);
|
||||||
|
|
||||||
string TestStatic_GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string jsonGroup) =>
|
public static string GetResultsGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, bool create) =>
|
||||||
GetResultsDateGroupDirectory(propertyConfiguration, description, jsonGroup);
|
Result.GetResultsGroupDirectory(propertyConfiguration, description, create);
|
||||||
static string GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string jsonGroup) =>
|
|
||||||
|
public static string GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string jsonGroup) =>
|
||||||
Result.GetResultsDateGroupDirectory(propertyConfiguration, description, jsonGroup);
|
Result.GetResultsDateGroupDirectory(propertyConfiguration, description, jsonGroup);
|
||||||
|
|
||||||
List<string> TestStatic_GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription, bool converted) =>
|
public static string GetResultsFullGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) =>
|
||||||
GetDirectoryInfoCollection(propertyConfiguration, sourceDirectory, dateGroupDirectory, contentDescription, singletonDescription, collectionDescription, converted);
|
|
||||||
static List<string> GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription, bool converted) =>
|
|
||||||
Result.GetDirectoryInfoCollection(propertyConfiguration, sourceDirectory, dateGroupDirectory, contentDescription, singletonDescription, collectionDescription, converted);
|
|
||||||
|
|
||||||
string TestStatic_GetResultsFullGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) =>
|
|
||||||
GetResultsFullGroupDirectory(propertyConfiguration, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel);
|
|
||||||
static string GetResultsFullGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) =>
|
|
||||||
Result.GetResultsFullGroupDirectory(propertyConfiguration, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel);
|
Result.GetResultsFullGroupDirectory(propertyConfiguration, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel);
|
||||||
|
|
||||||
List<string> TestStatic_GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) =>
|
public static List<string> GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription, bool converted) =>
|
||||||
GetDirectoryInfoCollection(propertyConfiguration, sourceDirectory, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel, contentDescription, singletonDescription, collectionDescription);
|
Result.GetDirectoryInfoCollection(propertyConfiguration, sourceDirectory, dateGroupDirectory, contentDescription, singletonDescription, collectionDescription, converted);
|
||||||
static List<string> GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) =>
|
|
||||||
|
public static List<string> GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) =>
|
||||||
Result.GetDirectoryInfoCollection(propertyConfiguration, sourceDirectory, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel, contentDescription, singletonDescription, collectionDescription);
|
Result.GetDirectoryInfoCollection(propertyConfiguration, sourceDirectory, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel, contentDescription, singletonDescription, collectionDescription);
|
||||||
|
|
||||||
|
internal string TestStatic_GetRelativePath(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string path) =>
|
||||||
|
GetRelativePath(propertyConfiguration, path);
|
||||||
|
|
||||||
|
internal string TestStatic_GetResultsGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description) =>
|
||||||
|
GetResultsGroupDirectory(propertyConfiguration, description);
|
||||||
|
|
||||||
|
internal string TestStatic_GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description) =>
|
||||||
|
GetResultsDateGroupDirectory(propertyConfiguration, description);
|
||||||
|
|
||||||
|
internal string TestStatic_GetResultsGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, bool create) =>
|
||||||
|
GetResultsGroupDirectory(propertyConfiguration, description, create);
|
||||||
|
|
||||||
|
internal string TestStatic_GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string jsonGroup) =>
|
||||||
|
GetResultsDateGroupDirectory(propertyConfiguration, description, jsonGroup);
|
||||||
|
|
||||||
|
internal string TestStatic_GetResultsFullGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) =>
|
||||||
|
GetResultsFullGroupDirectory(propertyConfiguration, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel);
|
||||||
|
|
||||||
|
internal List<string> TestStatic_GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription, bool converted) =>
|
||||||
|
GetDirectoryInfoCollection(propertyConfiguration, sourceDirectory, dateGroupDirectory, contentDescription, singletonDescription, collectionDescription, converted);
|
||||||
|
|
||||||
|
internal List<string> TestStatic_GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) =>
|
||||||
|
GetDirectoryInfoCollection(propertyConfiguration, sourceDirectory, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel, contentDescription, singletonDescription, collectionDescription);
|
||||||
|
|
||||||
}
|
}
|
@ -14,56 +14,53 @@ namespace View_by_Distance.Property.Models.Stateless;
|
|||||||
internal partial class Property
|
internal partial class Property
|
||||||
{
|
{
|
||||||
|
|
||||||
[GeneratedRegex(@"\D+")]
|
internal static TimeSpan GetThreeStandardDeviationHigh(int minimum, Container.Models.Container container)
|
||||||
private static partial Regex Digit();
|
|
||||||
|
|
||||||
private static List<DateTime> GetDateTimes(DateTime dateTimeFromName, DateTime?[] dateTimes)
|
|
||||||
{
|
{
|
||||||
List<DateTime> results = [dateTimeFromName];
|
TimeSpan result;
|
||||||
foreach (DateTime? dateTime in dateTimes)
|
DateTime? minimumDateTime;
|
||||||
|
List<long> ticksCollection = [];
|
||||||
|
foreach (Item item in container.Items)
|
||||||
{
|
{
|
||||||
if (dateTime is null)
|
if (item.Property is null)
|
||||||
continue;
|
continue;
|
||||||
results.Add(dateTime.Value);
|
minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
|
||||||
|
if (minimumDateTime is null)
|
||||||
|
continue;
|
||||||
|
ticksCollection.Add(minimumDateTime.Value.Ticks);
|
||||||
}
|
}
|
||||||
return results;
|
long threeStandardDeviationHigh;
|
||||||
|
long min;
|
||||||
|
if (ticksCollection.Count == 0)
|
||||||
|
min = 0;
|
||||||
|
else
|
||||||
|
min = ticksCollection.Min();
|
||||||
|
if (ticksCollection.Count < minimum)
|
||||||
|
threeStandardDeviationHigh = long.MaxValue;
|
||||||
|
else
|
||||||
|
threeStandardDeviationHigh = GetThreeStandardDeviationHigh(ref ticksCollection, min);
|
||||||
|
result = new TimeSpan(threeStandardDeviationHigh - min);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<DateTime> GetDateTimes(DateTime?[] dateTimes, DateTime?[] metadataDateTimes)
|
private static long GetThreeStandardDeviationHigh(ref List<long> ticksCollection, long min)
|
||||||
{
|
{
|
||||||
List<DateTime> results = [];
|
long result;
|
||||||
foreach (DateTime? dateTime in metadataDateTimes)
|
ticksCollection = (from l in ticksCollection select l - min).ToList();
|
||||||
{
|
double sum = ticksCollection.Sum();
|
||||||
if (dateTime is null || results.Contains(dateTime.Value))
|
double average = sum / ticksCollection.Count;
|
||||||
continue;
|
double standardDeviation = GetStandardDeviation(ticksCollection, average);
|
||||||
results.Add(dateTime.Value);
|
result = (long)Math.Ceiling(average + min + (standardDeviation * 3));
|
||||||
}
|
return result;
|
||||||
foreach (DateTime? dateTime in dateTimes)
|
|
||||||
{
|
|
||||||
if (dateTime is null || results.Contains(dateTime.Value))
|
|
||||||
continue;
|
|
||||||
results.Add(dateTime.Value);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<DateTime> GetDateTimes(FilePath filePath, DateTime?[] dateTimes)
|
internal static double GetStandardDeviation(List<long> values, double average)
|
||||||
{
|
{
|
||||||
List<DateTime> results = [];
|
double result = 0;
|
||||||
string[] digits = Digit().Split(filePath.FullName);
|
if (values.Count == 0)
|
||||||
foreach (string digit in digits)
|
throw new Exception("Collection must have at least one value!");
|
||||||
{
|
double sum = values.Sum(l => (l - average) * (l - average));
|
||||||
if (digit.Length != 4 || digit[..2] is not "19" and not "20" || !int.TryParse(digit, out int year))
|
result = Math.Sqrt(sum / values.Count);
|
||||||
continue;
|
return result;
|
||||||
results.Add(new(year, 1, 1));
|
|
||||||
}
|
|
||||||
foreach (DateTime? dateTime in dateTimes)
|
|
||||||
{
|
|
||||||
if (dateTime is null)
|
|
||||||
continue;
|
|
||||||
results.Add(dateTime.Value);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static byte[] GetBytes(string value)
|
internal static byte[] GetBytes(string value)
|
||||||
@ -126,22 +123,40 @@ internal partial class Property
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<DateTime> GetDateTimes(DateTime?[] metadataDateTimes)
|
internal static bool Any(Container.Models.Container[] containers)
|
||||||
{
|
{
|
||||||
List<DateTime> results = [];
|
bool result = false;
|
||||||
foreach (DateTime? dateTime in metadataDateTimes)
|
foreach (Container.Models.Container container in containers)
|
||||||
{
|
{
|
||||||
if (dateTime is null || results.Contains(dateTime.Value))
|
if (container.Items.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
results.Add(dateTime.Value);
|
if ((from l in container.Items where l.Any() select true).Any())
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CA1416
|
internal static DateTime? GetDateTime(string dateTimeFormat, string? value)
|
||||||
|
{
|
||||||
|
DateTime? result;
|
||||||
|
string alternateFormat = "ddd MMM dd HH:mm:ss yyyy";
|
||||||
|
if (value is not null && DateTime.TryParse(value, out DateTime dateTime))
|
||||||
|
result = dateTime;
|
||||||
|
else if (value is not null && value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
|
||||||
|
result = dateTime;
|
||||||
|
else if (value is not null && value.Length == alternateFormat.Length && DateTime.TryParseExact(value, alternateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
|
||||||
|
result = dateTime;
|
||||||
|
else
|
||||||
|
result = null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
internal static PropertyItem GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value)
|
internal static PropertyItem GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value)
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CA1416
|
||||||
PropertyItem result = (PropertyItem)constructorInfo.Invoke(null);
|
PropertyItem result = (PropertyItem)constructorInfo.Invoke(null);
|
||||||
int length;
|
int length;
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
@ -161,27 +176,65 @@ internal partial class Property
|
|||||||
result.Len = length;
|
result.Len = length;
|
||||||
result.Type = type;
|
result.Type = type;
|
||||||
result.Value = bytes;
|
result.Value = bytes;
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning restore CA1416
|
#pragma warning restore CA1416
|
||||||
|
|
||||||
internal static DateTime? GetDateTime(string dateTimeFormat, string? value)
|
|
||||||
{
|
|
||||||
DateTime? result;
|
|
||||||
string alternateFormat = "ddd MMM dd HH:mm:ss yyyy";
|
|
||||||
if (value is not null && DateTime.TryParse(value, out DateTime dateTime))
|
|
||||||
result = dateTime;
|
|
||||||
else if (value is not null && value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
|
|
||||||
result = dateTime;
|
|
||||||
else if (value is not null && value.Length == alternateFormat.Length && DateTime.TryParseExact(value, alternateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
|
|
||||||
result = dateTime;
|
|
||||||
else
|
|
||||||
result = null;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CA1416
|
internal static (int, List<DateTime>, List<Item>) Get(Container.Models.Container container, TimeSpan threeStandardDeviationHigh, int i)
|
||||||
|
{
|
||||||
|
List<Item> results = [];
|
||||||
|
int j = i;
|
||||||
|
long? ticks;
|
||||||
|
TimeSpan timeSpan;
|
||||||
|
Item item;
|
||||||
|
DateTime? minimumDateTime;
|
||||||
|
Item nextItem;
|
||||||
|
DateTime? nextMinimumDateTime;
|
||||||
|
List<DateTime> dateTimes = [];
|
||||||
|
for (; j < container.Items.Count; j++)
|
||||||
|
{
|
||||||
|
ticks = null;
|
||||||
|
item = container.Items[j];
|
||||||
|
if (item.Property is null)
|
||||||
|
continue;
|
||||||
|
minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
|
||||||
|
if (minimumDateTime is null)
|
||||||
|
continue;
|
||||||
|
for (int k = j + 1; k < container.Items.Count; k++)
|
||||||
|
{
|
||||||
|
nextItem = container.Items[k];
|
||||||
|
if (nextItem.Property is null)
|
||||||
|
continue;
|
||||||
|
nextMinimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(nextItem.Property);
|
||||||
|
if (nextMinimumDateTime is null)
|
||||||
|
continue;
|
||||||
|
ticks = nextMinimumDateTime.Value.Ticks;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
results.Add(item);
|
||||||
|
dateTimes.Add(minimumDateTime.Value);
|
||||||
|
if (ticks.HasValue)
|
||||||
|
{
|
||||||
|
timeSpan = new(ticks.Value - minimumDateTime.Value.Ticks);
|
||||||
|
if (timeSpan > threeStandardDeviationHigh)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new(j, dateTimes, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static (DateTime?, DateTime[], int?, string?) Get(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding)
|
||||||
|
{
|
||||||
|
int? id = null;
|
||||||
|
string? message;
|
||||||
|
DateTime[] dateTimes;
|
||||||
|
Shared.Models.Property? property = null;
|
||||||
|
if (isIgnoreExtension || !isValidImageFormatExtension)
|
||||||
|
(message, dateTimes, property) = (null, [], null);
|
||||||
|
else
|
||||||
|
(message, dateTimes, property) = GetProperty(populateId, metadata, filePath, property, isIgnoreExtension, isValidImageFormatExtension, id, asciiEncoding);
|
||||||
|
return new(property?.DateTimeOriginal, dateTimes, property?.Id, message);
|
||||||
|
}
|
||||||
|
|
||||||
internal static (string?, DateTime[], Shared.Models.Property) GetProperty(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, Shared.Models.Property? property, bool isIgnoreExtension, bool isValidImageFormatExtension, int? id, ASCIIEncoding asciiEncoding)
|
internal static (string?, DateTime[], Shared.Models.Property) GetProperty(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, Shared.Models.Property? property, bool isIgnoreExtension, bool isValidImageFormatExtension, int? id, ASCIIEncoding asciiEncoding)
|
||||||
{
|
{
|
||||||
@ -225,6 +278,7 @@ internal partial class Property
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CA1416
|
||||||
using Image image = Image.FromFile(filePath.FullName);
|
using Image image = Image.FromFile(filePath.FullName);
|
||||||
width = image.Width;
|
width = image.Width;
|
||||||
height = image.Height;
|
height = image.Height;
|
||||||
@ -240,7 +294,7 @@ internal partial class Property
|
|||||||
bitmap.UnlockBits(bitmapData);
|
bitmap.UnlockBits(bitmapData);
|
||||||
id ??= Shared.Models.Stateless.Methods.IId.GetDeterministicHashCode(bytes);
|
id ??= Shared.Models.Stateless.Methods.IId.GetDeterministicHashCode(bytes);
|
||||||
}
|
}
|
||||||
dateTimeFormat = IProperty.DateTimeFormat();
|
dateTimeFormat = IProperty.DateTimeFormat;
|
||||||
if (image.PropertyIdList.Contains(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTime))
|
if (image.PropertyIdList.Contains(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTime))
|
||||||
{
|
{
|
||||||
propertyItem = image.GetPropertyItem(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTime);
|
propertyItem = image.GetPropertyItem(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTime);
|
||||||
@ -318,6 +372,7 @@ internal partial class Property
|
|||||||
keywords = Encoding.Unicode.GetString(propertyItem.Value).Trim('\0', ' ').Split(';');
|
keywords = Encoding.Unicode.GetString(propertyItem.Value).Trim('\0', ' ').Split(';');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
message = null;
|
message = null;
|
||||||
dateTimes = [new(filePath.LastWriteTicks), new(filePath.CreationTicks), dateTime, dateTimeDigitized, dateTimeOriginal, gpsDateStamp];
|
dateTimes = [new(filePath.LastWriteTicks), new(filePath.CreationTicks), dateTime, dateTimeDigitized, dateTimeOriginal, gpsDateStamp];
|
||||||
}
|
}
|
||||||
@ -351,127 +406,68 @@ internal partial class Property
|
|||||||
return (message, dateTimesByLogic.ToArray(), result);
|
return (message, dateTimesByLogic.ToArray(), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning restore CA1416
|
private static List<DateTime> GetDateTimes(DateTime?[] metadataDateTimes)
|
||||||
|
|
||||||
internal static (DateTime?, DateTime[], int?, string?) Get(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FilePath filePath, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding)
|
|
||||||
{
|
{
|
||||||
int? id = null;
|
List<DateTime> results = [];
|
||||||
string? message;
|
foreach (DateTime? dateTime in metadataDateTimes)
|
||||||
DateTime[] dateTimes;
|
|
||||||
Shared.Models.Property? property = null;
|
|
||||||
if (isIgnoreExtension || !isValidImageFormatExtension)
|
|
||||||
(message, dateTimes, property) = (null, [], null);
|
|
||||||
else
|
|
||||||
(message, dateTimes, property) = GetProperty(populateId, metadata, filePath, property, isIgnoreExtension, isValidImageFormatExtension, id, asciiEncoding);
|
|
||||||
return new(property?.DateTimeOriginal, dateTimes, property?.Id, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static double GetStandardDeviation(List<long> values, double average)
|
|
||||||
{
|
|
||||||
double result = 0;
|
|
||||||
if (values.Count == 0)
|
|
||||||
throw new Exception("Collection must have at least one value!");
|
|
||||||
double sum = values.Sum(l => (l - average) * (l - average));
|
|
||||||
result = Math.Sqrt(sum / values.Count);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long GetThreeStandardDeviationHigh(ref List<long> ticksCollection, long min)
|
|
||||||
{
|
|
||||||
long result;
|
|
||||||
ticksCollection = (from l in ticksCollection select l - min).ToList();
|
|
||||||
double sum = ticksCollection.Sum();
|
|
||||||
double average = sum / ticksCollection.Count;
|
|
||||||
double standardDeviation = GetStandardDeviation(ticksCollection, average);
|
|
||||||
result = (long)Math.Ceiling(average + min + (standardDeviation * 3));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static TimeSpan GetThreeStandardDeviationHigh(int minimum, Container.Models.Container container)
|
|
||||||
{
|
|
||||||
TimeSpan result;
|
|
||||||
DateTime? minimumDateTime;
|
|
||||||
List<long> ticksCollection = [];
|
|
||||||
foreach (Shared.Models.Item item in container.Items)
|
|
||||||
{
|
{
|
||||||
if (item.Property is null)
|
if (dateTime is null || results.Contains(dateTime.Value))
|
||||||
continue;
|
continue;
|
||||||
minimumDateTime = Shared.Models.Methods.IProperty.GetMinimumDateTime(item.Property);
|
results.Add(dateTime.Value);
|
||||||
if (minimumDateTime is null)
|
|
||||||
continue;
|
|
||||||
ticksCollection.Add(minimumDateTime.Value.Ticks);
|
|
||||||
}
|
}
|
||||||
long threeStandardDeviationHigh;
|
return results;
|
||||||
long min;
|
|
||||||
if (ticksCollection.Count == 0)
|
|
||||||
min = 0;
|
|
||||||
else
|
|
||||||
min = ticksCollection.Min();
|
|
||||||
if (ticksCollection.Count < minimum)
|
|
||||||
threeStandardDeviationHigh = long.MaxValue;
|
|
||||||
else
|
|
||||||
threeStandardDeviationHigh = GetThreeStandardDeviationHigh(ref ticksCollection, min);
|
|
||||||
result = new TimeSpan(threeStandardDeviationHigh - min);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static (int, List<DateTime>, List<Shared.Models.Item>) Get(Container.Models.Container container, TimeSpan threeStandardDeviationHigh, int i)
|
private static List<DateTime> GetDateTimes(FilePath filePath, DateTime?[] dateTimes)
|
||||||
{
|
{
|
||||||
List<Shared.Models.Item> results = [];
|
List<DateTime> results = [];
|
||||||
int j = i;
|
string[] digits = Digit().Split(filePath.FullName);
|
||||||
long? ticks;
|
foreach (string digit in digits)
|
||||||
TimeSpan timeSpan;
|
|
||||||
Shared.Models.Item item;
|
|
||||||
DateTime? minimumDateTime;
|
|
||||||
Shared.Models.Item nextItem;
|
|
||||||
DateTime? nextMinimumDateTime;
|
|
||||||
List<DateTime> dateTimes = [];
|
|
||||||
for (; j < container.Items.Count; j++)
|
|
||||||
{
|
{
|
||||||
ticks = null;
|
if (digit.Length != 4 || digit[..2] is not "19" and not "20" || !int.TryParse(digit, out int year))
|
||||||
item = container.Items[j];
|
|
||||||
if (item.Property is null)
|
|
||||||
continue;
|
continue;
|
||||||
minimumDateTime = Shared.Models.Methods.IProperty.GetMinimumDateTime(item.Property);
|
results.Add(new(year, 1, 1));
|
||||||
if (minimumDateTime is null)
|
|
||||||
continue;
|
|
||||||
for (int k = j + 1; k < container.Items.Count; k++)
|
|
||||||
{
|
|
||||||
nextItem = container.Items[k];
|
|
||||||
if (nextItem.Property is null)
|
|
||||||
continue;
|
|
||||||
nextMinimumDateTime = Shared.Models.Methods.IProperty.GetMinimumDateTime(nextItem.Property);
|
|
||||||
if (nextMinimumDateTime is null)
|
|
||||||
continue;
|
|
||||||
ticks = nextMinimumDateTime.Value.Ticks;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
results.Add(item);
|
|
||||||
dateTimes.Add(minimumDateTime.Value);
|
|
||||||
if (ticks.HasValue)
|
|
||||||
{
|
|
||||||
timeSpan = new(ticks.Value - minimumDateTime.Value.Ticks);
|
|
||||||
if (timeSpan > threeStandardDeviationHigh)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return new(j, dateTimes, results);
|
foreach (DateTime? dateTime in dateTimes)
|
||||||
|
{
|
||||||
|
if (dateTime is null)
|
||||||
|
continue;
|
||||||
|
results.Add(dateTime.Value);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool Any(Container.Models.Container[] containers)
|
private static List<DateTime> GetDateTimes(DateTime dateTimeFromName, DateTime?[] dateTimes)
|
||||||
{
|
{
|
||||||
bool result = false;
|
List<DateTime> results = [dateTimeFromName];
|
||||||
foreach (Container.Models.Container container in containers)
|
foreach (DateTime? dateTime in dateTimes)
|
||||||
{
|
{
|
||||||
if (container.Items.Count == 0)
|
if (dateTime is null)
|
||||||
continue;
|
continue;
|
||||||
if ((from l in container.Items where l.Any() select true).Any())
|
results.Add(dateTime.Value);
|
||||||
{
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<DateTime> GetDateTimes(DateTime?[] dateTimes, DateTime?[] metadataDateTimes)
|
||||||
|
{
|
||||||
|
List<DateTime> results = [];
|
||||||
|
foreach (DateTime? dateTime in metadataDateTimes)
|
||||||
|
{
|
||||||
|
if (dateTime is null || results.Contains(dateTime.Value))
|
||||||
|
continue;
|
||||||
|
results.Add(dateTime.Value);
|
||||||
|
}
|
||||||
|
foreach (DateTime? dateTime in dateTimes)
|
||||||
|
{
|
||||||
|
if (dateTime is null || results.Contains(dateTime.Value))
|
||||||
|
continue;
|
||||||
|
results.Add(dateTime.Value);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
[GeneratedRegex(@"\D+")]
|
||||||
|
private static partial Regex Digit();
|
||||||
|
|
||||||
}
|
}
|
@ -5,13 +5,8 @@ namespace View_by_Distance.Property.Models.Stateless;
|
|||||||
internal class Result
|
internal class Result
|
||||||
{
|
{
|
||||||
|
|
||||||
internal static string GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string jsonGroup)
|
internal static string GetRelativePath(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string path) =>
|
||||||
{
|
Shared.Models.Stateless.Methods.IPath.GetRelativePath(path, propertyConfiguration.RootDirectory.Length);
|
||||||
string result = Path.Combine(GetResultsDateGroupDirectory(propertyConfiguration, description), jsonGroup);
|
|
||||||
if (!Directory.Exists(result))
|
|
||||||
_ = Directory.CreateDirectory(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description)
|
internal static string GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description)
|
||||||
{
|
{
|
||||||
@ -21,12 +16,66 @@ internal class Result
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetRelativePath(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string path)
|
internal static string GetResultsGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, bool create)
|
||||||
{
|
{
|
||||||
string result = Shared.Models.Stateless.Methods.IPath.GetRelativePath(path, propertyConfiguration.RootDirectory.Length);
|
string result = Path.Combine($"{propertyConfiguration.RootDirectory}-Results", description.Replace('_', ')'));
|
||||||
|
if (create && !Directory.Exists(result))
|
||||||
|
_ = Directory.CreateDirectory(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static string GetResultsDateGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string jsonGroup)
|
||||||
|
{
|
||||||
|
string result = Path.Combine(GetResultsDateGroupDirectory(propertyConfiguration, description), jsonGroup);
|
||||||
|
if (!Directory.Exists(result))
|
||||||
|
_ = Directory.CreateDirectory(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetResultsFullGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel)
|
||||||
|
{
|
||||||
|
string result = GetResultsDateGroupDirectory(propertyConfiguration, description);
|
||||||
|
if (includeResizeGroup)
|
||||||
|
result = Path.Combine(result, outputResolution);
|
||||||
|
if (includeModel && includePredictorModel)
|
||||||
|
{
|
||||||
|
string modelName;
|
||||||
|
string predictorModelName;
|
||||||
|
if (propertyConfiguration.ModelName is null)
|
||||||
|
modelName = Model.Hog.ToString();
|
||||||
|
else
|
||||||
|
modelName = propertyConfiguration.ModelName;
|
||||||
|
if (propertyConfiguration.PredictorModelName is null)
|
||||||
|
predictorModelName = PredictorModel.Large.ToString();
|
||||||
|
else
|
||||||
|
predictorModelName = propertyConfiguration.PredictorModelName;
|
||||||
|
string dateGroupDirectory = string.Concat(outputResolution.Replace(" ", string.Empty), "-", modelName, "-", predictorModelName, "-", propertyConfiguration.NumberOfJitters, "-", propertyConfiguration.NumberOfTimesToUpsample);
|
||||||
|
result = Path.Combine(result, dateGroupDirectory);
|
||||||
|
}
|
||||||
|
else if (includeModel)
|
||||||
|
throw new Exception();
|
||||||
|
else if (includePredictorModel)
|
||||||
|
throw new Exception();
|
||||||
|
if (!Directory.Exists(result))
|
||||||
|
_ = Directory.CreateDirectory(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<string> GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription, bool converted)
|
||||||
|
{
|
||||||
|
List<string> results = [];
|
||||||
|
string sourceDirectorySegment = GetRelativePath(propertyConfiguration, sourceDirectory);
|
||||||
|
string result = string.Concat(Path.Combine(dateGroupDirectory, "<>"), sourceDirectorySegment);
|
||||||
|
if (!string.IsNullOrEmpty(contentDescription))
|
||||||
|
CheckContent(propertyConfiguration, dateGroupDirectory, contentDescription, result);
|
||||||
|
if (!string.IsNullOrEmpty(singletonDescription))
|
||||||
|
CheckSingleton(propertyConfiguration, dateGroupDirectory, singletonDescription, converted, result);
|
||||||
|
if (!string.IsNullOrEmpty(collectionDescription))
|
||||||
|
CheckCollection(propertyConfiguration, dateGroupDirectory, collectionDescription, converted, result);
|
||||||
|
results.Add(result);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
private static void CheckContent(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dateGroupDirectory, string contentDescription, string result)
|
private static void CheckContent(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dateGroupDirectory, string contentDescription, string result)
|
||||||
{
|
{
|
||||||
string checkDirectory;
|
string checkDirectory;
|
||||||
@ -74,58 +123,6 @@ internal class Result
|
|||||||
_ = Directory.CreateDirectory(checkDirectory);
|
_ = Directory.CreateDirectory(checkDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetResultsFullGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel)
|
|
||||||
{
|
|
||||||
string result = GetResultsDateGroupDirectory(propertyConfiguration, description);
|
|
||||||
if (includeResizeGroup)
|
|
||||||
result = Path.Combine(result, outputResolution);
|
|
||||||
if (includeModel && includePredictorModel)
|
|
||||||
{
|
|
||||||
string modelName;
|
|
||||||
string predictorModelName;
|
|
||||||
if (propertyConfiguration.ModelName is null)
|
|
||||||
modelName = Model.Hog.ToString();
|
|
||||||
else
|
|
||||||
modelName = propertyConfiguration.ModelName;
|
|
||||||
if (propertyConfiguration.PredictorModelName is null)
|
|
||||||
predictorModelName = PredictorModel.Large.ToString();
|
|
||||||
else
|
|
||||||
predictorModelName = propertyConfiguration.PredictorModelName;
|
|
||||||
string dateGroupDirectory = string.Concat(outputResolution.Replace(" ", string.Empty), "-", modelName, "-", predictorModelName, "-", propertyConfiguration.NumberOfJitters, "-", propertyConfiguration.NumberOfTimesToUpsample);
|
|
||||||
result = Path.Combine(result, dateGroupDirectory);
|
|
||||||
}
|
|
||||||
else if (includeModel)
|
|
||||||
throw new Exception();
|
|
||||||
else if (includePredictorModel)
|
|
||||||
throw new Exception();
|
|
||||||
if (!Directory.Exists(result))
|
|
||||||
_ = Directory.CreateDirectory(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static List<string> GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string dateGroupDirectory, string contentDescription, string singletonDescription, string collectionDescription, bool converted)
|
|
||||||
{
|
|
||||||
List<string> results = [];
|
|
||||||
string sourceDirectorySegment = GetRelativePath(propertyConfiguration, sourceDirectory);
|
|
||||||
string result = string.Concat(Path.Combine(dateGroupDirectory, "<>"), sourceDirectorySegment);
|
|
||||||
if (!string.IsNullOrEmpty(contentDescription))
|
|
||||||
CheckContent(propertyConfiguration, dateGroupDirectory, contentDescription, result);
|
|
||||||
if (!string.IsNullOrEmpty(singletonDescription))
|
|
||||||
CheckSingleton(propertyConfiguration, dateGroupDirectory, singletonDescription, converted, result);
|
|
||||||
if (!string.IsNullOrEmpty(collectionDescription))
|
|
||||||
CheckCollection(propertyConfiguration, dateGroupDirectory, collectionDescription, converted, result);
|
|
||||||
results.Add(result);
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string GetResultsGroupDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string description, bool create)
|
|
||||||
{
|
|
||||||
string result = Path.Combine($"{propertyConfiguration.RootDirectory}-Results", description.Replace('_', ')'));
|
|
||||||
if (create && !Directory.Exists(result))
|
|
||||||
_ = Directory.CreateDirectory(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static List<string> GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription)
|
internal static List<string> GetDirectoryInfoCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription)
|
||||||
{
|
{
|
||||||
List<string> results;
|
List<string> results;
|
||||||
|
@ -66,6 +66,98 @@ public class C_Resize
|
|||||||
_ConstructorInfo = constructorInfo;
|
_ConstructorInfo = constructorInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] GetBitmapData(Bitmap bitmap)
|
||||||
|
{
|
||||||
|
byte[] results;
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
Rectangle rectangle = new(0, 0, bitmap.Width, bitmap.Height);
|
||||||
|
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||||
|
IntPtr intPtr = bitmapData.Scan0;
|
||||||
|
int length = bitmapData.Stride * bitmap.Height;
|
||||||
|
results = new byte[length];
|
||||||
|
Marshal.Copy(intPtr, results, 0, length);
|
||||||
|
bitmap.UnlockBits(bitmapData);
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetPngLowQuality()
|
||||||
|
{
|
||||||
|
(ImageCodecInfo, EncoderParameters, string) result;
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
ImageFormat imageFormat = ImageFormat.Png;
|
||||||
|
ImageCodecInfo[] imageCodecInfoCollection = ImageCodecInfo.GetImageEncoders();
|
||||||
|
ImageCodecInfo imageCodecInfo = (from l in imageCodecInfoCollection 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..]);
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetJpegLowQuality()
|
||||||
|
{
|
||||||
|
(ImageCodecInfo, EncoderParameters, string) result;
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
ImageFormat imageFormat = ImageFormat.Jpeg;
|
||||||
|
ImageCodecInfo[] imageCodecInfoCollection = ImageCodecInfo.GetImageEncoders();
|
||||||
|
ImageCodecInfo imageCodecInfo = (from l in imageCodecInfoCollection 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..]);
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetTuple(string outputExtension, int outputQuality)
|
||||||
|
{
|
||||||
|
(ImageCodecInfo, EncoderParameters, string) result;
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
ImageFormat imageFormat = outputExtension switch
|
||||||
|
{
|
||||||
|
".gif" => ImageFormat.Gif,
|
||||||
|
".jfif" => ImageFormat.Jpeg,
|
||||||
|
".jpe" => ImageFormat.Jpeg,
|
||||||
|
".jpeg" => ImageFormat.Jpeg,
|
||||||
|
".jpg" => ImageFormat.Jpeg,
|
||||||
|
".png" => ImageFormat.Png,
|
||||||
|
".tif" => ImageFormat.Tiff,
|
||||||
|
".tiff" => ImageFormat.Tiff,
|
||||||
|
_ => throw new Exception(),
|
||||||
|
};
|
||||||
|
ImageCodecInfo[] imageCodecInfoCollection = ImageCodecInfo.GetImageEncoders();
|
||||||
|
ImageCodecInfo imageCodecInfo = (from l in imageCodecInfoCollection where l.FormatID == imageFormat.Guid select l).First();
|
||||||
|
EncoderParameters encoderParameters = new(1);
|
||||||
|
// encoderParameters.Param[0] = New EncoderParameter(Encoder.Quality, CType(75L, Int32)) 'Default
|
||||||
|
// encoderParameters.Param[0] = New EncoderParameter(Encoder.Quality, CType(95L, Int32)) 'Paint
|
||||||
|
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, outputQuality);
|
||||||
|
if (string.IsNullOrEmpty(imageCodecInfo.FilenameExtension))
|
||||||
|
throw new NullReferenceException(nameof(imageCodecInfo.FilenameExtension));
|
||||||
|
result = new(imageCodecInfo, encoderParameters, imageCodecInfo.FilenameExtension.Split(';')[0].ToLower()[1..]);
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, Item item, bool outputResolutionHasNumber, int id) =>
|
||||||
|
GetResizedFileHolder(cResultsFullGroupDirectory, item.FilePath, outputResolutionHasNumber, $"{id}{item.FilePath.ExtensionLowered}");
|
||||||
|
|
||||||
|
private FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, FilePath filePath, bool outputResolutionHasNumber, string fileName)
|
||||||
|
{
|
||||||
|
FileHolder result;
|
||||||
|
if (outputResolutionHasNumber)
|
||||||
|
result = Shared.Models.Stateless.Methods.IFileHolder.Get(Path.Combine(AngleBracketCollection[0].Replace("<>", _PropertyConfiguration.ResultContent), fileName));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
|
||||||
|
result = Shared.Models.Stateless.Methods.IFileHolder.Get(Path.Combine(cResultsFullGroupDirectory, _PropertyConfiguration.ResultContent, cei.Combined, fileName));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
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 });
|
||||||
@ -96,373 +188,10 @@ public class C_Resize
|
|||||||
converted: true));
|
converted: true));
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CA1416
|
|
||||||
|
|
||||||
public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetJpegLowQuality()
|
|
||||||
{
|
|
||||||
(ImageCodecInfo, EncoderParameters, string) result;
|
|
||||||
ImageFormat imageFormat = ImageFormat.Jpeg;
|
|
||||||
ImageCodecInfo[] imageCodecInfoCollection = ImageCodecInfo.GetImageEncoders();
|
|
||||||
ImageCodecInfo imageCodecInfo = (from l in imageCodecInfoCollection 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;
|
|
||||||
ImageFormat imageFormat = ImageFormat.Png;
|
|
||||||
ImageCodecInfo[] imageCodecInfoCollection = ImageCodecInfo.GetImageEncoders();
|
|
||||||
ImageCodecInfo imageCodecInfo = (from l in imageCodecInfoCollection 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;
|
|
||||||
ImageFormat imageFormat = outputExtension switch
|
|
||||||
{
|
|
||||||
".gif" => ImageFormat.Gif,
|
|
||||||
".jfif" => ImageFormat.Jpeg,
|
|
||||||
".jpe" => ImageFormat.Jpeg,
|
|
||||||
".jpeg" => ImageFormat.Jpeg,
|
|
||||||
".jpg" => ImageFormat.Jpeg,
|
|
||||||
".png" => ImageFormat.Png,
|
|
||||||
".tif" => ImageFormat.Tiff,
|
|
||||||
".tiff" => ImageFormat.Tiff,
|
|
||||||
_ => throw new Exception(),
|
|
||||||
};
|
|
||||||
ImageCodecInfo[] imageCodecInfoCollection = ImageCodecInfo.GetImageEncoders();
|
|
||||||
ImageCodecInfo imageCodecInfo = (from l in imageCodecInfoCollection where l.FormatID == imageFormat.Guid select l).First();
|
|
||||||
EncoderParameters encoderParameters = new(1);
|
|
||||||
// encoderParameters.Param[0] = New EncoderParameter(Encoder.Quality, CType(75L, Int32)) 'Default
|
|
||||||
// encoderParameters.Param[0] = New EncoderParameter(Encoder.Quality, CType(95L, Int32)) 'Paint
|
|
||||||
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, outputQuality);
|
|
||||||
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 byte[] GetBitmapData(Bitmap bitmap)
|
|
||||||
{
|
|
||||||
byte[] results;
|
|
||||||
Rectangle rectangle = new(0, 0, bitmap.Width, bitmap.Height);
|
|
||||||
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
|
||||||
IntPtr intPtr = bitmapData.Scan0;
|
|
||||||
int length = bitmapData.Stride * bitmap.Height;
|
|
||||||
results = new byte[length];
|
|
||||||
Marshal.Copy(intPtr, results, 0, length);
|
|
||||||
bitmap.UnlockBits(bitmapData);
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CopyPropertyItems(byte[] bytes, PropertyItem[] propertyItems, Bitmap bitmap)
|
|
||||||
{
|
|
||||||
bool hasId = false;
|
|
||||||
int id = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeDigitized;
|
|
||||||
int imageWidth = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageWidth;
|
|
||||||
int imageHeight = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageHeight;
|
|
||||||
int orientation = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation;
|
|
||||||
foreach (PropertyItem propertyItem in propertyItems)
|
|
||||||
{
|
|
||||||
if (propertyItem.Id == id)
|
|
||||||
hasId = true;
|
|
||||||
else if (propertyItem.Id == imageWidth)
|
|
||||||
continue;
|
|
||||||
else if (propertyItem.Id == imageHeight)
|
|
||||||
continue;
|
|
||||||
else if (propertyItem.Id == orientation)
|
|
||||||
continue;
|
|
||||||
bitmap.SetPropertyItem(propertyItem);
|
|
||||||
}
|
|
||||||
if (!hasId)
|
|
||||||
{
|
|
||||||
PropertyItem propertyItem = (PropertyItem)_ConstructorInfo.Invoke(null);
|
|
||||||
propertyItem.Id = id;
|
|
||||||
propertyItem.Len = bytes.Length;
|
|
||||||
propertyItem.Type = 2;
|
|
||||||
propertyItem.Value = bytes;
|
|
||||||
bitmap.SetPropertyItem(propertyItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveResizedSubfile3(MappingFromItem mappingFromItem, int[] resize, byte[] bytes)
|
|
||||||
{
|
|
||||||
Bitmap bitmap;
|
|
||||||
int outputResolutionWidth = resize[_OutputResolutionWidthIndex];
|
|
||||||
using Bitmap temp = new(mappingFromItem.FilePath.FullName, useIcm: false);
|
|
||||||
int outputResolutionHeight = resize[_OutputResolutionHeightIndex];
|
|
||||||
PropertyItem[] propertyItems = temp.PropertyItems;
|
|
||||||
int outputResolutionOrientation = resize[_OutputResolutionOrientationIndex];
|
|
||||||
bitmap = new(temp, outputResolutionWidth, outputResolutionHeight);
|
|
||||||
switch (outputResolutionOrientation) // exif 274
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
break; // 1 = Horizontal (normal)
|
|
||||||
case 2:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipX);
|
|
||||||
break; // 2 = Mirror horizontal
|
|
||||||
case 3:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
|
|
||||||
break; // 3 = Rotate 180
|
|
||||||
case 4:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
|
||||||
break; // 4 = Mirror vertical
|
|
||||||
case 5:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.Rotate270FlipX);
|
|
||||||
break; // 5 = Mirror horizontal and rotate 270 CW
|
|
||||||
case 6:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
|
|
||||||
break; // 6 = Rotate 90 CW
|
|
||||||
case 7:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
|
|
||||||
break; // 7 = Mirror horizontal and rotate 90 CW
|
|
||||||
case 8:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
|
|
||||||
break; // 8 = Rotate 270 CW
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
CopyPropertyItems(bytes, propertyItems, bitmap);
|
|
||||||
bitmap.Save(mappingFromItem.ResizedFileHolder.FullName, _ImageCodecInfo, _EncoderParameters);
|
|
||||||
bitmap.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveResizedSubfile5(MappingFromItem mappingFromItem, int[] resize, byte[] bytes)
|
|
||||||
{
|
|
||||||
Bitmap bitmap;
|
|
||||||
using Bitmap temp = new(mappingFromItem.FilePath.FullName, useIcm: false);
|
|
||||||
PropertyItem[] propertyItems = temp.PropertyItems;
|
|
||||||
int tempResolutionWidth = resize[_TempResolutionWidth];
|
|
||||||
int tempResolutionHeight = resize[_TempResolutionHeight];
|
|
||||||
int outputResolutionWidth = resize[_OutputResolutionWidthIndex];
|
|
||||||
int outputResolutionHeight = resize[_OutputResolutionHeightIndex];
|
|
||||||
int outputResolutionOrientation = resize[_OutputResolutionOrientationIndex];
|
|
||||||
bitmap = new(temp, tempResolutionWidth, tempResolutionHeight);
|
|
||||||
switch (outputResolutionOrientation) // exif 274
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
break; // 1 = Horizontal (normal)
|
|
||||||
case 2:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipX);
|
|
||||||
break; // 2 = Mirror horizontal
|
|
||||||
case 3:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
|
|
||||||
break; // 3 = Rotate 180
|
|
||||||
case 4:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
|
||||||
break; // 4 = Mirror vertical
|
|
||||||
case 5:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.Rotate270FlipX);
|
|
||||||
break; // 5 = Mirror horizontal and rotate 270 CW
|
|
||||||
case 6:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
|
|
||||||
break; // 6 = Rotate 90 CW
|
|
||||||
case 7:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
|
|
||||||
break; // 7 = Mirror horizontal and rotate 90 CW
|
|
||||||
case 8:
|
|
||||||
bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
|
|
||||||
break; // 8 = Rotate 270 CW
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Bitmap preRotated;
|
|
||||||
Rectangle rectangle;
|
|
||||||
if (tempResolutionHeight < tempResolutionWidth)
|
|
||||||
rectangle = new Rectangle((int)((tempResolutionWidth - outputResolutionWidth) * .5), 0, outputResolutionWidth, outputResolutionHeight);
|
|
||||||
else
|
|
||||||
rectangle = new Rectangle(0, (int)((tempResolutionHeight - outputResolutionHeight) * .5), outputResolutionWidth, outputResolutionHeight);
|
|
||||||
using (preRotated = new Bitmap(outputResolutionWidth, outputResolutionHeight))
|
|
||||||
{
|
|
||||||
using (Graphics graphics = Graphics.FromImage(preRotated))
|
|
||||||
graphics.DrawImage(bitmap, new Rectangle(0, 0, outputResolutionWidth, outputResolutionHeight), rectangle, GraphicsUnit.Pixel);
|
|
||||||
CopyPropertyItems(bytes, propertyItems, bitmap);
|
|
||||||
bitmap.Save(mappingFromItem.ResizedFileHolder.FullName, _ImageCodecInfo, _EncoderParameters);
|
|
||||||
}
|
|
||||||
bitmap.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning restore CA1416
|
|
||||||
|
|
||||||
private void SaveResizedSubfile(Shared.Models.Property property, MappingFromItem mappingFromItem, int[] resize)
|
|
||||||
{
|
|
||||||
string dateTimeFormat = IProperty.DateTimeFormat();
|
|
||||||
DateTime dateTime = property.DateTimeOriginal is not null ? property.DateTimeOriginal.Value : Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
|
|
||||||
string dateTimeValue = dateTime.ToString(dateTimeFormat);
|
|
||||||
byte[] bytes = _ASCIIEncoding.GetBytes(dateTimeValue);
|
|
||||||
if (_ASCIIEncoding.GetString(bytes, 0, bytes.Length) != dateTimeValue)
|
|
||||||
throw new Exception();
|
|
||||||
if (resize.Length == 3)
|
|
||||||
SaveResizedSubfile3(mappingFromItem, resize, bytes);
|
|
||||||
else if (resize.Length == 5)
|
|
||||||
SaveResizedSubfile5(mappingFromItem, resize, bytes);
|
|
||||||
else
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SaveResizedSubfile(Property.Models.Configuration configuration, string outputResolution, string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, Item item, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize)
|
|
||||||
{
|
|
||||||
if (mappingFromItem.ResizedFileHolder is null)
|
|
||||||
throw new NullReferenceException(nameof(mappingFromItem.ResizedFileHolder));
|
|
||||||
#pragma warning disable CA1854
|
|
||||||
if (!outputResolutionToResize.ContainsKey(_Original))
|
|
||||||
throw new Exception();
|
|
||||||
if (!outputResolutionToResize.ContainsKey(outputResolution))
|
|
||||||
throw new Exception();
|
|
||||||
#pragma warning restore CA1854
|
|
||||||
FileInfo fileInfo = new(mappingFromItem.ResizedFileHolder.FullName);
|
|
||||||
bool check = false;
|
|
||||||
int[] resize = outputResolutionToResize[outputResolution];
|
|
||||||
int outputResolutionWidth = resize[_OutputResolutionWidthIndex];
|
|
||||||
int outputResolutionHeight = resize[_OutputResolutionHeightIndex];
|
|
||||||
int outputResolutionOrientation = resize[_OutputResolutionOrientationIndex];
|
|
||||||
int[] originalCollection = outputResolutionToResize[_Original];
|
|
||||||
string[] changesFrom = [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();
|
|
||||||
if (_OverrideForResizeImages)
|
|
||||||
check = true;
|
|
||||||
else if (!fileInfo.Exists)
|
|
||||||
check = true;
|
|
||||||
if (outputResolutionWidth == originalCollection[_OutputResolutionWidthIndex] && outputResolutionHeight == originalCollection[_OutputResolutionHeightIndex] && outputResolutionOrientation == originalCollection[_OutputResolutionOrientationIndex])
|
|
||||||
{
|
|
||||||
if (!check && dateTimes.Count != 0 && dateTimes.Max() > fileInfo.CreationTime.AddDays(1))
|
|
||||||
check = true;
|
|
||||||
if (check)
|
|
||||||
{
|
|
||||||
// if (fileInfo.Exists)
|
|
||||||
// File.Delete(fileInfo.FullName);
|
|
||||||
// File.Copy(mappingFromItem.FilePath.FullName, fileInfo.FullName);
|
|
||||||
// item.SetResizedFileHolder(_FileNameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(mappingFromItem.ResizedFileHolder));
|
|
||||||
// subFileTuples.Add(new Tuple<string, DateTime>(nameof(C_Resize), DateTime.Now));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!check && dateTimes.Count != 0 && dateTimes.Max() > fileInfo.LastWriteTime)
|
|
||||||
check = true;
|
|
||||||
if (check)
|
|
||||||
{
|
|
||||||
SaveResizedSubfile(property, mappingFromItem, resize);
|
|
||||||
item.SetResizedFileHolder(_FileNameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(mappingFromItem.ResizedFileHolder));
|
|
||||||
subFileTuples.Add(new Tuple<string, DateTime>(nameof(C_Resize), DateTime.Now));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int[] GetCollection(string outputResolution)
|
|
||||||
{
|
|
||||||
List<int> results = [];
|
|
||||||
string[] segments = outputResolution.Split('x');
|
|
||||||
results.Add(int.Parse(segments[0]));
|
|
||||||
results.Add(int.Parse(segments[1]));
|
|
||||||
return results.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dictionary<string, int[]> GetImageResizes(Shared.Models.Property property)
|
|
||||||
{
|
|
||||||
Dictionary<string, int[]> results = [];
|
|
||||||
int[] desired;
|
|
||||||
int checkWidth;
|
|
||||||
int checkHeight;
|
|
||||||
int desiredWidth;
|
|
||||||
int desiredHeight;
|
|
||||||
int orientation = property.Orientation is null || string.IsNullOrEmpty(property.Orientation) || !int.TryParse(property.Orientation, out int propertyOrientation) ? 0 : propertyOrientation;
|
|
||||||
if (property is null || property.Width is null || property.Height is null)
|
|
||||||
throw new NotSupportedException();
|
|
||||||
checkWidth = property.Width.Value;
|
|
||||||
checkHeight = property.Height.Value;
|
|
||||||
if (!_ValidResolutions.Contains(_Original))
|
|
||||||
results.Add(_Original, [checkWidth, checkHeight, orientation]);
|
|
||||||
foreach (string validResolution in _ValidResolutions)
|
|
||||||
{
|
|
||||||
if (validResolution == _Original)
|
|
||||||
{
|
|
||||||
desiredWidth = checkWidth;
|
|
||||||
desiredHeight = checkHeight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
desired = GetCollection(validResolution);
|
|
||||||
desiredWidth = desired[0];
|
|
||||||
desiredHeight = desired[1];
|
|
||||||
}
|
|
||||||
if (checkWidth <= desiredWidth && checkHeight <= desiredHeight)
|
|
||||||
results.Add(validResolution, [checkWidth, checkHeight, orientation]);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (desiredWidth != desiredHeight)
|
|
||||||
{
|
|
||||||
if (checkWidth * desiredHeight > desiredWidth * checkHeight)
|
|
||||||
results.Add(validResolution, [desiredWidth, Convert.ToInt32(desiredWidth * checkHeight / (double)checkWidth), orientation]);
|
|
||||||
else
|
|
||||||
results.Add(validResolution, [Convert.ToInt32(desiredHeight * checkWidth / (double)checkHeight), desiredHeight, orientation]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (checkWidth * desiredHeight <= desiredWidth * checkHeight)
|
|
||||||
results.Add(validResolution, [desiredWidth, desiredHeight, orientation, desiredWidth, Convert.ToInt32(desiredWidth * checkHeight / (double)checkWidth)]);
|
|
||||||
else
|
|
||||||
results.Add(validResolution, [desiredWidth, desiredHeight, orientation, Convert.ToInt32(desiredHeight * checkWidth / (double)checkHeight), desiredHeight]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, FilePath filePath, bool outputResolutionHasNumber, string fileName)
|
|
||||||
{
|
|
||||||
FileHolder result;
|
|
||||||
if (outputResolutionHasNumber)
|
|
||||||
result = Shared.Models.Stateless.Methods.IFileHolder.Get(Path.Combine(AngleBracketCollection[0].Replace("<>", _PropertyConfiguration.ResultContent), fileName));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, filePath);
|
|
||||||
result = Shared.Models.Stateless.Methods.IFileHolder.Get(Path.Combine(cResultsFullGroupDirectory, _PropertyConfiguration.ResultContent, cei.Combined, fileName));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, Item item, bool outputResolutionHasNumber) =>
|
public FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, Item item, bool outputResolutionHasNumber) =>
|
||||||
GetResizedFileHolder(cResultsFullGroupDirectory, item.FilePath, outputResolutionHasNumber, item.FilePath.Name);
|
GetResizedFileHolder(cResultsFullGroupDirectory, item.FilePath, outputResolutionHasNumber, item.FilePath.Name);
|
||||||
|
|
||||||
public FileHolder GetResizedFileHolder(string cResultsFullGroupDirectory, Item item, bool outputResolutionHasNumber, int id) =>
|
public Dictionary<string, int[]> GetResizeKeyValuePairs(Configuration configuration, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem)
|
||||||
GetResizedFileHolder(cResultsFullGroupDirectory, item.FilePath, outputResolutionHasNumber, $"{id}{item.FilePath.ExtensionLowered}");
|
|
||||||
|
|
||||||
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
|
|
||||||
{
|
|
||||||
string[] segments = directory.Split(cei.Combined);
|
|
||||||
string? checkDirectory = segments.Length == 1 ?
|
|
||||||
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
|
||||||
segments.Length == 2 ?
|
|
||||||
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
|
||||||
null;
|
|
||||||
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
|
||||||
{
|
|
||||||
string checkFile = Path.Combine(checkDirectory, fileName);
|
|
||||||
if (File.Exists(checkFile))
|
|
||||||
{
|
|
||||||
File.Move(checkFile, fileInfo.FullName);
|
|
||||||
fileInfo.Refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<string, int[]> GetResizeKeyValuePairs(Property.Models.Configuration configuration, string cResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem)
|
|
||||||
{
|
{
|
||||||
Dictionary<string, int[]>? results;
|
Dictionary<string, int[]>? results;
|
||||||
string json;
|
string json;
|
||||||
@ -528,4 +257,285 @@ public class C_Resize
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
|
||||||
|
{
|
||||||
|
string[] segments = directory.Split(cei.Combined);
|
||||||
|
string? checkDirectory = segments.Length == 1 ?
|
||||||
|
Path.Combine(segments[0], $"{cei.Combined[2..]}") :
|
||||||
|
segments.Length == 2 ?
|
||||||
|
$"{segments[0]}{cei.Combined[2..]}{segments[1]}" :
|
||||||
|
null;
|
||||||
|
if (checkDirectory is not null && Directory.Exists(checkDirectory))
|
||||||
|
{
|
||||||
|
string checkFile = Path.Combine(checkDirectory, fileName);
|
||||||
|
if (File.Exists(checkFile))
|
||||||
|
{
|
||||||
|
File.Move(checkFile, fileInfo.FullName);
|
||||||
|
fileInfo.Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<string, int[]> GetImageResizes(Shared.Models.Property property)
|
||||||
|
{
|
||||||
|
Dictionary<string, int[]> results = [];
|
||||||
|
int[] desired;
|
||||||
|
int checkWidth;
|
||||||
|
int checkHeight;
|
||||||
|
int desiredWidth;
|
||||||
|
int desiredHeight;
|
||||||
|
int orientation = property.Orientation is null || string.IsNullOrEmpty(property.Orientation) || !int.TryParse(property.Orientation, out int propertyOrientation) ? 0 : propertyOrientation;
|
||||||
|
if (property is null || property.Width is null || property.Height is null)
|
||||||
|
throw new NotSupportedException();
|
||||||
|
checkWidth = property.Width.Value;
|
||||||
|
checkHeight = property.Height.Value;
|
||||||
|
if (!_ValidResolutions.Contains(_Original))
|
||||||
|
results.Add(_Original, [checkWidth, checkHeight, orientation]);
|
||||||
|
foreach (string validResolution in _ValidResolutions)
|
||||||
|
{
|
||||||
|
if (validResolution == _Original)
|
||||||
|
{
|
||||||
|
desiredWidth = checkWidth;
|
||||||
|
desiredHeight = checkHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
desired = GetCollection(validResolution);
|
||||||
|
desiredWidth = desired[0];
|
||||||
|
desiredHeight = desired[1];
|
||||||
|
}
|
||||||
|
if (checkWidth <= desiredWidth && checkHeight <= desiredHeight)
|
||||||
|
results.Add(validResolution, [checkWidth, checkHeight, orientation]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (desiredWidth != desiredHeight)
|
||||||
|
{
|
||||||
|
if (checkWidth * desiredHeight > desiredWidth * checkHeight)
|
||||||
|
results.Add(validResolution, [desiredWidth, Convert.ToInt32(desiredWidth * checkHeight / (double)checkWidth), orientation]);
|
||||||
|
else
|
||||||
|
results.Add(validResolution, [Convert.ToInt32(desiredHeight * checkWidth / (double)checkHeight), desiredHeight, orientation]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (checkWidth * desiredHeight <= desiredWidth * checkHeight)
|
||||||
|
results.Add(validResolution, [desiredWidth, desiredHeight, orientation, desiredWidth, Convert.ToInt32(desiredWidth * checkHeight / (double)checkWidth)]);
|
||||||
|
else
|
||||||
|
results.Add(validResolution, [desiredWidth, desiredHeight, orientation, Convert.ToInt32(desiredHeight * checkWidth / (double)checkHeight), desiredHeight]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] GetCollection(string outputResolution)
|
||||||
|
{
|
||||||
|
List<int> results = [];
|
||||||
|
string[] segments = outputResolution.Split('x');
|
||||||
|
results.Add(int.Parse(segments[0]));
|
||||||
|
results.Add(int.Parse(segments[1]));
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveResizedSubfile(Configuration configuration, string outputResolution, string cResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, Item item, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize)
|
||||||
|
{
|
||||||
|
if (mappingFromItem.ResizedFileHolder is null)
|
||||||
|
throw new NullReferenceException(nameof(mappingFromItem.ResizedFileHolder));
|
||||||
|
#pragma warning disable CA1854
|
||||||
|
if (!outputResolutionToResize.ContainsKey(_Original))
|
||||||
|
throw new Exception();
|
||||||
|
if (!outputResolutionToResize.ContainsKey(outputResolution))
|
||||||
|
throw new Exception();
|
||||||
|
#pragma warning restore CA1854
|
||||||
|
FileInfo fileInfo = new(mappingFromItem.ResizedFileHolder.FullName);
|
||||||
|
bool check = false;
|
||||||
|
int[] resize = outputResolutionToResize[outputResolution];
|
||||||
|
int outputResolutionWidth = resize[_OutputResolutionWidthIndex];
|
||||||
|
int outputResolutionHeight = resize[_OutputResolutionHeightIndex];
|
||||||
|
int outputResolutionOrientation = resize[_OutputResolutionOrientationIndex];
|
||||||
|
int[] originalCollection = outputResolutionToResize[_Original];
|
||||||
|
string[] changesFrom = [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();
|
||||||
|
if (_OverrideForResizeImages)
|
||||||
|
check = true;
|
||||||
|
else if (!fileInfo.Exists)
|
||||||
|
check = true;
|
||||||
|
if (outputResolutionWidth == originalCollection[_OutputResolutionWidthIndex] && outputResolutionHeight == originalCollection[_OutputResolutionHeightIndex] && outputResolutionOrientation == originalCollection[_OutputResolutionOrientationIndex])
|
||||||
|
{
|
||||||
|
if (!check && dateTimes.Count != 0 && dateTimes.Max() > fileInfo.CreationTime.AddDays(1))
|
||||||
|
check = true;
|
||||||
|
if (check)
|
||||||
|
{
|
||||||
|
// if (fileInfo.Exists)
|
||||||
|
// File.Delete(fileInfo.FullName);
|
||||||
|
// File.Copy(mappingFromItem.FilePath.FullName, fileInfo.FullName);
|
||||||
|
// item.SetResizedFileHolder(_FileNameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(mappingFromItem.ResizedFileHolder));
|
||||||
|
// subFileTuples.Add(new Tuple<string, DateTime>(nameof(C_Resize), DateTime.Now));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!check && dateTimes.Count != 0 && dateTimes.Max() > fileInfo.LastWriteTime)
|
||||||
|
check = true;
|
||||||
|
if (check)
|
||||||
|
{
|
||||||
|
SaveResizedSubfile(property, mappingFromItem, resize);
|
||||||
|
item.SetResizedFileHolder(_FileNameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(mappingFromItem.ResizedFileHolder));
|
||||||
|
subFileTuples.Add(new Tuple<string, DateTime>(nameof(C_Resize), DateTime.Now));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveResizedSubfile(Shared.Models.Property property, MappingFromItem mappingFromItem, int[] resize)
|
||||||
|
{
|
||||||
|
string dateTimeFormat = IProperty.DateTimeFormat;
|
||||||
|
DateTime dateTime = property.DateTimeOriginal is not null ? property.DateTimeOriginal.Value : Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
|
||||||
|
string dateTimeValue = dateTime.ToString(dateTimeFormat);
|
||||||
|
byte[] bytes = _ASCIIEncoding.GetBytes(dateTimeValue);
|
||||||
|
if (_ASCIIEncoding.GetString(bytes, 0, bytes.Length) != dateTimeValue)
|
||||||
|
throw new Exception();
|
||||||
|
if (resize.Length == 3)
|
||||||
|
SaveResizedSubfile3(mappingFromItem, resize, bytes);
|
||||||
|
else if (resize.Length == 5)
|
||||||
|
SaveResizedSubfile5(mappingFromItem, resize, bytes);
|
||||||
|
else
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveResizedSubfile3(MappingFromItem mappingFromItem, int[] resize, byte[] bytes)
|
||||||
|
{
|
||||||
|
Bitmap bitmap;
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
int outputResolutionWidth = resize[_OutputResolutionWidthIndex];
|
||||||
|
using Bitmap temp = new(mappingFromItem.FilePath.FullName, useIcm: false);
|
||||||
|
int outputResolutionHeight = resize[_OutputResolutionHeightIndex];
|
||||||
|
PropertyItem[] propertyItems = temp.PropertyItems;
|
||||||
|
int outputResolutionOrientation = resize[_OutputResolutionOrientationIndex];
|
||||||
|
bitmap = new(temp, outputResolutionWidth, outputResolutionHeight);
|
||||||
|
switch (outputResolutionOrientation) // exif 274
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
break; // 1 = Horizontal (normal)
|
||||||
|
case 2:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipX);
|
||||||
|
break; // 2 = Mirror horizontal
|
||||||
|
case 3:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
|
||||||
|
break; // 3 = Rotate 180
|
||||||
|
case 4:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||||
|
break; // 4 = Mirror vertical
|
||||||
|
case 5:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.Rotate270FlipX);
|
||||||
|
break; // 5 = Mirror horizontal and rotate 270 CW
|
||||||
|
case 6:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
|
||||||
|
break; // 6 = Rotate 90 CW
|
||||||
|
case 7:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
|
||||||
|
break; // 7 = Mirror horizontal and rotate 90 CW
|
||||||
|
case 8:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
|
||||||
|
break; // 8 = Rotate 270 CW
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CopyPropertyItems(bytes, propertyItems, bitmap);
|
||||||
|
bitmap.Save(mappingFromItem.ResizedFileHolder.FullName, _ImageCodecInfo, _EncoderParameters);
|
||||||
|
bitmap.Dispose();
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CopyPropertyItems(byte[] bytes, PropertyItem[] propertyItems, Bitmap bitmap)
|
||||||
|
{
|
||||||
|
bool hasId = false;
|
||||||
|
int id = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeDigitized;
|
||||||
|
int imageWidth = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageWidth;
|
||||||
|
int imageHeight = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageHeight;
|
||||||
|
int orientation = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation;
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
foreach (PropertyItem propertyItem in propertyItems)
|
||||||
|
{
|
||||||
|
if (propertyItem.Id == id)
|
||||||
|
hasId = true;
|
||||||
|
else if (propertyItem.Id == imageWidth)
|
||||||
|
continue;
|
||||||
|
else if (propertyItem.Id == imageHeight)
|
||||||
|
continue;
|
||||||
|
else if (propertyItem.Id == orientation)
|
||||||
|
continue;
|
||||||
|
bitmap.SetPropertyItem(propertyItem);
|
||||||
|
}
|
||||||
|
if (!hasId)
|
||||||
|
{
|
||||||
|
PropertyItem propertyItem = (PropertyItem)_ConstructorInfo.Invoke(null);
|
||||||
|
propertyItem.Id = id;
|
||||||
|
propertyItem.Len = bytes.Length;
|
||||||
|
propertyItem.Type = 2;
|
||||||
|
propertyItem.Value = bytes;
|
||||||
|
bitmap.SetPropertyItem(propertyItem);
|
||||||
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveResizedSubfile5(MappingFromItem mappingFromItem, int[] resize, byte[] bytes)
|
||||||
|
{
|
||||||
|
Bitmap bitmap;
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
using Bitmap temp = new(mappingFromItem.FilePath.FullName, useIcm: false);
|
||||||
|
PropertyItem[] propertyItems = temp.PropertyItems;
|
||||||
|
int tempResolutionWidth = resize[_TempResolutionWidth];
|
||||||
|
int tempResolutionHeight = resize[_TempResolutionHeight];
|
||||||
|
int outputResolutionWidth = resize[_OutputResolutionWidthIndex];
|
||||||
|
int outputResolutionHeight = resize[_OutputResolutionHeightIndex];
|
||||||
|
int outputResolutionOrientation = resize[_OutputResolutionOrientationIndex];
|
||||||
|
bitmap = new(temp, tempResolutionWidth, tempResolutionHeight);
|
||||||
|
switch (outputResolutionOrientation) // exif 274
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
break; // 1 = Horizontal (normal)
|
||||||
|
case 2:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipX);
|
||||||
|
break; // 2 = Mirror horizontal
|
||||||
|
case 3:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
|
||||||
|
break; // 3 = Rotate 180
|
||||||
|
case 4:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||||
|
break; // 4 = Mirror vertical
|
||||||
|
case 5:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.Rotate270FlipX);
|
||||||
|
break; // 5 = Mirror horizontal and rotate 270 CW
|
||||||
|
case 6:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
|
||||||
|
break; // 6 = Rotate 90 CW
|
||||||
|
case 7:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
|
||||||
|
break; // 7 = Mirror horizontal and rotate 90 CW
|
||||||
|
case 8:
|
||||||
|
bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
|
||||||
|
break; // 8 = Rotate 270 CW
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Bitmap preRotated;
|
||||||
|
Rectangle rectangle;
|
||||||
|
if (tempResolutionHeight < tempResolutionWidth)
|
||||||
|
rectangle = new Rectangle((int)((tempResolutionWidth - outputResolutionWidth) * .5), 0, outputResolutionWidth, outputResolutionHeight);
|
||||||
|
else
|
||||||
|
rectangle = new Rectangle(0, (int)((tempResolutionHeight - outputResolutionHeight) * .5), outputResolutionWidth, outputResolutionHeight);
|
||||||
|
using (preRotated = new Bitmap(outputResolutionWidth, outputResolutionHeight))
|
||||||
|
{
|
||||||
|
using (Graphics graphics = Graphics.FromImage(preRotated))
|
||||||
|
graphics.DrawImage(bitmap, new Rectangle(0, 0, outputResolutionWidth, outputResolutionHeight), rectangle, GraphicsUnit.Pixel);
|
||||||
|
CopyPropertyItems(bytes, propertyItems, bitmap);
|
||||||
|
bitmap.Save(mappingFromItem.ResizedFileHolder.FullName, _ImageCodecInfo, _EncoderParameters);
|
||||||
|
}
|
||||||
|
bitmap.Dispose();
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -5,59 +5,70 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
|||||||
public interface IDirectory
|
public interface IDirectory
|
||||||
{
|
{
|
||||||
|
|
||||||
char TestStatic_GetDirectory(string fileName) =>
|
public static int GetDirectory(char directory) =>
|
||||||
GetDirectory(fileName);
|
|
||||||
static char GetDirectory(string fileName) =>
|
|
||||||
fileName.Split('-').Length > 2 ? '-' : fileName.Split('.')[0][^1];
|
|
||||||
|
|
||||||
int TestStatic_GetDirectory(char directory) =>
|
|
||||||
GetDirectory(directory);
|
|
||||||
static int GetDirectory(char directory) =>
|
|
||||||
directory == '-' ? 10 : int.TryParse(directory.ToString(), out int value) ? value : 11;
|
directory == '-' ? 10 : int.TryParse(directory.ToString(), out int value) ? value : 11;
|
||||||
|
|
||||||
ReadOnlyCollection<string[]> TestStatic_GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) =>
|
public static char GetDirectory(string fileName) =>
|
||||||
GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
|
fileName.Split('-').Length > 2 ? '-' : fileName.Split('.')[0][^1];
|
||||||
static ReadOnlyCollection<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) =>
|
|
||||||
XDirectory.GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
|
|
||||||
|
|
||||||
ReadOnlyCollection<ReadOnlyCollection<FilePath>> TestStatic_GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string fileSearchFilter, string directory, bool useCeilingAverage) =>
|
public static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
|
||||||
GetFilePathCollections(propertyConfiguration, directorySearchFilter, fileSearchFilter, directory, useCeilingAverage);
|
|
||||||
static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string fileSearchFilter, string directory, bool useCeilingAverage) =>
|
|
||||||
XDirectory.GetFilePathCollections(propertyConfiguration, directorySearchFilter, fileSearchFilter, directory, useCeilingAverage);
|
|
||||||
|
|
||||||
void TestStatic_MoveFiles(List<string> files, string find, string replace) =>
|
|
||||||
MoveFiles(files, find, replace);
|
|
||||||
static void MoveFiles(List<string> files, string find, string replace) =>
|
|
||||||
XDirectory.MoveFiles(files, find, replace);
|
|
||||||
|
|
||||||
(string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
|
|
||||||
GetToDoCollection(propertyConfiguration, filePathsCollection, fileGroups, tick);
|
|
||||||
static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
|
|
||||||
XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates: false, ifCanUseId: true, filePathsCollection, fileGroups, tick);
|
|
||||||
|
|
||||||
(string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
|
|
||||||
GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, fileGroups, tick);
|
|
||||||
static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
|
|
||||||
XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, fileGroups, tick);
|
XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, fileGroups, tick);
|
||||||
|
|
||||||
List<string> TestStatic_CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) =>
|
public static void MoveFiles(List<string> files, string find, string replace) =>
|
||||||
CopyOrMove(toDoCollection, move, moveBack, tick);
|
XDirectory.MoveFiles(files, find, replace);
|
||||||
static List<string> CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) =>
|
|
||||||
|
public static List<string> CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) =>
|
||||||
XDirectory.CopyOrMove(toDoCollection, move, moveBack, tick);
|
XDirectory.CopyOrMove(toDoCollection, move, moveBack, tick);
|
||||||
|
|
||||||
ReadOnlyCollection<ReadOnlyCollection<FilePath>> TestStatic_GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) =>
|
public static int MaybeMove(Properties.IPropertyConfiguration propertyConfiguration, List<FilePair> filePairs, string jsonGroupDirectory, string extension) =>
|
||||||
GetFilePathCollections(propertyConfiguration, filesCollection);
|
|
||||||
static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) =>
|
|
||||||
XDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
|
|
||||||
|
|
||||||
List<FilePair> TestStatic_GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles) =>
|
|
||||||
GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, compareFileNamesToFiles);
|
|
||||||
static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles) =>
|
|
||||||
XDirectory.GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, compareFileNamesToFiles);
|
|
||||||
|
|
||||||
int TestStatic_MaybeMove(Properties.IPropertyConfiguration propertyConfiguration, List<FilePair> filePairs, string jsonGroupDirectory, string extension) =>
|
|
||||||
MaybeMove(propertyConfiguration, filePairs, jsonGroupDirectory, extension);
|
|
||||||
static int MaybeMove(Properties.IPropertyConfiguration propertyConfiguration, List<FilePair> filePairs, string jsonGroupDirectory, string extension) =>
|
|
||||||
XDirectory.MaybeMove(propertyConfiguration, filePairs, jsonGroupDirectory, extension);
|
XDirectory.MaybeMove(propertyConfiguration, filePairs, jsonGroupDirectory, extension);
|
||||||
|
|
||||||
|
public static ReadOnlyCollection<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) =>
|
||||||
|
XDirectory.GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
|
||||||
|
|
||||||
|
public static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) =>
|
||||||
|
XDirectory.GetFilePathCollections(propertyConfiguration, filesCollection);
|
||||||
|
|
||||||
|
public static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string fileSearchFilter, string directory, bool useCeilingAverage) =>
|
||||||
|
XDirectory.GetFilePathCollections(propertyConfiguration, directorySearchFilter, fileSearchFilter, directory, useCeilingAverage);
|
||||||
|
|
||||||
|
public static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles) =>
|
||||||
|
XDirectory.GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, compareFileNamesToFiles);
|
||||||
|
|
||||||
|
public static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
|
||||||
|
XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates: false, ifCanUseId: true, filePathsCollection, fileGroups, tick);
|
||||||
|
|
||||||
|
internal int TestStatic_GetDirectory(char directory) =>
|
||||||
|
GetDirectory(directory);
|
||||||
|
|
||||||
|
internal char TestStatic_GetDirectory(string fileName) =>
|
||||||
|
GetDirectory(fileName);
|
||||||
|
|
||||||
|
internal void TestStatic_MoveFiles(List<string> files, string find, string replace) =>
|
||||||
|
MoveFiles(files, find, replace);
|
||||||
|
|
||||||
|
internal List<string> TestStatic_CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick) =>
|
||||||
|
CopyOrMove(toDoCollection, move, moveBack, tick);
|
||||||
|
|
||||||
|
internal int TestStatic_MaybeMove(Properties.IPropertyConfiguration propertyConfiguration, List<FilePair> filePairs, string jsonGroupDirectory, string extension) =>
|
||||||
|
MaybeMove(propertyConfiguration, filePairs, jsonGroupDirectory, extension);
|
||||||
|
|
||||||
|
internal ReadOnlyCollection<string[]> TestStatic_GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage) =>
|
||||||
|
GetFilesCollection(directory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
|
||||||
|
|
||||||
|
internal ReadOnlyCollection<ReadOnlyCollection<FilePath>> TestStatic_GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection) =>
|
||||||
|
GetFilePathCollections(propertyConfiguration, filesCollection);
|
||||||
|
|
||||||
|
internal ReadOnlyCollection<ReadOnlyCollection<FilePath>> TestStatic_GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string fileSearchFilter, string directory, bool useCeilingAverage) =>
|
||||||
|
GetFilePathCollections(propertyConfiguration, directorySearchFilter, fileSearchFilter, directory, useCeilingAverage);
|
||||||
|
|
||||||
|
internal List<FilePair> TestStatic_GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles) =>
|
||||||
|
GetFiles(propertyConfiguration, filePathsCollection, fileNamesToFiles, compareFileNamesToFiles);
|
||||||
|
|
||||||
|
internal (string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
|
||||||
|
GetToDoCollection(propertyConfiguration, filePathsCollection, fileGroups, tick);
|
||||||
|
|
||||||
|
internal (string[], List<(FilePath, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick) =>
|
||||||
|
GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filePathsCollection, fileGroups, tick);
|
||||||
|
|
||||||
}
|
}
|
@ -1,63 +1,75 @@
|
|||||||
|
using View_by_Distance.Shared.Models.Properties;
|
||||||
|
|
||||||
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
||||||
|
|
||||||
public interface IId
|
public interface IId
|
||||||
{ // ...
|
{
|
||||||
|
|
||||||
const int DeterministicHashCode = 9876543;
|
const int DeterministicHashCode = 9876543;
|
||||||
|
|
||||||
static bool IsOffsetDeterministicHashCode(Properties.IPropertyConfiguration propertyConfiguration) =>
|
public static int GetDeterministicHashCode(byte[] value) =>
|
||||||
propertyConfiguration.Offset == DeterministicHashCode;
|
|
||||||
|
|
||||||
string TestStatic_GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
|
|
||||||
GetIntelligentId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal);
|
|
||||||
static string GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
|
|
||||||
Id.GetIntelligentId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal);
|
|
||||||
|
|
||||||
int TestStatic_GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) =>
|
|
||||||
GetId(propertyConfiguration, intelligentId);
|
|
||||||
static int GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) =>
|
|
||||||
Id.GetId(propertyConfiguration, intelligentId);
|
|
||||||
|
|
||||||
string TestStatic_GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
|
|
||||||
GetPaddedId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
|
|
||||||
static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
|
|
||||||
Id.GetPaddedId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
|
|
||||||
|
|
||||||
bool TestStatic_NameWithoutExtensionIsIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, string fileNameFirstSegment) =>
|
|
||||||
NameWithoutExtensionIsIntelligentIdFormat(propertyConfiguration, fileNameFirstSegment);
|
|
||||||
static bool NameWithoutExtensionIsIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, string fileNameFirstSegment) =>
|
|
||||||
fileNameFirstSegment.Length - 1 == propertyConfiguration.IntMinValueLength && fileNameFirstSegment[^1] is '1' or '2' or '3' or '7' or '8' or '9' && fileNameFirstSegment.All(char.IsNumber);
|
|
||||||
|
|
||||||
bool TestStatic_NameWithoutExtensionIsPaddedIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
|
||||||
NameWithoutExtensionIsPaddedIntelligentIdFormat(propertyConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment);
|
|
||||||
static bool NameWithoutExtensionIsPaddedIntelligentIdFormat(Properties.IPropertyConfiguration propertyConfiguration, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
|
||||||
fileNameFirstSegment.Length == propertyConfiguration.IntMinValueLength + sortOrderOnlyLengthIndex + 1
|
|
||||||
&& fileNameFirstSegment[^1] is '1' or '2' or '3' or '7' or '8' or '9'
|
|
||||||
&& fileNameFirstSegment.All(char.IsNumber);
|
|
||||||
|
|
||||||
bool TestStatic_NameWithoutExtensionIsIdFormat(Properties.IPropertyConfiguration propertyConfiguration, Models.FileHolder fileHolder) =>
|
|
||||||
NameWithoutExtensionIsIdFormat(propertyConfiguration, fileHolder);
|
|
||||||
static bool NameWithoutExtensionIsIdFormat(Properties.IPropertyConfiguration propertyConfiguration, Models.FileHolder fileHolder) =>
|
|
||||||
Id.NameWithoutExtensionIsIdFormat(propertyConfiguration, fileHolder.NameWithoutExtension.Split('.')[0]);
|
|
||||||
|
|
||||||
int TestStatic_GetDeterministicHashCode(byte[] value) =>
|
|
||||||
GetDeterministicHashCode(value);
|
|
||||||
static int GetDeterministicHashCode(byte[] value) =>
|
|
||||||
Id.GetDeterministicHashCode(value);
|
Id.GetDeterministicHashCode(value);
|
||||||
|
|
||||||
int TestStatic_GetHasIgnoreKeyword(FilePath filePath) =>
|
public static byte GetHasIgnoreKeyword(FilePath filePath) =>
|
||||||
GetHasIgnoreKeyword(filePath);
|
|
||||||
static int GetHasIgnoreKeyword(FilePath filePath) =>
|
|
||||||
Id.GetHasIgnoreKeyword(filePath);
|
Id.GetHasIgnoreKeyword(filePath);
|
||||||
|
|
||||||
int TestStatic_GetMissingDateTimeOriginal(FilePath filePath) =>
|
public static int GetId(IPropertyConfiguration propertyConfiguration, string intelligentId) =>
|
||||||
GetMissingDateTimeOriginal(filePath);
|
Id.GetId(propertyConfiguration, intelligentId);
|
||||||
static int GetMissingDateTimeOriginal(FilePath filePath) =>
|
|
||||||
Id.GetMissingDateTimeOriginal(filePath);
|
|
||||||
|
|
||||||
int TestStatic_GetHasDateTimeOriginal(FilePath filePath) =>
|
public static bool IsOffsetDeterministicHashCode(IPropertyConfiguration propertyConfiguration) =>
|
||||||
GetHasDateTimeOriginal(filePath);
|
propertyConfiguration.Offset == DeterministicHashCode;
|
||||||
static int GetHasDateTimeOriginal(FilePath filePath) =>
|
|
||||||
Id.GetHasDateTimeOriginal(filePath);
|
public static byte GetHasDateTimeOriginal(IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
|
||||||
|
Id.GetHasDateTimeOriginal(propertyConfiguration, filePath);
|
||||||
|
|
||||||
|
public static byte GetMissingDateTimeOriginal(IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
|
||||||
|
Id.GetMissingDateTimeOriginal(propertyConfiguration, filePath);
|
||||||
|
|
||||||
|
public static bool NameWithoutExtensionIsIdFormat(IPropertyConfiguration propertyConfiguration, Models.FileHolder fileHolder) =>
|
||||||
|
Id.NameWithoutExtensionIsIdFormat(propertyConfiguration, fileHolder.NameWithoutExtension.Split('.')[0]);
|
||||||
|
|
||||||
|
public static bool NameWithoutExtensionIsIntelligentIdFormat(IPropertyConfiguration propertyConfiguration, string fileNameFirstSegment) =>
|
||||||
|
fileNameFirstSegment.Length - 1 == propertyConfiguration.IntMinValueLength && fileNameFirstSegment[^1] is '1' or '2' or '3' or '4' or '5' or '6' or '7' or '8' or '9' && fileNameFirstSegment.All(char.IsNumber);
|
||||||
|
|
||||||
|
public static string GetIntelligentId(IPropertyConfiguration propertyConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
|
||||||
|
Id.GetIntelligentId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal);
|
||||||
|
|
||||||
|
public static string GetPaddedId(IPropertyConfiguration propertyConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
|
||||||
|
Id.GetPaddedId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
|
||||||
|
|
||||||
|
public static bool NameWithoutExtensionIsPaddedIntelligentIdFormat(IPropertyConfiguration propertyConfiguration, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
||||||
|
fileNameFirstSegment.Length == propertyConfiguration.IntMinValueLength + sortOrderOnlyLengthIndex + 1
|
||||||
|
&& fileNameFirstSegment[^1] is '1' or '2' or '3' or '4' or '5' or '6' or '7' or '8' or '9'
|
||||||
|
&& fileNameFirstSegment.All(char.IsNumber);
|
||||||
|
|
||||||
|
internal int TestStatic_GetDeterministicHashCode(byte[] value) =>
|
||||||
|
GetDeterministicHashCode(value);
|
||||||
|
|
||||||
|
internal byte TestStatic_GetHasIgnoreKeyword(FilePath filePath) =>
|
||||||
|
GetHasIgnoreKeyword(filePath);
|
||||||
|
|
||||||
|
internal int TestStatic_GetId(IPropertyConfiguration propertyConfiguration, string intelligentId) =>
|
||||||
|
GetId(propertyConfiguration, intelligentId);
|
||||||
|
|
||||||
|
internal byte TestStatic_GetHasDateTimeOriginal(IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
|
||||||
|
GetHasDateTimeOriginal(propertyConfiguration, filePath);
|
||||||
|
|
||||||
|
internal byte TestStatic_GetMissingDateTimeOriginal(IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
|
||||||
|
GetMissingDateTimeOriginal(propertyConfiguration, filePath);
|
||||||
|
|
||||||
|
internal bool TestStatic_NameWithoutExtensionIsIdFormat(IPropertyConfiguration propertyConfiguration, Models.FileHolder fileHolder) =>
|
||||||
|
NameWithoutExtensionIsIdFormat(propertyConfiguration, fileHolder);
|
||||||
|
|
||||||
|
internal bool TestStatic_NameWithoutExtensionIsIntelligentIdFormat(IPropertyConfiguration propertyConfiguration, string fileNameFirstSegment) =>
|
||||||
|
NameWithoutExtensionIsIntelligentIdFormat(propertyConfiguration, fileNameFirstSegment);
|
||||||
|
|
||||||
|
internal string TestStatic_GetIntelligentId(IPropertyConfiguration propertyConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
|
||||||
|
GetIntelligentId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal);
|
||||||
|
|
||||||
|
internal string TestStatic_GetPaddedId(IPropertyConfiguration propertyConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
|
||||||
|
GetPaddedId(propertyConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
|
||||||
|
|
||||||
|
internal bool TestStatic_NameWithoutExtensionIsPaddedIntelligentIdFormat(IPropertyConfiguration propertyConfiguration, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
||||||
|
NameWithoutExtensionIsPaddedIntelligentIdFormat(propertyConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment);
|
||||||
|
|
||||||
}
|
}
|
@ -4,77 +4,89 @@ using View_by_Distance.Shared.Models.Properties;
|
|||||||
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
||||||
|
|
||||||
public interface IPath
|
public interface IPath
|
||||||
{ // ...
|
{
|
||||||
|
|
||||||
string TestStatic_GetRelativePath(string path, int length) =>
|
public static byte GetEnum(FilePath filePath) =>
|
||||||
GetRelativePath(path, length);
|
|
||||||
static string GetRelativePath(string path, int length) =>
|
|
||||||
XPath.GetRelativePath(path, length, forceExtensionToLower: false);
|
|
||||||
|
|
||||||
bool TestStatic_DeleteEmptyDirectories(string rootDirectory) =>
|
|
||||||
DeleteEmptyDirectories(rootDirectory);
|
|
||||||
static bool DeleteEmptyDirectories(string rootDirectory) =>
|
|
||||||
XPath.DeleteEmptyDirectories(rootDirectory);
|
|
||||||
|
|
||||||
void TestStatic_ChangeDateForEmptyDirectories(string rootDirectory, long ticks) =>
|
|
||||||
ChangeDateForEmptyDirectories(rootDirectory, ticks);
|
|
||||||
static void ChangeDateForEmptyDirectories(string rootDirectory, long ticks) =>
|
|
||||||
XPath.ChangeDateForEmptyDirectories(rootDirectory, ticks);
|
|
||||||
|
|
||||||
void TestStatic_MakeHiddenIfAllItemsAreHidden(string rootDirectory) =>
|
|
||||||
MakeHiddenIfAllItemsAreHidden(rootDirectory);
|
|
||||||
static void MakeHiddenIfAllItemsAreHidden(string rootDirectory) =>
|
|
||||||
XPath.MakeHiddenIfAllItemsAreHidden(rootDirectory);
|
|
||||||
|
|
||||||
void TestStatic_DeleteEmptyDirectories(string rootDirectory, List<string> deletedDirectories) =>
|
|
||||||
DeleteEmptyDirectories(rootDirectory, deletedDirectories);
|
|
||||||
static void DeleteEmptyDirectories(string rootDirectory, List<string> deletedDirectories) =>
|
|
||||||
XPath.DeleteEmptyDirectories(rootDirectory, deletedDirectories);
|
|
||||||
// $dirs = gci "" -directory -recurse | Where { (gci $_.fullName).count -eq 0 } | select -expandproperty FullName $dirs | Foreach-Object { Remove-Item $_ }
|
|
||||||
|
|
||||||
string[] TestStatic_GetDirectoryNames(string directory) =>
|
|
||||||
GetDirectoryNames(directory);
|
|
||||||
static string[] GetDirectoryNames(string directory) =>
|
|
||||||
XPath.GetDirectoryNames(directory).ToArray();
|
|
||||||
|
|
||||||
string[] TestStatic_GetDirectories(string directory) =>
|
|
||||||
GetDirectories(directory);
|
|
||||||
static string[] GetDirectories(string directory) =>
|
|
||||||
XPath.GetDirectories(directory).ToArray();
|
|
||||||
|
|
||||||
string TestStatic_GetRelativePath(string path, int length, bool forceExtensionToLower) =>
|
|
||||||
GetRelativePath(path, length, forceExtensionToLower);
|
|
||||||
static string GetRelativePath(string path, int length, bool forceExtensionToLower) =>
|
|
||||||
XPath.GetRelativePath(path, length, forceExtensionToLower);
|
|
||||||
|
|
||||||
bool TestStatic_WriteAllText(string path, string contents, bool updateDateWhenMatches, bool compareBeforeWrite, DateTime? updateToWhenMatches = null) =>
|
|
||||||
WriteAllText(path, contents, updateDateWhenMatches, compareBeforeWrite, updateToWhenMatches);
|
|
||||||
static bool WriteAllText(string path, string contents, bool updateDateWhenMatches, bool compareBeforeWrite, DateTime? updateToWhenMatches = null) =>
|
|
||||||
XPath.WriteAllText(path, contents, updateDateWhenMatches, compareBeforeWrite, updateToWhenMatches);
|
|
||||||
|
|
||||||
(int level, List<string> directories) TestStatic_Get(string rootDirectory, string sourceDirectory) =>
|
|
||||||
Get(rootDirectory, sourceDirectory);
|
|
||||||
static (int level, List<string> directories) Get(string rootDirectory, string sourceDirectory) =>
|
|
||||||
XPath.Get(rootDirectory, sourceDirectory);
|
|
||||||
|
|
||||||
string TestStatic_GetDirectory(string sourceDirectory, int level, string directoryName) =>
|
|
||||||
GetDirectory(sourceDirectory, level, directoryName);
|
|
||||||
static string GetDirectory(string sourceDirectory, int level, string directoryName) =>
|
|
||||||
XPath.GetDirectory(sourceDirectory, level, directoryName);
|
|
||||||
|
|
||||||
CombinedEnumAndIndex TestStatic_GetCombinedEnumAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
|
|
||||||
GetCombinedEnumAndIndex(propertyConfiguration, filePath);
|
|
||||||
static CombinedEnumAndIndex GetCombinedEnumAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
|
|
||||||
XPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
|
|
||||||
|
|
||||||
ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> TestStatic_GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups) =>
|
|
||||||
GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, jsonGroups);
|
|
||||||
static ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups) =>
|
|
||||||
XPath.GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, jsonGroups);
|
|
||||||
|
|
||||||
byte TestStatic_GetEnum(FilePath filePath) =>
|
|
||||||
GetEnum(filePath);
|
|
||||||
static byte GetEnum(FilePath filePath) =>
|
|
||||||
XPath.GetEnum(filePath);
|
XPath.GetEnum(filePath);
|
||||||
|
|
||||||
|
public static string[] GetDirectories(string directory) =>
|
||||||
|
XPath.GetDirectories(directory).ToArray();
|
||||||
|
|
||||||
|
public static string[] GetDirectoryNames(string directory) =>
|
||||||
|
XPath.GetDirectoryNames(directory).ToArray();
|
||||||
|
|
||||||
|
public static string GetRelativePath(string path, int length) =>
|
||||||
|
XPath.GetRelativePath(path, length, forceExtensionToLower: false);
|
||||||
|
|
||||||
|
public static bool DeleteEmptyDirectories(string rootDirectory) =>
|
||||||
|
XPath.DeleteEmptyDirectories(rootDirectory);
|
||||||
|
|
||||||
|
public static void MakeHiddenIfAllItemsAreHidden(string rootDirectory) =>
|
||||||
|
XPath.MakeHiddenIfAllItemsAreHidden(rootDirectory);
|
||||||
|
|
||||||
|
public static void ChangeDateForEmptyDirectories(string rootDirectory, long ticks) =>
|
||||||
|
XPath.ChangeDateForEmptyDirectories(rootDirectory, ticks);
|
||||||
|
|
||||||
|
public static string GetRelativePath(string path, int length, bool forceExtensionToLower) =>
|
||||||
|
XPath.GetRelativePath(path, length, forceExtensionToLower);
|
||||||
|
|
||||||
|
public static string GetDirectory(string sourceDirectory, int level, string directoryName) =>
|
||||||
|
XPath.GetDirectory(sourceDirectory, level, directoryName);
|
||||||
|
|
||||||
|
public static void DeleteEmptyDirectories(string rootDirectory, List<string> deletedDirectories) =>
|
||||||
|
XPath.DeleteEmptyDirectories(rootDirectory, deletedDirectories);
|
||||||
|
public static (int level, List<string> directories) Get(string rootDirectory, string sourceDirectory) =>
|
||||||
|
XPath.Get(rootDirectory, sourceDirectory);
|
||||||
|
|
||||||
|
public static CombinedEnumAndIndex GetCombinedEnumAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
|
||||||
|
XPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
|
||||||
|
|
||||||
|
public static bool WriteAllText(string path, string contents, bool updateDateWhenMatches, bool compareBeforeWrite, DateTime? updateToWhenMatches = null) =>
|
||||||
|
XPath.WriteAllText(path, contents, updateDateWhenMatches, compareBeforeWrite, updateToWhenMatches);
|
||||||
|
|
||||||
|
public static ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups) =>
|
||||||
|
XPath.GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, jsonGroups);
|
||||||
|
|
||||||
|
internal byte TestStatic_GetEnum(FilePath filePath) =>
|
||||||
|
GetEnum(filePath);
|
||||||
|
|
||||||
|
internal string[] TestStatic_GetDirectories(string directory) =>
|
||||||
|
GetDirectories(directory);
|
||||||
|
|
||||||
|
internal string[] TestStatic_GetDirectoryNames(string directory) =>
|
||||||
|
GetDirectoryNames(directory);
|
||||||
|
|
||||||
|
internal string TestStatic_GetRelativePath(string path, int length) =>
|
||||||
|
GetRelativePath(path, length);
|
||||||
|
|
||||||
|
internal bool TestStatic_DeleteEmptyDirectories(string rootDirectory) =>
|
||||||
|
DeleteEmptyDirectories(rootDirectory);
|
||||||
|
|
||||||
|
internal void TestStatic_MakeHiddenIfAllItemsAreHidden(string rootDirectory) =>
|
||||||
|
MakeHiddenIfAllItemsAreHidden(rootDirectory);
|
||||||
|
|
||||||
|
internal void TestStatic_ChangeDateForEmptyDirectories(string rootDirectory, long ticks) =>
|
||||||
|
ChangeDateForEmptyDirectories(rootDirectory, ticks);
|
||||||
|
|
||||||
|
internal string TestStatic_GetRelativePath(string path, int length, bool forceExtensionToLower) =>
|
||||||
|
GetRelativePath(path, length, forceExtensionToLower);
|
||||||
|
|
||||||
|
internal string TestStatic_GetDirectory(string sourceDirectory, int level, string directoryName) =>
|
||||||
|
GetDirectory(sourceDirectory, level, directoryName);
|
||||||
|
|
||||||
|
internal void TestStatic_DeleteEmptyDirectories(string rootDirectory, List<string> deletedDirectories) =>
|
||||||
|
DeleteEmptyDirectories(rootDirectory, deletedDirectories);
|
||||||
|
|
||||||
|
internal (int level, List<string> directories) TestStatic_Get(string rootDirectory, string sourceDirectory) =>
|
||||||
|
Get(rootDirectory, sourceDirectory);
|
||||||
|
|
||||||
|
internal CombinedEnumAndIndex TestStatic_GetCombinedEnumAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
|
||||||
|
GetCombinedEnumAndIndex(propertyConfiguration, filePath);
|
||||||
|
|
||||||
|
internal bool TestStatic_WriteAllText(string path, string contents, bool updateDateWhenMatches, bool compareBeforeWrite, DateTime? updateToWhenMatches = null) =>
|
||||||
|
WriteAllText(path, contents, updateDateWhenMatches, compareBeforeWrite, updateToWhenMatches);
|
||||||
|
|
||||||
|
internal ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> TestStatic_GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups) =>
|
||||||
|
GetKeyValuePairs(propertyConfiguration, resultsFullGroupDirectory, jsonGroups);
|
||||||
|
|
||||||
}
|
}
|
@ -5,6 +5,51 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
|||||||
internal abstract class Id
|
internal abstract class Id
|
||||||
{
|
{
|
||||||
|
|
||||||
|
internal static int GetDeterministicHashCode(byte[] value)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hash1 = (5381 << 16) + 5381;
|
||||||
|
int hash2 = hash1;
|
||||||
|
for (int i = 0; i < value.Length; i += 2)
|
||||||
|
{
|
||||||
|
hash1 = ((hash1 << 5) + hash1) ^ value[i];
|
||||||
|
if (i == value.Length - 1)
|
||||||
|
break;
|
||||||
|
hash2 = ((hash2 << 5) + hash2) ^ value[i + 1];
|
||||||
|
}
|
||||||
|
result = hash1 + (hash2 * 1566083941);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static byte GetHasIgnoreKeyword(FilePath filePath) =>
|
||||||
|
(byte)(filePath.Id > -1 ? 8 : 2);
|
||||||
|
|
||||||
|
internal static int GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
StringBuilder results = new();
|
||||||
|
if (propertyConfiguration.IntMinValueLength < (propertyConfiguration.ResultAllInOneSubdirectoryLength + 2))
|
||||||
|
throw new NotSupportedException();
|
||||||
|
for (int i = intelligentId.Length - (propertyConfiguration.ResultAllInOneSubdirectoryLength + 2); i > -1; i--)
|
||||||
|
_ = results.Append(intelligentId[i]);
|
||||||
|
_ = results.Append(intelligentId[^3]).Append(intelligentId[^2]);
|
||||||
|
result = int.Parse(results.ToString());
|
||||||
|
if (intelligentId[^1] is '1' or '2' or '3' or '4')
|
||||||
|
result *= -1;
|
||||||
|
else if (intelligentId[^1] is not '9' and not '8' and not '7' and not '6' and not '5')
|
||||||
|
throw new NotSupportedException();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static byte GetHasDateTimeOriginal(Properties.IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
|
||||||
|
(byte)(!propertyConfiguration.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered) ? filePath.Id > -1 ? 9 : 1 : filePath.Id > -1 ? 6 : 4);
|
||||||
|
|
||||||
|
internal static byte GetMissingDateTimeOriginal(Properties.IPropertyConfiguration propertyConfiguration, FilePath filePath) =>
|
||||||
|
(byte)(!propertyConfiguration.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered) ? filePath.Id > -1 ? 7 : 3 : 5);
|
||||||
|
|
||||||
internal static bool NameWithoutExtensionIsIdFormat(Properties.IPropertyConfiguration propertyConfiguration, string fileNameWithoutExtension)
|
internal static bool NameWithoutExtensionIsIdFormat(Properties.IPropertyConfiguration propertyConfiguration, string fileNameWithoutExtension)
|
||||||
{
|
{
|
||||||
bool result;
|
bool result;
|
||||||
@ -18,32 +63,6 @@ internal abstract class Id
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static int GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
StringBuilder results = new();
|
|
||||||
if (propertyConfiguration.IntMinValueLength < (propertyConfiguration.ResultAllInOneSubdirectoryLength + 2))
|
|
||||||
throw new NotSupportedException();
|
|
||||||
for (int i = intelligentId.Length - (propertyConfiguration.ResultAllInOneSubdirectoryLength + 2); i > -1; i--)
|
|
||||||
_ = results.Append(intelligentId[i]);
|
|
||||||
_ = results.Append(intelligentId[^3]).Append(intelligentId[^2]);
|
|
||||||
result = int.Parse(results.ToString());
|
|
||||||
if (intelligentId[^1] is '1' or '2' or '3')
|
|
||||||
result *= -1;
|
|
||||||
else if (intelligentId[^1] is not '9' and not '8' and not '7')
|
|
||||||
throw new NotSupportedException();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static int GetHasIgnoreKeyword(FilePath filePath) =>
|
|
||||||
filePath.Id > -1 ? 8 : 2;
|
|
||||||
|
|
||||||
internal static int GetMissingDateTimeOriginal(FilePath filePath) =>
|
|
||||||
filePath.Id > -1 ? 7 : 3;
|
|
||||||
|
|
||||||
internal static int GetHasDateTimeOriginal(FilePath filePath) =>
|
|
||||||
filePath.Id > -1 ? 9 : 1;
|
|
||||||
|
|
||||||
internal static string GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal)
|
internal static string GetIntelligentId(Properties.IPropertyConfiguration propertyConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal)
|
||||||
{
|
{
|
||||||
string result;
|
string result;
|
||||||
@ -89,23 +108,4 @@ internal abstract class Id
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static int GetDeterministicHashCode(byte[] value)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
unchecked
|
|
||||||
{
|
|
||||||
int hash1 = (5381 << 16) + 5381;
|
|
||||||
int hash2 = hash1;
|
|
||||||
for (int i = 0; i < value.Length; i += 2)
|
|
||||||
{
|
|
||||||
hash1 = ((hash1 << 5) + hash1) ^ value[i];
|
|
||||||
if (i == value.Length - 1)
|
|
||||||
break;
|
|
||||||
hash2 = ((hash2 << 5) + hash2) ^ value[i + 1];
|
|
||||||
}
|
|
||||||
result = hash1 + (hash2 * 1566083941);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -5,31 +5,119 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
|||||||
internal abstract partial class XDirectory
|
internal abstract partial class XDirectory
|
||||||
{
|
{
|
||||||
|
|
||||||
private static int GetCeilingAverage(List<string[]> fileCollection)
|
internal static void MoveFiles(List<string> files, string find, string replace)
|
||||||
{
|
{
|
||||||
List<int> counts = [];
|
string checkFile;
|
||||||
foreach (string[] files in fileCollection)
|
string? checkDirectory;
|
||||||
counts.Add(files.Length);
|
List<string> directories = [];
|
||||||
int average = (int)Math.Ceiling(counts.Average());
|
foreach (string file in files)
|
||||||
return average;
|
{
|
||||||
|
checkDirectory = Path.GetDirectoryName(file.Replace(find, replace));
|
||||||
|
if (string.IsNullOrEmpty(checkDirectory) || directories.Contains(checkDirectory))
|
||||||
|
continue;
|
||||||
|
directories.Add(checkDirectory);
|
||||||
|
}
|
||||||
|
foreach (string directory in directories)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(directory))
|
||||||
|
continue;
|
||||||
|
_ = Directory.CreateDirectory(directory);
|
||||||
|
}
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
if (!File.Exists(file))
|
||||||
|
continue;
|
||||||
|
checkFile = file.Replace(find, replace);
|
||||||
|
if (File.Exists(checkFile))
|
||||||
|
{
|
||||||
|
File.Delete(checkFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
File.Move(file, checkFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<string[]> GetFilesCollection(List<string[]> fileCollection, int ceilingAverage)
|
internal static List<string> CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick)
|
||||||
{
|
{
|
||||||
List<string[]> results = [];
|
List<string> results = [];
|
||||||
foreach (string[] files in fileCollection)
|
FileInfo fileInfo;
|
||||||
|
List<string> distinctExtensions = [];
|
||||||
|
foreach ((FilePath filePath, string to) in toDoCollection)
|
||||||
{
|
{
|
||||||
if (files.Length < ceilingAverage)
|
tick?.Invoke();
|
||||||
results.Add(files);
|
fileInfo = new(to);
|
||||||
}
|
if (fileInfo.Exists)
|
||||||
foreach (string[] files in fileCollection)
|
{
|
||||||
{
|
if (filePath.Length == fileInfo.Length && filePath.LastWriteTicks == fileInfo.LastWriteTime.Ticks)
|
||||||
if (files.Length >= ceilingAverage)
|
continue;
|
||||||
results.Add(files);
|
fileInfo.Delete();
|
||||||
|
}
|
||||||
|
results.Add(filePath.NameWithoutExtension);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!distinctExtensions.Contains(filePath.ExtensionLowered))
|
||||||
|
distinctExtensions.Add(filePath.ExtensionLowered);
|
||||||
|
if (move || moveBack)
|
||||||
|
File.Move(filePath.FullName, to);
|
||||||
|
else
|
||||||
|
File.Copy(filePath.FullName, to);
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static int MaybeMove(Properties.IPropertyConfiguration propertyConfiguration, List<FilePair> filePairs, string jsonGroupDirectory, string extension)
|
||||||
|
{
|
||||||
|
FileInfo? toFileInfo;
|
||||||
|
FileInfo fromFileInfo;
|
||||||
|
string checkDirectory;
|
||||||
|
List<(string, string)> rename = [];
|
||||||
|
foreach (FilePair filePair in filePairs)
|
||||||
|
{
|
||||||
|
if (filePair.IsUnique)
|
||||||
|
continue;
|
||||||
|
IsNotUniqueLoop(propertyConfiguration, jsonGroupDirectory, extension, filePair, rename);
|
||||||
|
}
|
||||||
|
foreach ((string from, string to) in rename)
|
||||||
|
{
|
||||||
|
toFileInfo = null;
|
||||||
|
checkDirectory = to;
|
||||||
|
fromFileInfo = new(from);
|
||||||
|
if (!fromFileInfo.Exists)
|
||||||
|
continue;
|
||||||
|
for (int i = 0; i < int.MaxValue; i++)
|
||||||
|
{
|
||||||
|
toFileInfo = new(checkDirectory);
|
||||||
|
if (toFileInfo.Directory is null)
|
||||||
|
continue;
|
||||||
|
if (!toFileInfo.Directory.Exists)
|
||||||
|
_ = Directory.CreateDirectory(toFileInfo.Directory.FullName);
|
||||||
|
if (checkDirectory.Length > 199)
|
||||||
|
throw new Exception();
|
||||||
|
if (!toFileInfo.Exists)
|
||||||
|
break;
|
||||||
|
else if (fromFileInfo.Length == toFileInfo.Length && fromFileInfo.LastWriteTime == toFileInfo.LastWriteTime)
|
||||||
|
checkDirectory = string.Concat(checkDirectory, ".del");
|
||||||
|
else
|
||||||
|
checkDirectory = string.Concat(checkDirectory, ".j");
|
||||||
|
}
|
||||||
|
File.Move(from, checkDirectory);
|
||||||
|
}
|
||||||
|
return rename.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void IsNotUniqueLoop(Properties.IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, FilePair filePair, List<(string, string)> rename)
|
||||||
|
{
|
||||||
|
int length = propertyConfiguration.RootDirectory.Length;
|
||||||
|
foreach (string path in filePair.Collection)
|
||||||
|
{
|
||||||
|
if (filePair.Match is null || path != filePair.Match)
|
||||||
|
continue;
|
||||||
|
rename.Add(new(path, string.Concat(jsonGroupDirectory, filePair.Path[length..], extension)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal static ReadOnlyCollection<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage)
|
internal static ReadOnlyCollection<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter, bool useCeilingAverage)
|
||||||
{
|
{
|
||||||
List<string[]> results = [];
|
List<string[]> results = [];
|
||||||
@ -60,6 +148,53 @@ internal abstract partial class XDirectory
|
|||||||
return results.AsReadOnly();
|
return results.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int GetCeilingAverage(List<string[]> fileCollection)
|
||||||
|
{
|
||||||
|
List<int> counts = [];
|
||||||
|
foreach (string[] files in fileCollection)
|
||||||
|
counts.Add(files.Length);
|
||||||
|
int average = (int)Math.Ceiling(counts.Average());
|
||||||
|
return average;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string[]> GetFilesCollection(List<string[]> fileCollection, int ceilingAverage)
|
||||||
|
{
|
||||||
|
List<string[]> results = [];
|
||||||
|
foreach (string[] files in fileCollection)
|
||||||
|
{
|
||||||
|
if (files.Length < ceilingAverage)
|
||||||
|
results.Add(files);
|
||||||
|
}
|
||||||
|
foreach (string[] files in fileCollection)
|
||||||
|
{
|
||||||
|
if (files.Length >= ceilingAverage)
|
||||||
|
results.Add(files);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection)
|
||||||
|
{
|
||||||
|
List<ReadOnlyCollection<FilePath>> results = [];
|
||||||
|
FilePath filePath;
|
||||||
|
List<FilePath> filePaths;
|
||||||
|
Models.FileHolder fileHolder;
|
||||||
|
foreach (string[] files in filesCollection)
|
||||||
|
{
|
||||||
|
filePaths = [];
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
fileHolder = IFileHolder.Get(file);
|
||||||
|
if (propertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
|
||||||
|
continue;
|
||||||
|
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
|
||||||
|
filePaths.Add(filePath);
|
||||||
|
}
|
||||||
|
results.Add(new(filePaths));
|
||||||
|
}
|
||||||
|
return results.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
internal static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string fileSearchFilter, string directory, bool useCeilingAverage)
|
internal static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string fileSearchFilter, string directory, bool useCeilingAverage)
|
||||||
{
|
{
|
||||||
ReadOnlyCollection<ReadOnlyCollection<FilePath>> results;
|
ReadOnlyCollection<ReadOnlyCollection<FilePath>> results;
|
||||||
@ -68,48 +203,6 @@ internal abstract partial class XDirectory
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool GetIsNotUniqueAndNeedsReview(string file, List<string> collection)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
FileInfo possibleFileInfo;
|
|
||||||
FileInfo fileInfo = new(file);
|
|
||||||
foreach (string possible in collection)
|
|
||||||
{
|
|
||||||
if (possible == file)
|
|
||||||
continue;
|
|
||||||
possibleFileInfo = new(possible);
|
|
||||||
if (possibleFileInfo.LastWriteTime != fileInfo.LastWriteTime)
|
|
||||||
File.SetLastWriteTime(file, new DateTime[] { possibleFileInfo.LastWriteTime, fileInfo.LastWriteTime }.Max());
|
|
||||||
if (possibleFileInfo.LastWriteTime == fileInfo.LastWriteTime && possibleFileInfo.Length == fileInfo.Length)
|
|
||||||
continue;
|
|
||||||
if (!result)
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string? GetMatch(string file, List<string> collection)
|
|
||||||
{
|
|
||||||
string? result = null;
|
|
||||||
FileInfo possibleFileInfo;
|
|
||||||
List<long> lengths = [];
|
|
||||||
List<string> matches = [];
|
|
||||||
FileInfo fileInfo = new(file);
|
|
||||||
List<DateTime> creationTimes = [];
|
|
||||||
foreach (string possible in collection)
|
|
||||||
{
|
|
||||||
possibleFileInfo = new(possible);
|
|
||||||
lengths.Add(possibleFileInfo.Length);
|
|
||||||
creationTimes.Add(possibleFileInfo.CreationTime);
|
|
||||||
if (possibleFileInfo.CreationTime != fileInfo.LastWriteTime)
|
|
||||||
continue;
|
|
||||||
matches.Add(possible);
|
|
||||||
}
|
|
||||||
if (matches.Count == 1 || (matches.Count > 0 && lengths.Distinct().Count() == 1 && creationTimes.Distinct().Count() == 1))
|
|
||||||
result = matches.First();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles)
|
internal static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles)
|
||||||
{
|
{
|
||||||
List<FilePair> results = [];
|
List<FilePair> results = [];
|
||||||
@ -168,126 +261,51 @@ internal abstract partial class XDirectory
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void IsNotUniqueLoop(Properties.IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, FilePair filePair, List<(string, string)> rename)
|
private static bool GetIsNotUniqueAndNeedsReview(string file, List<string> collection)
|
||||||
{
|
{
|
||||||
int length = propertyConfiguration.RootDirectory.Length;
|
bool result = false;
|
||||||
foreach (string path in filePair.Collection)
|
FileInfo possibleFileInfo;
|
||||||
|
FileInfo fileInfo = new(file);
|
||||||
|
foreach (string possible in collection)
|
||||||
{
|
{
|
||||||
if (filePair.Match is null || path != filePair.Match)
|
if (possible == file)
|
||||||
continue;
|
continue;
|
||||||
rename.Add(new(path, string.Concat(jsonGroupDirectory, filePair.Path[length..], extension)));
|
possibleFileInfo = new(possible);
|
||||||
|
if (possibleFileInfo.LastWriteTime != fileInfo.LastWriteTime)
|
||||||
|
File.SetLastWriteTime(file, new DateTime[] { possibleFileInfo.LastWriteTime, fileInfo.LastWriteTime }.Max());
|
||||||
|
if (possibleFileInfo.LastWriteTime == fileInfo.LastWriteTime && possibleFileInfo.Length == fileInfo.Length)
|
||||||
|
continue;
|
||||||
|
if (!result)
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static int MaybeMove(Properties.IPropertyConfiguration propertyConfiguration, List<FilePair> filePairs, string jsonGroupDirectory, string extension)
|
private static string? GetMatch(string file, List<string> collection)
|
||||||
{
|
{
|
||||||
FileInfo? toFileInfo;
|
string? result = null;
|
||||||
FileInfo fromFileInfo;
|
FileInfo possibleFileInfo;
|
||||||
string checkDirectory;
|
List<long> lengths = [];
|
||||||
List<(string, string)> rename = [];
|
List<string> matches = [];
|
||||||
foreach (FilePair filePair in filePairs)
|
FileInfo fileInfo = new(file);
|
||||||
|
List<DateTime> creationTimes = [];
|
||||||
|
foreach (string possible in collection)
|
||||||
{
|
{
|
||||||
if (filePair.IsUnique)
|
possibleFileInfo = new(possible);
|
||||||
|
lengths.Add(possibleFileInfo.Length);
|
||||||
|
creationTimes.Add(possibleFileInfo.CreationTime);
|
||||||
|
if (possibleFileInfo.CreationTime != fileInfo.LastWriteTime)
|
||||||
continue;
|
continue;
|
||||||
IsNotUniqueLoop(propertyConfiguration, jsonGroupDirectory, extension, filePair, rename);
|
matches.Add(possible);
|
||||||
}
|
}
|
||||||
foreach ((string from, string to) in rename)
|
if (matches.Count == 1 || (matches.Count > 0 && lengths.Distinct().Count() == 1 && creationTimes.Distinct().Count() == 1))
|
||||||
{
|
result = matches.First();
|
||||||
toFileInfo = null;
|
return result;
|
||||||
checkDirectory = to;
|
|
||||||
fromFileInfo = new(from);
|
|
||||||
if (!fromFileInfo.Exists)
|
|
||||||
continue;
|
|
||||||
for (int i = 0; i < int.MaxValue; i++)
|
|
||||||
{
|
|
||||||
toFileInfo = new(checkDirectory);
|
|
||||||
if (toFileInfo.Directory is null)
|
|
||||||
continue;
|
|
||||||
if (!toFileInfo.Directory.Exists)
|
|
||||||
_ = Directory.CreateDirectory(toFileInfo.Directory.FullName);
|
|
||||||
if (checkDirectory.Length > 199)
|
|
||||||
throw new Exception();
|
|
||||||
if (!toFileInfo.Exists)
|
|
||||||
break;
|
|
||||||
else if (fromFileInfo.Length == toFileInfo.Length && fromFileInfo.LastWriteTime == toFileInfo.LastWriteTime)
|
|
||||||
checkDirectory = string.Concat(checkDirectory, ".del");
|
|
||||||
else
|
|
||||||
checkDirectory = string.Concat(checkDirectory, ".j");
|
|
||||||
}
|
|
||||||
File.Move(from, checkDirectory);
|
|
||||||
}
|
|
||||||
return rename.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void MoveFiles(List<string> files, string find, string replace)
|
|
||||||
{
|
|
||||||
string checkFile;
|
|
||||||
string? checkDirectory;
|
|
||||||
List<string> directories = [];
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
checkDirectory = Path.GetDirectoryName(file.Replace(find, replace));
|
|
||||||
if (string.IsNullOrEmpty(checkDirectory) || directories.Contains(checkDirectory))
|
|
||||||
continue;
|
|
||||||
directories.Add(checkDirectory);
|
|
||||||
}
|
|
||||||
foreach (string directory in directories)
|
|
||||||
{
|
|
||||||
if (Directory.Exists(directory))
|
|
||||||
continue;
|
|
||||||
_ = Directory.CreateDirectory(directory);
|
|
||||||
}
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
if (!File.Exists(file))
|
|
||||||
continue;
|
|
||||||
checkFile = file.Replace(find, replace);
|
|
||||||
if (File.Exists(checkFile))
|
|
||||||
{
|
|
||||||
File.Delete(checkFile);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
File.Move(file, checkFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FilePath[] GetSortedRecords(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
|
|
||||||
{
|
|
||||||
List<FilePath> results = [];
|
|
||||||
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
|
|
||||||
{
|
|
||||||
foreach (FilePath filePath in filePaths)
|
|
||||||
results.Add(filePath);
|
|
||||||
}
|
|
||||||
return (from l in results orderby l.CreationTicks, l.FullName.Length descending select l).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static ReadOnlyCollection<ReadOnlyCollection<FilePath>> GetFilePathCollections(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection)
|
|
||||||
{
|
|
||||||
List<ReadOnlyCollection<FilePath>> results = [];
|
|
||||||
FilePath filePath;
|
|
||||||
List<FilePath> filePaths;
|
|
||||||
Models.FileHolder fileHolder;
|
|
||||||
foreach (string[] files in filesCollection)
|
|
||||||
{
|
|
||||||
filePaths = [];
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
fileHolder = IFileHolder.Get(file);
|
|
||||||
if (propertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
|
|
||||||
continue;
|
|
||||||
filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null);
|
|
||||||
filePaths.Add(filePath);
|
|
||||||
}
|
|
||||||
results.Add(new(filePaths));
|
|
||||||
}
|
|
||||||
return results.AsReadOnly();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick)
|
internal static (string[], List<(FilePath, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, IReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> fileGroups, Action? tick)
|
||||||
{
|
{
|
||||||
List<(FilePath, string)> results = [];
|
List<(FilePath, string)> results = [];
|
||||||
string key;
|
|
||||||
string paddedId;
|
string paddedId;
|
||||||
string checkFile;
|
string checkFile;
|
||||||
string directory;
|
string directory;
|
||||||
@ -305,6 +323,8 @@ internal abstract partial class XDirectory
|
|||||||
List<string> distinctDirectories = [];
|
List<string> distinctDirectories = [];
|
||||||
FilePath[] sortedRecords = GetSortedRecords(filePathsCollection);
|
FilePath[] sortedRecords = GetSortedRecords(filePathsCollection);
|
||||||
ReadOnlyDictionary<byte, ReadOnlyCollection<string>>? keyValuePairs;
|
ReadOnlyDictionary<byte, ReadOnlyCollection<string>>? keyValuePairs;
|
||||||
|
if (!fileGroups.TryGetValue(propertyConfiguration.ResultContent, out keyValuePairs))
|
||||||
|
throw new NotImplementedException();
|
||||||
bool isOffsetDeterministicHashCode = IId.IsOffsetDeterministicHashCode(propertyConfiguration);
|
bool isOffsetDeterministicHashCode = IId.IsOffsetDeterministicHashCode(propertyConfiguration);
|
||||||
for (int i = 0; i < sortedRecords.Length; i++)
|
for (int i = 0; i < sortedRecords.Length; i++)
|
||||||
{
|
{
|
||||||
@ -312,11 +332,8 @@ internal abstract partial class XDirectory
|
|||||||
filePath = sortedRecords[i];
|
filePath = sortedRecords[i];
|
||||||
if (filePath.Name.EndsWith("len") || filePath.ExtensionLowered == ".id" || filePath.ExtensionLowered == ".lsv" || filePath.DirectoryFullPath is null)
|
if (filePath.Name.EndsWith("len") || filePath.ExtensionLowered == ".id" || filePath.ExtensionLowered == ".lsv" || filePath.DirectoryFullPath is null)
|
||||||
continue;
|
continue;
|
||||||
key = propertyConfiguration.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered) ? propertyConfiguration.ResultContentCollection : propertyConfiguration.ResultContent;
|
|
||||||
if (!fileGroups.TryGetValue(key, out keyValuePairs))
|
|
||||||
continue;
|
|
||||||
cei = IPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
|
|
||||||
fileDirectoryName = Path.GetFileName(filePath.DirectoryFullPath);
|
fileDirectoryName = Path.GetFileName(filePath.DirectoryFullPath);
|
||||||
|
cei = IPath.GetCombinedEnumAndIndex(propertyConfiguration, filePath);
|
||||||
if (fileDirectoryName.Length < propertyConfiguration.ResultAllInOneSubdirectoryLength + 3 || !filePath.Name.StartsWith(fileDirectoryName))
|
if (fileDirectoryName.Length < propertyConfiguration.ResultAllInOneSubdirectoryLength + 3 || !filePath.Name.StartsWith(fileDirectoryName))
|
||||||
{
|
{
|
||||||
if (wrapped)
|
if (wrapped)
|
||||||
@ -409,34 +426,15 @@ internal abstract partial class XDirectory
|
|||||||
return (distinctDirectories.ToArray(), results);
|
return (distinctDirectories.ToArray(), results);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<string> CopyOrMove(List<(FilePath, string)> toDoCollection, bool move, bool moveBack, Action? tick)
|
private static FilePath[] GetSortedRecords(ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection)
|
||||||
{
|
{
|
||||||
List<string> results = [];
|
List<FilePath> results = [];
|
||||||
FileInfo fileInfo;
|
foreach (ReadOnlyCollection<FilePath> filePaths in filePathsCollection)
|
||||||
List<string> distinctExtensions = [];
|
|
||||||
foreach ((FilePath filePath, string to) in toDoCollection)
|
|
||||||
{
|
{
|
||||||
tick?.Invoke();
|
foreach (FilePath filePath in filePaths)
|
||||||
fileInfo = new(to);
|
results.Add(filePath);
|
||||||
if (fileInfo.Exists)
|
|
||||||
{
|
|
||||||
if (filePath.Length == fileInfo.Length && filePath.LastWriteTicks == fileInfo.LastWriteTime.Ticks)
|
|
||||||
continue;
|
|
||||||
fileInfo.Delete();
|
|
||||||
}
|
|
||||||
results.Add(filePath.NameWithoutExtension);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!distinctExtensions.Contains(filePath.ExtensionLowered))
|
|
||||||
distinctExtensions.Add(filePath.ExtensionLowered);
|
|
||||||
if (move || moveBack)
|
|
||||||
File.Move(filePath.FullName, to);
|
|
||||||
else
|
|
||||||
File.Copy(filePath.FullName, to);
|
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
}
|
}
|
||||||
return results;
|
return (from l in results orderby l.CreationTicks, l.FullName.Length descending select l).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -6,35 +6,21 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
|||||||
internal abstract class XPath
|
internal abstract class XPath
|
||||||
{
|
{
|
||||||
|
|
||||||
internal static string GetRelativePath(string path, int length, bool forceExtensionToLower)
|
private static ReadOnlyDictionary<byte, ReadOnlyCollection<string>> Convert(List<CombinedEnumAndIndex> collection)
|
||||||
{
|
{
|
||||||
string result;
|
Dictionary<byte, List<string>> results = [];
|
||||||
if (forceExtensionToLower)
|
List<string>? c;
|
||||||
|
foreach (CombinedEnumAndIndex cei in collection)
|
||||||
{
|
{
|
||||||
string extension = Path.GetExtension(path);
|
if (!results.TryGetValue(cei.Enum, out c))
|
||||||
string extensionLowered = Path.GetExtension(path).ToLower();
|
|
||||||
if (extension != extensionLowered)
|
|
||||||
{
|
{
|
||||||
string? directoryName = Path.GetDirectoryName(path);
|
results.Add(cei.Enum, []);
|
||||||
if (string.IsNullOrEmpty(directoryName))
|
if (!results.TryGetValue(cei.Enum, out c))
|
||||||
throw new NullReferenceException(directoryName);
|
throw new Exception();
|
||||||
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
|
|
||||||
if (string.IsNullOrEmpty(fileNameWithoutExtension))
|
|
||||||
throw new NullReferenceException(fileNameWithoutExtension);
|
|
||||||
path = Path.Combine(directoryName, $"{fileNameWithoutExtension}{extensionLowered}");
|
|
||||||
}
|
}
|
||||||
|
c.Add(cei.Combined);
|
||||||
}
|
}
|
||||||
result = path[length..].Replace(@"\", "/");
|
return Convert(results);
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static bool DeleteEmptyDirectories(string rootDirectory)
|
|
||||||
{
|
|
||||||
bool result;
|
|
||||||
List<string> results = [];
|
|
||||||
DeleteEmptyDirectories(rootDirectory, results);
|
|
||||||
result = results.Count > 0;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void DeleteEmptyDirectories(string rootDirectory, List<string> deletedDirectories)
|
internal static void DeleteEmptyDirectories(string rootDirectory, List<string> deletedDirectories)
|
||||||
@ -72,45 +58,79 @@ internal abstract class XPath
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool WriteAllText(string path, string contents, bool updateDateWhenMatches, bool compareBeforeWrite, DateTime? updateToWhenMatches)
|
internal static CombinedEnumAndIndex GetCombinedEnumAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath, string fileNameFirstSegment)
|
||||||
{
|
{
|
||||||
bool result;
|
CombinedEnumAndIndex result;
|
||||||
string text;
|
int converted;
|
||||||
if (!compareBeforeWrite)
|
string combined;
|
||||||
result = true;
|
byte @enum = GetEnum(filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal);
|
||||||
|
string check = fileNameFirstSegment.Length < propertyConfiguration.ResultAllInOneSubdirectoryLength ?
|
||||||
|
new('-', propertyConfiguration.ResultAllInOneSubdirectoryLength) :
|
||||||
|
fileNameFirstSegment.Split('.')[0][^propertyConfiguration.ResultAllInOneSubdirectoryLength..];
|
||||||
|
if (check.Any(l => !char.IsNumber(l)))
|
||||||
|
{
|
||||||
|
combined = $"{@enum}{new('-', propertyConfiguration.ResultAllInOneSubdirectoryLength)}";
|
||||||
|
converted = int.Parse($"1{new string('0', propertyConfiguration.ResultAllInOneSubdirectoryLength)}");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!File.Exists(path))
|
combined = $"{@enum}{check}";
|
||||||
text = string.Empty;
|
converted = int.Parse(check);
|
||||||
else
|
|
||||||
text = File.ReadAllText(path);
|
|
||||||
result = text != contents;
|
|
||||||
if (!result && updateDateWhenMatches)
|
|
||||||
{
|
|
||||||
if (updateToWhenMatches is null)
|
|
||||||
File.SetLastWriteTime(path, DateTime.Now);
|
|
||||||
else
|
|
||||||
File.SetLastWriteTime(path, updateToWhenMatches.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
if (path.Contains("()"))
|
|
||||||
File.WriteAllText(path, contents);
|
|
||||||
else if (path.Contains("{}") && !path.EndsWith(".json"))
|
|
||||||
File.WriteAllText(path, contents);
|
|
||||||
else if (path.Contains("[]") && !path.EndsWith(".json"))
|
|
||||||
File.WriteAllText(path, contents);
|
|
||||||
else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
|
|
||||||
File.WriteAllText(path, contents);
|
|
||||||
else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
|
|
||||||
File.WriteAllText(path, contents);
|
|
||||||
else
|
|
||||||
File.WriteAllText(path, contents);
|
|
||||||
}
|
}
|
||||||
|
result = new(combined, @enum, converted);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static byte GetEnum(bool? ik, bool? dto)
|
||||||
|
{
|
||||||
|
byte result;
|
||||||
|
if (ik is not null && ik.Value && dto is not null && dto.Value)
|
||||||
|
result = 11;
|
||||||
|
else if (ik is not null && ik.Value && dto is not null && !dto.Value)
|
||||||
|
result = 15;
|
||||||
|
else if (ik is not null && ik.Value && dto is null)
|
||||||
|
result = 19;
|
||||||
|
else if (ik is not null && !ik.Value && dto is not null && dto.Value)
|
||||||
|
result = 51;
|
||||||
|
else if (ik is not null && !ik.Value && dto is not null && !dto.Value)
|
||||||
|
result = 55;
|
||||||
|
else if (ik is not null && !ik.Value && dto is null)
|
||||||
|
result = 59;
|
||||||
|
else if (ik is null && dto is not null && dto.Value)
|
||||||
|
result = 91;
|
||||||
|
else if (ik is null && dto is not null && !dto.Value)
|
||||||
|
result = 95;
|
||||||
|
else if (ik is null && dto is null)
|
||||||
|
result = 99;
|
||||||
|
else
|
||||||
|
throw new Exception();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static byte GetEnum(FilePath filePath) =>
|
||||||
|
GetEnum(filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal);
|
||||||
|
|
||||||
|
internal static List<string> GetDirectories(string directory)
|
||||||
|
{
|
||||||
|
List<string> results = [];
|
||||||
|
string? checkDirectory = directory;
|
||||||
|
string? pathRoot = Path.GetPathRoot(directory);
|
||||||
|
if (string.IsNullOrEmpty(pathRoot))
|
||||||
|
throw new NullReferenceException(nameof(pathRoot));
|
||||||
|
if (Directory.Exists(directory))
|
||||||
|
results.Add(directory);
|
||||||
|
for (int i = 0; i < int.MaxValue; i++)
|
||||||
|
{
|
||||||
|
checkDirectory = Path.GetDirectoryName(checkDirectory);
|
||||||
|
if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == pathRoot)
|
||||||
|
break;
|
||||||
|
results.Add(checkDirectory);
|
||||||
|
}
|
||||||
|
results.Add(pathRoot);
|
||||||
|
results.Reverse();
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
internal static List<string> GetDirectoryNames(string directory)
|
internal static List<string> GetDirectoryNames(string directory)
|
||||||
{
|
{
|
||||||
List<string> results = [];
|
List<string> results = [];
|
||||||
@ -147,83 +167,15 @@ internal abstract class XPath
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<string> GetDirectories(string directory)
|
internal static bool DeleteEmptyDirectories(string rootDirectory)
|
||||||
{
|
{
|
||||||
|
bool result;
|
||||||
List<string> results = [];
|
List<string> results = [];
|
||||||
string? checkDirectory = directory;
|
DeleteEmptyDirectories(rootDirectory, results);
|
||||||
string? pathRoot = Path.GetPathRoot(directory);
|
result = results.Count > 0;
|
||||||
if (string.IsNullOrEmpty(pathRoot))
|
|
||||||
throw new NullReferenceException(nameof(pathRoot));
|
|
||||||
if (Directory.Exists(directory))
|
|
||||||
results.Add(directory);
|
|
||||||
for (int i = 0; i < int.MaxValue; i++)
|
|
||||||
{
|
|
||||||
checkDirectory = Path.GetDirectoryName(checkDirectory);
|
|
||||||
if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == pathRoot)
|
|
||||||
break;
|
|
||||||
results.Add(checkDirectory);
|
|
||||||
}
|
|
||||||
results.Add(pathRoot);
|
|
||||||
results.Reverse();
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static (int level, List<string> directories) Get(string rootDirectory, string sourceDirectory)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
string? directory;
|
|
||||||
string? checkDirectory;
|
|
||||||
List<string> results = [];
|
|
||||||
checkDirectory = sourceDirectory;
|
|
||||||
for (int i = 0; i < int.MaxValue; i++)
|
|
||||||
{
|
|
||||||
result += 1;
|
|
||||||
directory = Path.GetFileName(checkDirectory);
|
|
||||||
if (string.IsNullOrEmpty(directory))
|
|
||||||
break;
|
|
||||||
results.Add(directory);
|
|
||||||
checkDirectory = Path.GetDirectoryName(checkDirectory);
|
|
||||||
if (checkDirectory == rootDirectory)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
results.Reverse();
|
|
||||||
return new(result, results);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string GetDirectory(string sourceDirectory, int level, string directoryName)
|
|
||||||
{
|
|
||||||
string result;
|
|
||||||
string? checkDirectory;
|
|
||||||
checkDirectory = Path.GetDirectoryName(sourceDirectory);
|
|
||||||
for (int i = 0; i < level; i++)
|
|
||||||
checkDirectory = Path.GetDirectoryName(checkDirectory);
|
|
||||||
if (string.IsNullOrEmpty(checkDirectory))
|
|
||||||
throw new Exception();
|
|
||||||
checkDirectory = Path.Combine(checkDirectory, directoryName);
|
|
||||||
if (!Directory.Exists(checkDirectory))
|
|
||||||
_ = Directory.CreateDirectory(checkDirectory);
|
|
||||||
result = checkDirectory;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ChangeDateForEmptyDirectories(string rootDirectory, long ticks)
|
|
||||||
{
|
|
||||||
DateTime dateTime = new(ticks);
|
|
||||||
IEnumerable<string> fileSystemEntries;
|
|
||||||
string[] directories;
|
|
||||||
if (!Directory.Exists(rootDirectory))
|
|
||||||
directories = [];
|
|
||||||
else
|
|
||||||
directories = Directory.GetDirectories(rootDirectory, "*", SearchOption.AllDirectories);
|
|
||||||
foreach (string directory in directories)
|
|
||||||
{
|
|
||||||
fileSystemEntries = Directory.EnumerateFileSystemEntries(directory, "*", SearchOption.TopDirectoryOnly);
|
|
||||||
if (fileSystemEntries.Any())
|
|
||||||
continue;
|
|
||||||
Directory.SetLastWriteTime(directory, dateTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void MakeHiddenIfAllItemsAreHidden(string rootDirectory)
|
internal static void MakeHiddenIfAllItemsAreHidden(string rootDirectory)
|
||||||
{
|
{
|
||||||
bool check;
|
bool check;
|
||||||
@ -266,104 +218,131 @@ internal abstract class XPath
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte GetEnum(bool? ik, bool? dto)
|
internal static void ChangeDateForEmptyDirectories(string rootDirectory, long ticks)
|
||||||
{
|
{
|
||||||
byte result;
|
DateTime dateTime = new(ticks);
|
||||||
if (ik is not null && ik.Value && dto is not null && dto.Value)
|
IEnumerable<string> fileSystemEntries;
|
||||||
result = 11;
|
string[] directories;
|
||||||
else if (ik is not null && ik.Value && dto is not null && !dto.Value)
|
if (!Directory.Exists(rootDirectory))
|
||||||
result = 15;
|
directories = [];
|
||||||
else if (ik is not null && ik.Value && dto is null)
|
|
||||||
result = 19;
|
|
||||||
else if (ik is not null && !ik.Value && dto is not null && dto.Value)
|
|
||||||
result = 51;
|
|
||||||
else if (ik is not null && !ik.Value && dto is not null && !dto.Value)
|
|
||||||
result = 55;
|
|
||||||
else if (ik is not null && !ik.Value && dto is null)
|
|
||||||
result = 59;
|
|
||||||
else if (ik is null && dto is not null && dto.Value)
|
|
||||||
result = 91;
|
|
||||||
else if (ik is null && dto is not null && !dto.Value)
|
|
||||||
result = 95;
|
|
||||||
else if (ik is null && dto is null)
|
|
||||||
result = 99;
|
|
||||||
else
|
else
|
||||||
throw new Exception();
|
directories = Directory.GetDirectories(rootDirectory, "*", SearchOption.AllDirectories);
|
||||||
|
foreach (string directory in directories)
|
||||||
|
{
|
||||||
|
fileSystemEntries = Directory.EnumerateFileSystemEntries(directory, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
if (fileSystemEntries.Any())
|
||||||
|
continue;
|
||||||
|
Directory.SetLastWriteTime(directory, dateTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetRelativePath(string path, int length, bool forceExtensionToLower)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
if (forceExtensionToLower)
|
||||||
|
{
|
||||||
|
string extension = Path.GetExtension(path);
|
||||||
|
string extensionLowered = Path.GetExtension(path).ToLower();
|
||||||
|
if (extension != extensionLowered)
|
||||||
|
{
|
||||||
|
string? directoryName = Path.GetDirectoryName(path);
|
||||||
|
if (string.IsNullOrEmpty(directoryName))
|
||||||
|
throw new NullReferenceException(directoryName);
|
||||||
|
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
|
||||||
|
if (string.IsNullOrEmpty(fileNameWithoutExtension))
|
||||||
|
throw new NullReferenceException(fileNameWithoutExtension);
|
||||||
|
path = Path.Combine(directoryName, $"{fileNameWithoutExtension}{extensionLowered}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = path[length..].Replace(@"\", "/");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static byte GetEnum(FilePath filePath) =>
|
internal static string GetDirectory(string sourceDirectory, int level, string directoryName)
|
||||||
GetEnum(filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal);
|
|
||||||
|
|
||||||
internal static CombinedEnumAndIndex GetCombinedEnumAndIndex(int resultAllInOneSubdirectoryLength, FilePath filePath, string fileName)
|
|
||||||
{
|
{
|
||||||
CombinedEnumAndIndex result;
|
string result;
|
||||||
int converted;
|
string? checkDirectory;
|
||||||
string combined;
|
checkDirectory = Path.GetDirectoryName(sourceDirectory);
|
||||||
byte @enum = GetEnum(filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal);
|
for (int i = 0; i < level; i++)
|
||||||
string check = fileName.Length < resultAllInOneSubdirectoryLength ?
|
checkDirectory = Path.GetDirectoryName(checkDirectory);
|
||||||
new('-', resultAllInOneSubdirectoryLength) :
|
if (string.IsNullOrEmpty(checkDirectory))
|
||||||
fileName.Split('.')[0][^resultAllInOneSubdirectoryLength..];
|
throw new Exception();
|
||||||
if (check.Any(l => !char.IsNumber(l)))
|
checkDirectory = Path.Combine(checkDirectory, directoryName);
|
||||||
{
|
if (!Directory.Exists(checkDirectory))
|
||||||
combined = $"{@enum}{new('-', resultAllInOneSubdirectoryLength)}";
|
_ = Directory.CreateDirectory(checkDirectory);
|
||||||
converted = int.Parse($"1{new string('0', resultAllInOneSubdirectoryLength)}");
|
result = checkDirectory;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
combined = $"{@enum}{check}";
|
|
||||||
converted = int.Parse(check);
|
|
||||||
}
|
|
||||||
result = new(combined, @enum, converted);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static (int level, List<string> directories) Get(string rootDirectory, string sourceDirectory)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
string? directory;
|
||||||
|
string? checkDirectory;
|
||||||
|
List<string> results = [];
|
||||||
|
checkDirectory = sourceDirectory;
|
||||||
|
for (int i = 0; i < int.MaxValue; i++)
|
||||||
|
{
|
||||||
|
result += 1;
|
||||||
|
directory = Path.GetFileName(checkDirectory);
|
||||||
|
if (string.IsNullOrEmpty(directory))
|
||||||
|
break;
|
||||||
|
results.Add(directory);
|
||||||
|
checkDirectory = Path.GetDirectoryName(checkDirectory);
|
||||||
|
if (checkDirectory == rootDirectory)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
results.Reverse();
|
||||||
|
return new(result, results);
|
||||||
|
}
|
||||||
|
|
||||||
internal static CombinedEnumAndIndex GetCombinedEnumAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath)
|
internal static CombinedEnumAndIndex GetCombinedEnumAndIndex(IPropertyConfiguration propertyConfiguration, FilePath filePath)
|
||||||
{
|
{
|
||||||
CombinedEnumAndIndex result;
|
CombinedEnumAndIndex result;
|
||||||
if (filePath.Id is not null)
|
if (filePath.Id is not null)
|
||||||
result = GetCombinedEnumAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, filePath, filePath.Id.Value.ToString());
|
result = GetCombinedEnumAndIndex(propertyConfiguration, filePath, filePath.Id.Value.ToString());
|
||||||
else
|
else
|
||||||
result = GetCombinedEnumAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, filePath, filePath.FileNameFirstSegment);
|
result = GetCombinedEnumAndIndex(propertyConfiguration, filePath, filePath.FileNameFirstSegment);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] GetBytes() =>
|
internal static bool WriteAllText(string path, string contents, bool updateDateWhenMatches, bool compareBeforeWrite, DateTime? updateToWhenMatches)
|
||||||
[
|
|
||||||
11,
|
|
||||||
15,
|
|
||||||
19,
|
|
||||||
51,
|
|
||||||
55,
|
|
||||||
59,
|
|
||||||
91,
|
|
||||||
95,
|
|
||||||
99
|
|
||||||
];
|
|
||||||
|
|
||||||
private static ReadOnlyDictionary<byte, ReadOnlyCollection<string>> Convert(Dictionary<byte, List<string>> keyValuePairs)
|
|
||||||
{
|
{
|
||||||
Dictionary<byte, ReadOnlyCollection<string>> results = [];
|
bool result;
|
||||||
foreach (KeyValuePair<byte, List<string>> keyValuePair in keyValuePairs)
|
string text;
|
||||||
results.Add(keyValuePair.Key, new(keyValuePair.Value));
|
if (!compareBeforeWrite)
|
||||||
return results.AsReadOnly();
|
result = true;
|
||||||
}
|
else
|
||||||
|
|
||||||
private static ReadOnlyDictionary<byte, ReadOnlyCollection<string>> Convert(List<CombinedEnumAndIndex> collection)
|
|
||||||
{
|
|
||||||
Dictionary<byte, List<string>> results = [];
|
|
||||||
List<string>? c;
|
|
||||||
foreach (CombinedEnumAndIndex cei in collection)
|
|
||||||
{
|
{
|
||||||
if (!results.TryGetValue(cei.Enum, out c))
|
if (!File.Exists(path))
|
||||||
|
text = string.Empty;
|
||||||
|
else
|
||||||
|
text = File.ReadAllText(path);
|
||||||
|
result = text != contents;
|
||||||
|
if (!result && updateDateWhenMatches)
|
||||||
{
|
{
|
||||||
results.Add(cei.Enum, []);
|
if (updateToWhenMatches is null)
|
||||||
if (!results.TryGetValue(cei.Enum, out c))
|
File.SetLastWriteTime(path, DateTime.Now);
|
||||||
throw new Exception();
|
else
|
||||||
|
File.SetLastWriteTime(path, updateToWhenMatches.Value);
|
||||||
}
|
}
|
||||||
c.Add(cei.Combined);
|
|
||||||
}
|
}
|
||||||
return Convert(results);
|
if (result)
|
||||||
|
{
|
||||||
|
if (path.Contains("()"))
|
||||||
|
File.WriteAllText(path, contents);
|
||||||
|
else if (path.Contains("{}") && !path.EndsWith(".json"))
|
||||||
|
File.WriteAllText(path, contents);
|
||||||
|
else if (path.Contains("[]") && !path.EndsWith(".json"))
|
||||||
|
File.WriteAllText(path, contents);
|
||||||
|
else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
|
||||||
|
File.WriteAllText(path, contents);
|
||||||
|
else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
|
||||||
|
File.WriteAllText(path, contents);
|
||||||
|
else
|
||||||
|
File.WriteAllText(path, contents);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups)
|
internal static ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> GetKeyValuePairs(IPropertyConfiguration propertyConfiguration, string? resultsFullGroupDirectory, string[]? jsonGroups)
|
||||||
@ -420,4 +399,25 @@ internal abstract class XPath
|
|||||||
return results.AsReadOnly();
|
return results.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static byte[] GetBytes() =>
|
||||||
|
[
|
||||||
|
11,
|
||||||
|
15,
|
||||||
|
19,
|
||||||
|
51,
|
||||||
|
55,
|
||||||
|
59,
|
||||||
|
91,
|
||||||
|
95,
|
||||||
|
99
|
||||||
|
];
|
||||||
|
|
||||||
|
private static ReadOnlyDictionary<byte, ReadOnlyCollection<string>> Convert(Dictionary<byte, List<string>> keyValuePairs)
|
||||||
|
{
|
||||||
|
Dictionary<byte, ReadOnlyCollection<string>> results = [];
|
||||||
|
foreach (KeyValuePair<byte, List<string>> keyValuePair in keyValuePairs)
|
||||||
|
results.Add(keyValuePair.Key, new(keyValuePair.Value));
|
||||||
|
return results.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user