IDirectory first pass
This commit is contained in:
@ -1,33 +1,10 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace View_by_Distance.Shared.Models;
|
||||
|
||||
public class Container : Properties.IContainer
|
||||
public record Container(string SourceDirectory, List<Item> Items)
|
||||
{
|
||||
|
||||
protected readonly int _G;
|
||||
protected readonly List<Item> _Items;
|
||||
protected readonly string _SourceDirectory;
|
||||
public int G => _G;
|
||||
public List<Item> Items => _Items;
|
||||
public string SourceDirectory => _SourceDirectory;
|
||||
|
||||
[JsonConstructor]
|
||||
public Container(int g, List<Item> items, string sourceDirectory)
|
||||
{
|
||||
_G = g;
|
||||
_Items = items;
|
||||
_SourceDirectory = sourceDirectory;
|
||||
}
|
||||
|
||||
public Container(int g, string sourceDirectory)
|
||||
{
|
||||
_G = g;
|
||||
_Items = new();
|
||||
_SourceDirectory = sourceDirectory;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
|
||||
|
3
Shared/Models/FilePair.cs
Normal file
3
Shared/Models/FilePair.cs
Normal file
@ -0,0 +1,3 @@
|
||||
namespace View_by_Distance.Shared.Models;
|
||||
|
||||
public record FilePair(string Path, bool IsUnique, List<string> Collection, string? Match) { }
|
@ -6,50 +6,47 @@ namespace View_by_Distance.Shared.Models;
|
||||
public class Item : Properties.IItem
|
||||
{
|
||||
|
||||
protected readonly bool? _Abandoned;
|
||||
protected List<Face> _Faces;
|
||||
protected readonly bool? _FileSizeChanged;
|
||||
protected readonly FileHolder _ImageFileHolder;
|
||||
protected bool? _IsUniqueFileName;
|
||||
protected bool _IsValidImageFormatExtension;
|
||||
protected bool? _LastWriteTimeChanged;
|
||||
protected bool? _Moved;
|
||||
protected readonly bool? _NoJson;
|
||||
protected Property? _Property;
|
||||
protected readonly string _RelativePath;
|
||||
protected FileHolder? _ResizedFileHolder;
|
||||
protected readonly FileHolder _SourceDirectoryFileHolder;
|
||||
protected bool _ValidImageFormatExtension;
|
||||
public bool? Abandoned => _Abandoned;
|
||||
public List<Face> Faces => _Faces;
|
||||
public bool? FileSizeChanged => _FileSizeChanged;
|
||||
public FileHolder ImageFileHolder => _ImageFileHolder;
|
||||
public bool? IsUniqueFileName => _IsUniqueFileName;
|
||||
public bool IsValidImageFormatExtension => _IsValidImageFormatExtension;
|
||||
public bool? LastWriteTimeChanged => _LastWriteTimeChanged;
|
||||
public bool? Moved => _Moved;
|
||||
public bool? NoJson => _NoJson;
|
||||
public Property? Property => _Property;
|
||||
public string RelativePath => _RelativePath;
|
||||
public FileHolder? ResizedFileHolder => _ResizedFileHolder;
|
||||
public FileHolder SourceDirectoryFileHolder => _SourceDirectoryFileHolder;
|
||||
public bool ValidImageFormatExtension => _ValidImageFormatExtension;
|
||||
|
||||
[JsonConstructor]
|
||||
public Item(bool? abandoned, List<Face> faces, bool? fileSizeChanged, FileHolder imageFileHolder, bool? lastWriteTimeChanged, bool? moved, bool? noJson, Property? property, string relativePath, FileHolder? resizedFileHolder, FileHolder sourceDirectoryFileHolder, bool validImageFormatExtension)
|
||||
public Item(List<Face> faces, bool? fileSizeChanged, FileHolder imageFileHolder, bool? isUniqueFileName, bool isValidImageFormatExtension, bool? lastWriteTimeChanged, bool? moved, Property? property, string relativePath, FileHolder? resizedFileHolder, FileHolder sourceDirectoryFileHolder)
|
||||
{
|
||||
_Faces = faces;
|
||||
_Moved = moved;
|
||||
_NoJson = noJson;
|
||||
_Property = property;
|
||||
_Abandoned = abandoned;
|
||||
_RelativePath = relativePath;
|
||||
_FileSizeChanged = fileSizeChanged;
|
||||
_ImageFileHolder = imageFileHolder;
|
||||
_IsUniqueFileName = isUniqueFileName;
|
||||
_IsValidImageFormatExtension = isValidImageFormatExtension;
|
||||
_LastWriteTimeChanged = lastWriteTimeChanged;
|
||||
_Moved = moved;
|
||||
_Property = property;
|
||||
_RelativePath = relativePath;
|
||||
_ResizedFileHolder = resizedFileHolder;
|
||||
_SourceDirectoryFileHolder = sourceDirectoryFileHolder;
|
||||
_LastWriteTimeChanged = lastWriteTimeChanged;
|
||||
_ValidImageFormatExtension = validImageFormatExtension;
|
||||
}
|
||||
|
||||
public Item(FileHolder sourceDirectoryFileHolder, string relativePath, FileHolder imageFileInfo, bool validImageFormatExtension, Property? property, bool? abandoned, bool? fileSizeChanged, bool? lastWriteTimeChanged) :
|
||||
this(abandoned, new(), fileSizeChanged, imageFileInfo, lastWriteTimeChanged, null, abandoned is null, property, relativePath, null, sourceDirectoryFileHolder, validImageFormatExtension)
|
||||
public Item(FileHolder sourceDirectoryFileHolder, string relativePath, FileHolder imageFileInfo, bool? isUniqueFileName, bool isValidImageFormatExtension, Property? property, bool? abandoned, bool? fileSizeChanged, bool? lastWriteTimeChanged) :
|
||||
this(new(), fileSizeChanged, imageFileInfo, isUniqueFileName, isValidImageFormatExtension, lastWriteTimeChanged, null, property, relativePath, null, sourceDirectoryFileHolder)
|
||||
{
|
||||
if (relativePath.EndsWith(".json"))
|
||||
throw new ArgumentException("Can not be a *.json file!");
|
||||
@ -58,7 +55,7 @@ public class Item : Properties.IItem
|
||||
}
|
||||
|
||||
public Item(FileHolder sourceDirectoryFileHolder, string relativePath, bool isValidImageFormatExtension) :
|
||||
this(sourceDirectoryFileHolder, relativePath, sourceDirectoryFileHolder, isValidImageFormatExtension, null, null, null, null)
|
||||
this(sourceDirectoryFileHolder, relativePath, sourceDirectoryFileHolder, null, isValidImageFormatExtension, null, null, null, null)
|
||||
{ }
|
||||
|
||||
public override string ToString()
|
||||
@ -79,7 +76,7 @@ public class Item : Properties.IItem
|
||||
_ResizedFileHolder = fileHolder;
|
||||
}
|
||||
|
||||
public bool Any() => (_Abandoned.HasValue && _Abandoned.Value) || (_FileSizeChanged.HasValue && _FileSizeChanged.Value) || (_LastWriteTimeChanged.HasValue && _LastWriteTimeChanged.Value) || (_Moved.HasValue && _Moved.Value) || (_NoJson.HasValue && _NoJson.Value);
|
||||
public bool Any() => !_SourceDirectoryFileHolder.Exists || (_FileSizeChanged.HasValue && _FileSizeChanged.Value) || (_LastWriteTimeChanged.HasValue && _LastWriteTimeChanged.Value) || (_Moved.HasValue && _Moved.Value);
|
||||
|
||||
public void Update(Property property) => _Property = property;
|
||||
|
||||
|
@ -1,10 +0,0 @@
|
||||
namespace View_by_Distance.Shared.Models.Properties;
|
||||
|
||||
public interface IContainer
|
||||
{
|
||||
|
||||
public int G { get; }
|
||||
public List<Item> Items { get; }
|
||||
public string SourceDirectory { get; }
|
||||
|
||||
}
|
@ -3,16 +3,15 @@ namespace View_by_Distance.Shared.Models.Properties;
|
||||
public interface IItem
|
||||
{
|
||||
|
||||
public bool? Abandoned { get; }
|
||||
public bool? FileSizeChanged { get; }
|
||||
public List<Face> Faces { get; }
|
||||
public FileHolder ImageFileHolder { get; }
|
||||
public bool? IsUniqueFileName { get; }
|
||||
public bool IsValidImageFormatExtension { get; }
|
||||
public bool? Moved { get; }
|
||||
public bool? NoJson { get; }
|
||||
public Property? Property { get; }
|
||||
public string RelativePath { get; }
|
||||
public FileHolder? ResizedFileHolder { get; }
|
||||
public FileHolder SourceDirectoryFileHolder { get; }
|
||||
public bool ValidImageFormatExtension { get; }
|
||||
|
||||
}
|
@ -5,11 +5,13 @@ public interface IPropertyConfiguration
|
||||
|
||||
public string DateGroup { init; get; }
|
||||
public string[] IgnoreExtensions { init; get; }
|
||||
public bool PropertiesChangedForProperty { init; get; }
|
||||
public string[] PropertyContentCollectionFiles { init; get; }
|
||||
public string ResultAllInOne { init; get; }
|
||||
public string ResultCollection { init; get; }
|
||||
public string ResultContent { init; get; }
|
||||
public string ResultSingleton { init; get; }
|
||||
public string[] ValidImageFormatExtensions { init; get; }
|
||||
public string[] VerifyToSeason { init; get; }
|
||||
public string? ModelName { get; }
|
||||
public int? NumberOfJitters { get; }
|
||||
|
@ -1,8 +1,12 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
||||
|
||||
internal abstract class Container
|
||||
{
|
||||
|
||||
private record FilePair(string Path, string? Directory, bool IsUnique, List<string> Collection, Models.Item Item) { }
|
||||
|
||||
internal static DateTime[] GetContainerDateTimes(Models.Item[] filteredItems)
|
||||
{
|
||||
DateTime[] results;
|
||||
@ -26,8 +30,7 @@ internal abstract class Container
|
||||
foreach (Models.Item item in container.Items)
|
||||
{
|
||||
if (item.ImageFileHolder is not null
|
||||
&& (item.Abandoned is null || !item.Abandoned.Value)
|
||||
&& item.ValidImageFormatExtension
|
||||
&& item.IsValidImageFormatExtension
|
||||
&& !propertyConfiguration.IgnoreExtensions.Contains(item.ImageFileHolder.ExtensionLowered))
|
||||
results.Add(item);
|
||||
}
|
||||
@ -55,9 +58,7 @@ internal abstract class Container
|
||||
internal static Models.Container[] SortContainers(Properties.IPropertyConfiguration propertyConfiguration, string[] ignoreRelativePaths, bool argZeroIsConfigurationRootDirectory, string argZero, Models.Container[] containers)
|
||||
{
|
||||
List<Models.Container> results = new();
|
||||
Models.Item[] filteredItems;
|
||||
bool isIgnoreRelativePath;
|
||||
List<int> collection = new();
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
foreach (Models.Container container in containers)
|
||||
@ -66,30 +67,145 @@ internal abstract class Container
|
||||
continue;
|
||||
if (!argZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
|
||||
continue;
|
||||
filteredItems = GetFilterItems(propertyConfiguration, container);
|
||||
if (!filteredItems.Any())
|
||||
continue;
|
||||
isIgnoreRelativePath = ignoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && IsIgnoreRelativePath(propertyConfiguration, ignoreRelativePaths, container.SourceDirectory);
|
||||
if (i == 1 && isIgnoreRelativePath)
|
||||
continue;
|
||||
if (i == 2 && !isIgnoreRelativePath)
|
||||
continue;
|
||||
foreach (Models.Item item in filteredItems)
|
||||
{
|
||||
if (item.Property?.Id is null)
|
||||
continue;
|
||||
if (collection.Contains(item.Property.Id.Value))
|
||||
{
|
||||
if (i == 1)
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
collection.Add(item.Property.Id.Value);
|
||||
}
|
||||
results.Add(container);
|
||||
}
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
internal static List<Models.FilePair> GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, List<string[]> filesCollection)
|
||||
{
|
||||
int renamed;
|
||||
List<Models.FilePair>? filePairs = null;
|
||||
List<string[]>? jsonFilesCollection = null;
|
||||
IReadOnlyDictionary<string, List<string>>? compareFileNamesToFiles = null;
|
||||
IReadOnlyDictionary<string, List<string>> fileNamesToFiles = IDirectory.GetFilesKeyValuePairs(filesCollection);
|
||||
for (int i = 0; i < int.MaxValue; i++)
|
||||
{
|
||||
renamed = 0;
|
||||
jsonFilesCollection = IDirectory.GetFilesCollection(aPropertySingletonDirectory, directorySearchFilter, extension);
|
||||
compareFileNamesToFiles = IDirectory.GetFilesKeyValuePairs(jsonFilesCollection);
|
||||
renamed += IDirectory.LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension);
|
||||
filePairs = IDirectory.GetFiles(filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles);
|
||||
renamed += IDirectory.MaybeMove(propertyConfiguration.RootDirectory, propertyConfiguration.ResultAllInOne, filePairs, aPropertySingletonDirectory, extension);
|
||||
if (renamed == 0)
|
||||
break;
|
||||
}
|
||||
if (filePairs is null || jsonFilesCollection is null || compareFileNamesToFiles is null)
|
||||
throw new NullReferenceException(nameof(filePairs));
|
||||
return filePairs;
|
||||
}
|
||||
|
||||
private static Models.Property? GetProperty(Models.FilePair filePair)
|
||||
{
|
||||
Models.Property? property;
|
||||
if (filePair.Match is null)
|
||||
property = null;
|
||||
else
|
||||
{
|
||||
string json = File.ReadAllText(filePair.Match);
|
||||
if (string.IsNullOrEmpty(json))
|
||||
property = null;
|
||||
else
|
||||
property = JsonSerializer.Deserialize<Models.Property>(json);
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
private static void ParallelFor(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string extension, int length, Models.FilePair filePair, List<FilePair> results)
|
||||
{
|
||||
char directory;
|
||||
string fileName;
|
||||
bool abandoned = false;
|
||||
Models.FileHolder sourceDirectoryFileHolder;
|
||||
Models.Property? property = GetProperty(filePair);
|
||||
Models.FileHolder imageFileInfo = new(filePair.Path);
|
||||
bool? fileSizeChanged = property is not null ? property.FileSize != imageFileInfo.Length : null;
|
||||
string relativePath = IPath.GetRelativePath(filePair.Path, length, forceExtensionToLower: true);
|
||||
bool isValidImageFormatExtension = propertyConfiguration.ValidImageFormatExtensions.Contains(imageFileInfo.ExtensionLowered);
|
||||
bool? lastWriteTimeChanged = property is not null ? propertyConfiguration.PropertiesChangedForProperty || property.LastWriteTime != imageFileInfo.LastWriteTime : null;
|
||||
if (filePair.Match is not null)
|
||||
sourceDirectoryFileHolder = new(filePair.Match);
|
||||
else if (!filePair.IsUnique)
|
||||
sourceDirectoryFileHolder = new(Path.GetFullPath(string.Concat(aPropertySingletonDirectory, relativePath, extension)));
|
||||
else
|
||||
{
|
||||
fileName = Path.GetFileName(filePair.Path);
|
||||
directory = IDirectory.GetDirectory(fileName);
|
||||
sourceDirectoryFileHolder = new(Path.Combine(aPropertySingletonDirectory, propertyConfiguration.ResultAllInOne, directory.ToString(), $"{fileName}{extension}"));
|
||||
}
|
||||
if (imageFileInfo.LastWriteTime is not null && sourceDirectoryFileHolder.CreationTime is not null && sourceDirectoryFileHolder.LastWriteTime is not null && imageFileInfo.LastWriteTime.Value != sourceDirectoryFileHolder.CreationTime.Value)
|
||||
{
|
||||
File.SetCreationTime(sourceDirectoryFileHolder.FullName, imageFileInfo.LastWriteTime.Value);
|
||||
File.SetLastWriteTime(sourceDirectoryFileHolder.FullName, sourceDirectoryFileHolder.LastWriteTime.Value);
|
||||
}
|
||||
Models.Item item = new(sourceDirectoryFileHolder, relativePath, imageFileInfo, filePair.IsUnique, isValidImageFormatExtension, property, abandoned, fileSizeChanged, lastWriteTimeChanged);
|
||||
lock (results)
|
||||
results.Add(new(filePair.Path, imageFileInfo.DirectoryName, filePair.IsUnique, filePair.Collection, item));
|
||||
}
|
||||
|
||||
private static List<FilePair> GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string extension, List<Models.FilePair> filePairs)
|
||||
{
|
||||
List<FilePair> results = new();
|
||||
int length = propertyConfiguration.RootDirectory.Length;
|
||||
int maxDegreeOfParallelism = Environment.ProcessorCount;
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(propertyConfiguration, aPropertySingletonDirectory, extension, length, filePairs[i], results));
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory)
|
||||
{
|
||||
List<Models.Container> results = new();
|
||||
string? directory;
|
||||
List<Models.Item>? items;
|
||||
Models.Container container;
|
||||
const string extension = ".json";
|
||||
const string fileSearchFilter = "*";
|
||||
const string directorySearchFilter = "*";
|
||||
Dictionary<string, List<Models.Item>> directoryToItems = new();
|
||||
List<string[]> filesCollection = IDirectory.GetFilesCollection(propertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter);
|
||||
foreach (string[] files in filesCollection)
|
||||
{
|
||||
if (!files.Any())
|
||||
continue;
|
||||
directory = Path.GetDirectoryName(files.First());
|
||||
if (directory is null)
|
||||
continue;
|
||||
if (!directoryToItems.TryGetValue(directory, out items))
|
||||
{
|
||||
directoryToItems.Add(directory, new());
|
||||
if (!directoryToItems.TryGetValue(directory, out items))
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
List<Models.FilePair> filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filesCollection);
|
||||
List<FilePair> collection = GetFilePairs(propertyConfiguration, aPropertySingletonDirectory, extension, filePairs);
|
||||
foreach (FilePair filePair in collection)
|
||||
{
|
||||
if (filePair.Directory is null)
|
||||
continue;
|
||||
if (!directoryToItems.TryGetValue(filePair.Directory, out items))
|
||||
{
|
||||
directoryToItems.Add(filePair.Directory, new());
|
||||
if (!directoryToItems.TryGetValue(filePair.Directory, out items))
|
||||
throw new Exception();
|
||||
}
|
||||
items.Add(filePair.Item);
|
||||
}
|
||||
foreach (KeyValuePair<string, List<Models.Item>> keyValuePair in directoryToItems)
|
||||
{
|
||||
if (!keyValuePair.Value.Any())
|
||||
continue;
|
||||
container = new(keyValuePair.Key, keyValuePair.Value);
|
||||
results.Add(container);
|
||||
}
|
||||
return (collection.Count, results.ToArray());
|
||||
}
|
||||
|
||||
}
|
@ -42,90 +42,4 @@ internal abstract class FileHolder
|
||||
}
|
||||
}
|
||||
|
||||
internal static (int t, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)>) GetGroupCollection(string rootDirectory, int maxImagesInDirectoryForTopLevelFirstPass, bool reverse, string searchPattern, List<string> topDirectories)
|
||||
{
|
||||
int result = 0;
|
||||
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> results = new();
|
||||
string? parentDirectory;
|
||||
string[] subDirectories;
|
||||
string[] sourceDirectoryFiles;
|
||||
List<string[]> fileCollections = new();
|
||||
if (!topDirectories.Any())
|
||||
{
|
||||
if (!Directory.Exists(rootDirectory))
|
||||
_ = Directory.CreateDirectory(rootDirectory);
|
||||
topDirectories.AddRange(from l in Directory.GetDirectories(rootDirectory, "*", SearchOption.TopDirectoryOnly) select Path.GetFullPath(l));
|
||||
}
|
||||
for (int g = 1; g < 5; g++)
|
||||
{
|
||||
if (g == 4)
|
||||
{
|
||||
for (int i = fileCollections.Count - 1; i > -1; i--)
|
||||
{
|
||||
parentDirectory = Path.GetDirectoryName(fileCollections[i][0]);
|
||||
if (string.IsNullOrEmpty(parentDirectory))
|
||||
continue;
|
||||
results.Add(new(g, parentDirectory, fileCollections[i]));
|
||||
fileCollections.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
else if (g == 2)
|
||||
{
|
||||
for (int i = fileCollections.Count - 1; i > -1; i--)
|
||||
{
|
||||
if (fileCollections[i].Length > maxImagesInDirectoryForTopLevelFirstPass * g)
|
||||
break;
|
||||
parentDirectory = Path.GetDirectoryName(fileCollections[i][0]);
|
||||
if (string.IsNullOrEmpty(parentDirectory))
|
||||
continue;
|
||||
results.Add(new(g, parentDirectory, fileCollections[i]));
|
||||
fileCollections.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
else if (g == 3)
|
||||
{
|
||||
subDirectories = Directory.GetDirectories(rootDirectory, "*", SearchOption.AllDirectories);
|
||||
if (reverse)
|
||||
subDirectories = subDirectories.Reverse().ToArray();
|
||||
foreach (string subDirectory in subDirectories)
|
||||
{
|
||||
sourceDirectoryFiles = Directory.GetFiles(subDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||
result += sourceDirectoryFiles.Length;
|
||||
if (!topDirectories.Contains(subDirectory))
|
||||
results.Add(new(g, subDirectory, sourceDirectoryFiles));
|
||||
}
|
||||
}
|
||||
else if (g == 1)
|
||||
{
|
||||
sourceDirectoryFiles = Directory.GetFiles(rootDirectory, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
result += sourceDirectoryFiles.Length;
|
||||
if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass)
|
||||
fileCollections.Add(sourceDirectoryFiles);
|
||||
else
|
||||
results.Add(new(g, rootDirectory, sourceDirectoryFiles));
|
||||
if (reverse)
|
||||
topDirectories.Reverse();
|
||||
subDirectories = topDirectories.ToArray();
|
||||
foreach (string subDirectory in subDirectories)
|
||||
{
|
||||
sourceDirectoryFiles = Directory.GetFiles(subDirectory, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
result += sourceDirectoryFiles.Length;
|
||||
if (sourceDirectoryFiles.Length > maxImagesInDirectoryForTopLevelFirstPass)
|
||||
fileCollections.Add(sourceDirectoryFiles);
|
||||
else
|
||||
{
|
||||
if (sourceDirectoryFiles.Any() || Directory.GetDirectories(subDirectory, "*", SearchOption.TopDirectoryOnly).Any())
|
||||
results.Add(new(g, subDirectory, sourceDirectoryFiles));
|
||||
else if (searchPattern == "*" && subDirectory != rootDirectory)
|
||||
Directory.Delete(subDirectory);
|
||||
}
|
||||
}
|
||||
fileCollections.Reverse();
|
||||
}
|
||||
else
|
||||
throw new Exception();
|
||||
}
|
||||
return new(result, results);
|
||||
}
|
||||
|
||||
}
|
@ -23,4 +23,14 @@ public interface IContainer
|
||||
static Models.Container[] SortContainers(Properties.IPropertyConfiguration propertyConfiguration, string[] ignoreRelativePaths, bool argZeroIsConfigurationRootDirectory, string argZero, Models.Container[] containers) =>
|
||||
Container.SortContainers(propertyConfiguration, ignoreRelativePaths, argZeroIsConfigurationRootDirectory, argZero, containers);
|
||||
|
||||
List<FilePair> TestStatic_GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, List<string[]> filesCollection) =>
|
||||
Container.GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filesCollection);
|
||||
static List<FilePair> GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, List<string[]> filesCollection) =>
|
||||
Container.GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filesCollection);
|
||||
|
||||
(int, Models.Container[]) TestStatic_GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
||||
GetContainers(propertyConfiguration, aPropertySingletonDirectory);
|
||||
static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
||||
Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory);
|
||||
|
||||
}
|
39
Shared/Models/Stateless/Methods/IDirectory.cs
Normal file
39
Shared/Models/Stateless/Methods/IDirectory.cs
Normal file
@ -0,0 +1,39 @@
|
||||
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
||||
|
||||
public interface IDirectory
|
||||
{
|
||||
|
||||
char TestStatic_GetDirectory(string fileName) =>
|
||||
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.Parse(directory.ToString());
|
||||
|
||||
List<string[]> TestStatic_GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter) =>
|
||||
GetFilesCollection(directory, directorySearchFilter, fileSearchFilter);
|
||||
static List<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter) =>
|
||||
XDirectory.GetFilesCollection(directory, directorySearchFilter, fileSearchFilter);
|
||||
|
||||
IReadOnlyDictionary<string, List<string>> TestStatic_GetFilesKeyValuePairs(List<string[]> filesCollection) =>
|
||||
GetFilesKeyValuePairs(filesCollection);
|
||||
static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(List<string[]> filesCollection) =>
|
||||
XDirectory.GetFilesKeyValuePairs(filesCollection);
|
||||
|
||||
int TestStatic_LookForAbandoned(List<string[]> jsonFilesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension) =>
|
||||
LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension);
|
||||
static int LookForAbandoned(List<string[]> jsonFilesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension) =>
|
||||
XDirectory.LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension);
|
||||
|
||||
int TestStatic_MaybeMove(string directory, string resultAllInOne, List<FilePair> filePairs, string jsonGroupDirectory, string extension) =>
|
||||
MaybeMove(directory, resultAllInOne, filePairs, jsonGroupDirectory, extension);
|
||||
static int MaybeMove(string directory, string resultAllInOne, List<FilePair> filePairs, string jsonGroupDirectory, string extension) =>
|
||||
XDirectory.MaybeMove(directory, resultAllInOne, filePairs, jsonGroupDirectory, extension);
|
||||
|
||||
List<FilePair> TestStatic_GetFiles(List<string[]> filesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles) =>
|
||||
GetFiles(filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles);
|
||||
static List<FilePair> GetFiles(List<string[]> filesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles) =>
|
||||
XDirectory.GetFiles(filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles);
|
||||
|
||||
}
|
@ -23,9 +23,4 @@ public interface IFileHolder
|
||||
static Models.FileHolder Refresh(Models.FileHolder fileHolder) =>
|
||||
new(fileHolder.FullName);
|
||||
|
||||
(int t, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)>) TestStatic_GetGroupCollection(string rootDirectory, int maxImagesInDirectoryForTopLevelFirstPass, bool reverse, string searchPattern, List<string> topDirectories) =>
|
||||
GetGroupCollection(rootDirectory, maxImagesInDirectoryForTopLevelFirstPass, reverse, searchPattern, topDirectories);
|
||||
static (int t, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)>) GetGroupCollection(string rootDirectory, int maxImagesInDirectoryForTopLevelFirstPass, bool reverse, string searchPattern, List<string> topDirectories) =>
|
||||
FileHolder.GetGroupCollection(rootDirectory, maxImagesInDirectoryForTopLevelFirstPass, reverse, searchPattern, topDirectories);
|
||||
|
||||
}
|
243
Shared/Models/Stateless/Methods/XDirectory.cs
Normal file
243
Shared/Models/Stateless/Methods/XDirectory.cs
Normal file
@ -0,0 +1,243 @@
|
||||
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
||||
|
||||
internal abstract partial class XDirectory
|
||||
{
|
||||
|
||||
private static int GetCeilingAverage(List<string[]> fileCollection)
|
||||
{
|
||||
List<int> counts = new();
|
||||
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 = new();
|
||||
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 List<string[]> GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter)
|
||||
{
|
||||
List<string[]> results = new();
|
||||
if (!fileSearchFilter.Contains('*'))
|
||||
fileSearchFilter = string.Concat('*', fileSearchFilter);
|
||||
if (!directorySearchFilter.Contains('*'))
|
||||
directorySearchFilter = string.Concat('*', directorySearchFilter);
|
||||
string[] directories = Directory.GetDirectories(directory, directorySearchFilter, SearchOption.TopDirectoryOnly);
|
||||
foreach (string innerDirectory in directories)
|
||||
results.Add(Directory.GetFiles(innerDirectory, fileSearchFilter, SearchOption.AllDirectories));
|
||||
int ceilingAverage = GetCeilingAverage(results);
|
||||
results = GetFilesCollection(results, ceilingAverage);
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static IReadOnlyDictionary<string, List<string>> GetFilesKeyValuePairs(List<string[]> filesCollection)
|
||||
{
|
||||
Dictionary<string, List<string>> results = new();
|
||||
string fileName;
|
||||
List<string>? collection;
|
||||
foreach (string[] files in filesCollection)
|
||||
{
|
||||
foreach (string file in files)
|
||||
{
|
||||
fileName = Path.GetFileName(file);
|
||||
if (!results.TryGetValue(fileName, out collection))
|
||||
{
|
||||
results.Add(fileName, new());
|
||||
if (!results.TryGetValue(fileName, out collection))
|
||||
throw new Exception();
|
||||
}
|
||||
collection.Add(file);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static int LookForAbandoned(List<string[]> jsonFilesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension)
|
||||
{
|
||||
string fileName;
|
||||
List<string>? collection;
|
||||
int length = extension.Length;
|
||||
List<(string, string)> rename = new();
|
||||
foreach (string[] files in jsonFilesCollection)
|
||||
{
|
||||
foreach (string file in files)
|
||||
{
|
||||
fileName = Path.GetFileName(file);
|
||||
if (fileName.Length < length || !fileName.EndsWith(extension))
|
||||
throw new Exception();
|
||||
if (!fileNamesToFiles.TryGetValue(fileName[..^length], out collection))
|
||||
rename.Add(new(file, string.Concat(file, ".del")));
|
||||
|
||||
}
|
||||
}
|
||||
foreach ((string from, string to) in rename)
|
||||
{
|
||||
if (File.Exists(to))
|
||||
continue;
|
||||
File.Move(from, to);
|
||||
}
|
||||
return rename.Count;
|
||||
}
|
||||
|
||||
private static void IsNotUniqueLoop(string file, List<string> collection)
|
||||
{
|
||||
TimeSpan timeSpan;
|
||||
FileInfo possibleFileInfo;
|
||||
FileInfo fileInfo = new(file);
|
||||
foreach (string possible in collection)
|
||||
{
|
||||
possibleFileInfo = new(possible);
|
||||
if (possibleFileInfo.LastWriteTime == fileInfo.LastWriteTime && possibleFileInfo.Length == fileInfo.Length)
|
||||
continue;
|
||||
timeSpan = new(possibleFileInfo.LastWriteTime.Ticks - fileInfo.LastWriteTime.Ticks);
|
||||
if (timeSpan.TotalMinutes < 2 && possibleFileInfo.Length == fileInfo.Length)
|
||||
{
|
||||
File.SetLastWriteTime(file, new DateTime[] { possibleFileInfo.LastWriteTime, fileInfo.LastWriteTime }.Min());
|
||||
continue;
|
||||
}
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
private static string? GetMatch(string file, List<string> collection)
|
||||
{
|
||||
string? result = null;
|
||||
FileInfo possibleFileInfo;
|
||||
List<long> lengths = new();
|
||||
List<string> matches = new();
|
||||
FileInfo fileInfo = new(file);
|
||||
List<DateTime> creationTimes = new();
|
||||
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 || (lengths.Distinct().Count() == 1 && creationTimes.Distinct().Count() == 1))
|
||||
result = matches.First();
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<FilePair> GetFiles(List<string[]> filesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles)
|
||||
{
|
||||
List<FilePair> results = new();
|
||||
string? match;
|
||||
string fileName;
|
||||
bool uniqueFileName;
|
||||
List<string>? collection;
|
||||
foreach (string[] files in filesCollection)
|
||||
{
|
||||
foreach (string file in files)
|
||||
{
|
||||
fileName = Path.GetFileName(file);
|
||||
if (!fileNamesToFiles.TryGetValue(fileName, out collection))
|
||||
throw new Exception();
|
||||
uniqueFileName = collection.Count == 1;
|
||||
if (!uniqueFileName)
|
||||
IsNotUniqueLoop(file, collection);
|
||||
if (!compareFileNamesToFiles.TryGetValue(string.Concat(fileName, extension), out collection))
|
||||
results.Add(new(file, uniqueFileName, new(), null));
|
||||
else
|
||||
{
|
||||
if (!collection.Any())
|
||||
results.Add(new(file, uniqueFileName, collection, null));
|
||||
else if (uniqueFileName && collection.Count == 1)
|
||||
results.Add(new(file, uniqueFileName, collection, collection.First()));
|
||||
else
|
||||
{
|
||||
match = GetMatch(file, collection);
|
||||
results.Add(new(file, uniqueFileName, collection, match));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void IsUniqueLoop(string resultAllInOne, string resultAllInOneDirectory, FilePair item, List<(string, string)> rename)
|
||||
{
|
||||
char directory;
|
||||
string fileName;
|
||||
foreach (string path in item.Collection)
|
||||
{
|
||||
if (path.Contains(resultAllInOne))
|
||||
continue;
|
||||
fileName = Path.GetFileName(path);
|
||||
directory = IDirectory.GetDirectory(fileName);
|
||||
rename.Add(new(path, Path.Combine(resultAllInOneDirectory, directory.ToString(), fileName)));
|
||||
}
|
||||
}
|
||||
|
||||
private static void IsNotUniqueLoop(string directory, string resultAllInOne, string jsonGroupDirectory, string extension, FilePair item, List<(string, string)> rename)
|
||||
{
|
||||
int length = directory.Length;
|
||||
foreach (string path in item.Collection)
|
||||
{
|
||||
if (!path.Contains(resultAllInOne))
|
||||
continue;
|
||||
if (item.Match is null || path != item.Match)
|
||||
continue;
|
||||
rename.Add(new(path, string.Concat(jsonGroupDirectory, item.Path[length..], extension)));
|
||||
}
|
||||
}
|
||||
|
||||
internal static int MaybeMove(string directory, string resultAllInOne, List<FilePair> filePairs, string jsonGroupDirectory, string extension)
|
||||
{
|
||||
FileInfo? toFileInfo;
|
||||
FileInfo fromFileInfo;
|
||||
string checkDirectory;
|
||||
List<(string, string)> rename = new();
|
||||
string resultAllInOneDirectory = Path.Combine(jsonGroupDirectory, resultAllInOne);
|
||||
foreach (FilePair item in filePairs)
|
||||
{
|
||||
if (item.IsUnique)
|
||||
IsUniqueLoop(resultAllInOne, resultAllInOneDirectory, item, rename);
|
||||
else
|
||||
IsNotUniqueLoop(directory, resultAllInOne, jsonGroupDirectory, extension, item, 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, ".i");
|
||||
}
|
||||
File.Move(from, checkDirectory);
|
||||
}
|
||||
_ = IPath.DeleteEmptyDirectories(jsonGroupDirectory);
|
||||
return rename.Count;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user