Mostly Sorting
Video Merge as 4, 5, and 6 Enum change to last character
This commit is contained in:
parent
ae23e803fa
commit
9fb6f0fa05
14
.vscode/tasks.json
vendored
14
.vscode/tasks.json
vendored
@ -628,5 +628,19 @@
|
||||
],
|
||||
"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/AA",
|
||||
"Day-Helper-2025-03-20",
|
||||
"false",
|
||||
"4"
|
||||
],
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
@ -17,6 +17,21 @@ public partial class Compare : ICompare, IDisposable
|
||||
private ProgressBar? _ProgressBar;
|
||||
private readonly ProgressBarOptions _ProgressBarOptions;
|
||||
|
||||
void ICompare.Tick() =>
|
||||
_ProgressBar?.Tick();
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
_ProgressBar?.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
void ICompare.ConstructProgressBar(int maxTicks, string message)
|
||||
{
|
||||
_ProgressBar?.Dispose();
|
||||
_ProgressBar = new(maxTicks, message, _ProgressBarOptions);
|
||||
}
|
||||
|
||||
public Compare(List<string> args, ILogger<Program>? logger, AppSettings appSettings, bool isSilent, IConsole console)
|
||||
{
|
||||
if (isSilent)
|
||||
@ -31,19 +46,46 @@ public partial class Compare : ICompare, IDisposable
|
||||
CompareWork(logger, appSettings, compare, ticks);
|
||||
}
|
||||
|
||||
void ICompare.Tick() =>
|
||||
_ProgressBar?.Tick();
|
||||
|
||||
void ICompare.ConstructProgressBar(int maxTicks, string message)
|
||||
private void CompareWork(ILogger<Program>? logger, AppSettings appSettings, ICompare compare, long ticks)
|
||||
{
|
||||
const int updated = 0;
|
||||
DistanceLimits? distanceLimits;
|
||||
logger?.LogInformation("{Ticks}", ticks);
|
||||
ReadOnlyCollection<LocationContainer> matrix;
|
||||
ReadOnlyCollection<SaveContainer> saveContainers;
|
||||
ReadOnlyCollection<ExifDirectory> exifDirectories;
|
||||
ReadOnlyCollection<LocationContainer> preFiltered;
|
||||
ReadOnlyCollection<LocationContainer> postFiltered;
|
||||
ReadOnlyDictionary<string, LocationContainer> onlyOne;
|
||||
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(appSettings, ticks);
|
||||
ReadOnlyCollections readOnlyCollections = GetReadOnlyCollections(appSettings);
|
||||
ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding = GetMappedExifDirectoryWithEncoding(appSettings, compare, ticks, readOnlyCollections);
|
||||
ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs = IDistance.Extract(appSettings.CompareSettings, mappedExifDirectoryWithEncoding);
|
||||
foreach (string outputResolution in appSettings.CompareSettings.OutputResolutions)
|
||||
{
|
||||
if (runToDoCollectionFirst || outputResolution.Any(char.IsNumber))
|
||||
continue;
|
||||
_ProgressBar?.Dispose();
|
||||
_ProgressBar = new(maxTicks, message, _ProgressBarOptions);
|
||||
logger?.LogInformation("{outputResolution}", outputResolution);
|
||||
exifDirectories = IFace.GetExifDirectories(appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, outputResolution);
|
||||
preFiltered = IDistance.GetPreFilterLocationContainer(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, readOnlyCollections, keyValuePairs, exifDirectories);
|
||||
if (preFiltered.Count == 0)
|
||||
continue;
|
||||
distanceLimits = new(appSettings.DistanceSettings);
|
||||
postFiltered = IDistance.GetPostFilterLocationContainer(preFiltered, distanceLimits);
|
||||
if (postFiltered.Count == 0)
|
||||
continue;
|
||||
matrix = IDistance.GetMatrixLocationContainers(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered);
|
||||
if (matrix.Count == 0)
|
||||
continue;
|
||||
onlyOne = IDistance.GetOnlyOne(appSettings.DistanceSettings, matrix);
|
||||
if (onlyOne.Count == 0)
|
||||
continue;
|
||||
saveContainers = IDistance.GetSaveContainers(appSettings.ResultSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, outputResolution, onlyOne);
|
||||
if (saveContainers.Count == 0)
|
||||
continue;
|
||||
IDistance.SaveContainers(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, updated, saveContainers);
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
_ProgressBar?.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private static bool GetRunToDoCollectionFirst(AppSettings appSettings, long ticks)
|
||||
@ -123,46 +165,4 @@ public partial class Compare : ICompare, IDisposable
|
||||
return results;
|
||||
}
|
||||
|
||||
private void CompareWork(ILogger<Program>? logger, AppSettings appSettings, ICompare compare, long ticks)
|
||||
{
|
||||
const int updated = 0;
|
||||
DistanceLimits? distanceLimits;
|
||||
logger?.LogInformation("{Ticks}", ticks);
|
||||
ReadOnlyCollection<LocationContainer> matrix;
|
||||
ReadOnlyCollection<SaveContainer> saveContainers;
|
||||
ReadOnlyCollection<ExifDirectory> exifDirectories;
|
||||
ReadOnlyCollection<LocationContainer> preFiltered;
|
||||
ReadOnlyCollection<LocationContainer> postFiltered;
|
||||
ReadOnlyDictionary<string, LocationContainer> onlyOne;
|
||||
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(appSettings, ticks);
|
||||
ReadOnlyCollections readOnlyCollections = GetReadOnlyCollections(appSettings);
|
||||
ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding = GetMappedExifDirectoryWithEncoding(appSettings, compare, ticks, readOnlyCollections);
|
||||
ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs = IDistance.Extract(appSettings.CompareSettings, mappedExifDirectoryWithEncoding);
|
||||
foreach (string outputResolution in appSettings.CompareSettings.OutputResolutions)
|
||||
{
|
||||
if (runToDoCollectionFirst || outputResolution.Any(char.IsNumber))
|
||||
continue;
|
||||
_ProgressBar?.Dispose();
|
||||
logger?.LogInformation("{outputResolution}", outputResolution);
|
||||
exifDirectories = IFace.GetExifDirectories(appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, outputResolution);
|
||||
preFiltered = IDistance.GetPreFilterLocationContainer(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, readOnlyCollections, keyValuePairs, exifDirectories);
|
||||
if (preFiltered.Count == 0)
|
||||
continue;
|
||||
distanceLimits = new(appSettings.DistanceSettings);
|
||||
postFiltered = IDistance.GetPostFilterLocationContainer(preFiltered, distanceLimits);
|
||||
if (postFiltered.Count == 0)
|
||||
continue;
|
||||
matrix = IDistance.GetMatrixLocationContainers(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered);
|
||||
if (matrix.Count == 0)
|
||||
continue;
|
||||
onlyOne = IDistance.GetOnlyOne(appSettings.DistanceSettings, matrix);
|
||||
if (onlyOne.Count == 0)
|
||||
continue;
|
||||
saveContainers = IDistance.GetSaveContainers(appSettings.ResultSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, outputResolution, onlyOne);
|
||||
if (saveContainers.Count == 0)
|
||||
continue;
|
||||
IDistance.SaveContainers(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, updated, saveContainers);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -8,11 +8,8 @@ public record CompareSettings(string Company,
|
||||
string FacesFileNameExtension,
|
||||
string FacesHiddenFileNameExtension,
|
||||
string FacesPartsFileNameExtension,
|
||||
string[] IgnoreExtensions,
|
||||
int MaxDegreeOfParallelism,
|
||||
string[] OutputResolutions,
|
||||
string[] ValidImageFormatExtensions,
|
||||
string[] ValidVideoFormatExtensions) : Shared.Models.Properties.ICompareSettings
|
||||
string[] OutputResolutions) : Shared.Models.Properties.ICompareSettings
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
|
@ -11,11 +11,21 @@ namespace View_by_Distance.Distance.Models.Stateless;
|
||||
internal static class FilterLogicD
|
||||
{
|
||||
|
||||
internal record RecordA(long? Ticks, string? Directory);
|
||||
internal static string GetResizeContentDirectory(ResultSettings resultSettings, string cContentDirectory, FilePath filePath)
|
||||
{
|
||||
string result;
|
||||
CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(resultSettings, filePath);
|
||||
result = Path.Combine(cContentDirectory, cei.Combined);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal record RecordB(string ByValue, bool IsByMapping, bool IsBySorting);
|
||||
|
||||
internal record RecordC(string? DebugDirectory, string? Directory, long? Ticks, string? PersonDirectory);
|
||||
internal static string GetFacePartsDirectoryX(ResultSettings resultSettings, string d2FacePartsContentDirectory, FilePath filePath)
|
||||
{
|
||||
string result;
|
||||
CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(resultSettings, filePath);
|
||||
result = Path.Combine(d2FacePartsContentDirectory, cei.Combined, filePath.NameWithoutExtension);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static RecordB Get(int? useFiltersCounter, bool saveIndividually, bool sortingContainersAny, string forceSingleImageHumanized, int? distancePermyriad, int? by, string? displayDirectoryName)
|
||||
{
|
||||
@ -39,141 +49,12 @@ internal static class FilterLogicD
|
||||
else if (isBySorting && useFiltersCounter.HasValue)
|
||||
byValue = $"{nameof(IMapLogic.Sorting)}{(!isDefaultName ? "-A" : "-Z")} Modified Filters - {useFiltersCounter.Value}";
|
||||
else
|
||||
{
|
||||
byValue = $"{by.Value switch
|
||||
{
|
||||
IMapLogic.Mapping => nameof(IMapLogic.Mapping),
|
||||
IMapLogic.Sorting => saveIndividually ? nameof(IMapLogic.Individually) : nameof(IMapLogic.Sorting),
|
||||
IMapLogic.ForceSingleImage => forceSingleImageHumanized,
|
||||
_ => throw new NotImplementedException()
|
||||
}}{(!isDefaultName ? "-A" : "-Z")}";
|
||||
}
|
||||
byValue = IDistance.Get(saveIndividually, forceSingleImageHumanized, by.Value, isDefaultName);
|
||||
}
|
||||
result = new(byValue, isByMapping, isBySorting);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static RecordB Get(int? useFiltersCounter, bool saveIndividually, bool sortingContainersAny, string forceSingleImageHumanized, int? distancePermyriad, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName) =>
|
||||
Get(useFiltersCounter, saveIndividually, sortingContainersAny, forceSingleImageHumanized, distancePermyriad, personKeyFormattedAndKeyTicksAndDisplayDirectoryName is null ? null : IMapLogic.Mapping, personKeyFormattedAndKeyTicksAndDisplayDirectoryName?.DisplayDirectoryName);
|
||||
|
||||
private static RecordC Get(string eDistanceContentTicksDirectory, RecordB recordB, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName, string segmentB)
|
||||
{
|
||||
RecordC result;
|
||||
if (string.IsNullOrEmpty(personKeyFormattedAndKeyTicksAndDisplayDirectoryName?.DisplayDirectoryName))
|
||||
throw new NotImplementedException();
|
||||
long? ticks = null;
|
||||
string? debugDirectory = Path.Combine(eDistanceContentTicksDirectory, recordB.ByValue, personKeyFormattedAndKeyTicksAndDisplayDirectoryName.KeyFormatted, personKeyFormattedAndKeyTicksAndDisplayDirectoryName.DisplayDirectoryName);
|
||||
string? directory = Path.Combine(eDistanceContentTicksDirectory, recordB.ByValue, personKeyFormattedAndKeyTicksAndDisplayDirectoryName.KeyFormatted, segmentB);
|
||||
string? personDirectory = Path.Combine(directory, personKeyFormattedAndKeyTicksAndDisplayDirectoryName.DisplayDirectoryName, "lnk");
|
||||
result = new(debugDirectory, directory, ticks, personDirectory);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string GetResizeContentDirectory(ResultSettings resultSettings, string cContentDirectory, FilePath filePath)
|
||||
{
|
||||
string result;
|
||||
CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(resultSettings, filePath);
|
||||
result = Path.Combine(cContentDirectory, cei.Combined);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string GetFacePartsDirectoryX(ResultSettings resultSettings, string d2FacePartsContentDirectory, FilePath filePath)
|
||||
{
|
||||
string result;
|
||||
CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(resultSettings, filePath);
|
||||
result = Path.Combine(d2FacePartsContentDirectory, cei.Combined, filePath.NameWithoutExtension);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static ReadOnlyCollection<SaveContainer> GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne)
|
||||
{
|
||||
List<SaveContainer> results = [];
|
||||
RecordB recordB;
|
||||
RecordC recordC;
|
||||
string segmentB;
|
||||
string checkFile;
|
||||
string? directory;
|
||||
string shortcutFile;
|
||||
string facesDirectory;
|
||||
bool isCounterPersonYear;
|
||||
string facePartsDirectory;
|
||||
FileHolder? faceFileHolder;
|
||||
SaveContainer? saveContainer;
|
||||
FileHolder? resizedFileHolder;
|
||||
int? useFiltersCounter = null;
|
||||
string resizeContentDirectory;
|
||||
FileHolder? facePartsFileHolder;
|
||||
FileHolder? hiddenFaceFileHolder;
|
||||
LocationContainer locationContainer;
|
||||
bool sortingContainersAny = onlyOne.Count > 0;
|
||||
string eResultsFullGroupDirectory = IResult.GetResultsDateGroupDirectory(resultSettings,
|
||||
nameof(E_Distance),
|
||||
resultSettings.ResultContent);
|
||||
string cResultsFullGroupDirectory = IResult.GetResultsFullGroupDirectory(resultSettings,
|
||||
nameof(C_Resize),
|
||||
outputResolution,
|
||||
includeResizeGroup: true,
|
||||
includeModel: false,
|
||||
includePredictorModel: false);
|
||||
string d2ResultsFullGroupDirectory = IResult.GetResultsFullGroupDirectory(resultSettings,
|
||||
nameof(D2_FaceParts),
|
||||
outputResolution,
|
||||
includeResizeGroup: true,
|
||||
includeModel: true,
|
||||
includePredictorModel: true);
|
||||
string cContentDirectory = Path.Combine(cResultsFullGroupDirectory, resultSettings.ResultContent);
|
||||
if (!Directory.Exists(cContentDirectory))
|
||||
_ = Directory.CreateDirectory(cContentDirectory);
|
||||
string eDistanceContentTicksDirectory = Path.Combine(eResultsFullGroupDirectory, ticks.ToString());
|
||||
if (!Directory.Exists(eDistanceContentTicksDirectory))
|
||||
_ = Directory.CreateDirectory(eDistanceContentTicksDirectory);
|
||||
string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, resultSettings.ResultContent);
|
||||
if (!Directory.Exists(d2FacePartsContentDirectory))
|
||||
_ = Directory.CreateDirectory(d2FacePartsContentDirectory);
|
||||
string forceSingleImageHumanized = nameof(IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title);
|
||||
string message = $") Building Save Container Collection - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
||||
compare.ConstructProgressBar(onlyOne.Count, message);
|
||||
foreach (KeyValuePair<string, LocationContainer> keyValuePair in onlyOne)
|
||||
{
|
||||
if (distanceSettings.SaveIndividually)
|
||||
break;
|
||||
locationContainer = keyValuePair.Value;
|
||||
if (locationContainer.LengthPermyriad is null || locationContainer.LengthSource is null)
|
||||
continue;
|
||||
segmentB = locationContainer.LengthPermyriad.Value.ToString().PadLeft(2, '0')[..2];
|
||||
if (locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName is null)
|
||||
continue;
|
||||
isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName.KeyTicks);
|
||||
recordB = Get(useFiltersCounter, distanceSettings.SaveIndividually, sortingContainersAny, forceSingleImageHumanized, locationContainer.LengthPermyriad, locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName);
|
||||
recordC = Get(eDistanceContentTicksDirectory, recordB, locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName, segmentB);
|
||||
if (string.IsNullOrEmpty(recordC.Directory) || string.IsNullOrEmpty(recordC.PersonDirectory))
|
||||
continue;
|
||||
directory = recordC.Directory;
|
||||
if (!string.IsNullOrEmpty(recordC.DebugDirectory))
|
||||
results.Add(SaveContainer.Get(recordC.DebugDirectory));
|
||||
if (locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName is null)
|
||||
{
|
||||
if (!distanceSettings.SaveSortingWithoutPerson)
|
||||
throw new NotSupportedException();
|
||||
if (recordC.Ticks is null)
|
||||
continue;
|
||||
}
|
||||
results.Add(SaveContainer.Get(recordC.PersonDirectory));
|
||||
facesDirectory = locationContainer.LengthSource.DirectoryFullPath;
|
||||
faceFileHolder = FileHolder.Get(locationContainer.LengthSource.FullName);
|
||||
checkFile = Path.Combine(directory, $"{locationContainer.LengthSource.Name}");
|
||||
shortcutFile = Path.Combine(recordC.PersonDirectory, $"{locationContainer.LengthSource.Name}.lnk");
|
||||
resizeContentDirectory = GetResizeContentDirectory(resultSettings, cContentDirectory, locationContainer.LengthSource);
|
||||
facePartsDirectory = GetFacePartsDirectoryX(resultSettings, d2FacePartsContentDirectory, locationContainer.LengthSource);
|
||||
hiddenFaceFileHolder = FileHolder.Get(Path.Combine(facesDirectory, $"{locationContainer.LengthSource.NameWithoutExtension}{compareSettings.FacesHiddenFileNameExtension}"));
|
||||
facePartsFileHolder = FileHolder.Get(Path.Combine(facePartsDirectory, $"{locationContainer.LengthSource.NameWithoutExtension}{compareSettings.FacesPartsFileNameExtension}"));
|
||||
resizedFileHolder = FileHolder.Get(Path.Combine(resizeContentDirectory, $"{locationContainer.LengthSource.FileNameFirstSegment}{Path.GetExtension(locationContainer.LengthSource.NameWithoutExtension)}"));
|
||||
saveContainer = SaveContainer.Get(checkFile, directory, faceFileHolder, hiddenFaceFileHolder, facePartsFileHolder, resizedFileHolder, shortcutFile);
|
||||
results.Add(saveContainer);
|
||||
}
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
internal static void SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, int? updated, ReadOnlyCollection<SaveContainer> saveContainers)
|
||||
{
|
||||
string fileName;
|
||||
@ -285,4 +166,115 @@ internal static class FilterLogicD
|
||||
}
|
||||
}
|
||||
|
||||
internal static ReadOnlyCollection<SaveContainer> GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne)
|
||||
{
|
||||
List<SaveContainer> results = [];
|
||||
RecordB recordB;
|
||||
RecordC recordC;
|
||||
string segmentB;
|
||||
string checkFile;
|
||||
string? directory;
|
||||
string shortcutFile;
|
||||
string facesDirectory;
|
||||
bool isCounterPersonYear;
|
||||
string facePartsDirectory;
|
||||
FileHolder? faceFileHolder;
|
||||
SaveContainer? saveContainer;
|
||||
FileHolder? resizedFileHolder;
|
||||
int? useFiltersCounter = null;
|
||||
string resizeContentDirectory;
|
||||
FileHolder? facePartsFileHolder;
|
||||
FileHolder? hiddenFaceFileHolder;
|
||||
LocationContainer locationContainer;
|
||||
bool sortingContainersAny = onlyOne.Count > 0;
|
||||
string eResultsFullGroupDirectory = IResult.GetResultsDateGroupDirectory(resultSettings,
|
||||
nameof(E_Distance),
|
||||
resultSettings.ResultContent);
|
||||
string cResultsFullGroupDirectory = IResult.GetResultsFullGroupDirectory(resultSettings,
|
||||
nameof(C_Resize),
|
||||
outputResolution,
|
||||
includeResizeGroup: true,
|
||||
includeModel: false,
|
||||
includePredictorModel: false);
|
||||
string d2ResultsFullGroupDirectory = IResult.GetResultsFullGroupDirectory(resultSettings,
|
||||
nameof(D2_FaceParts),
|
||||
outputResolution,
|
||||
includeResizeGroup: true,
|
||||
includeModel: true,
|
||||
includePredictorModel: true);
|
||||
string cContentDirectory = Path.Combine(cResultsFullGroupDirectory, resultSettings.ResultContent);
|
||||
if (!Directory.Exists(cContentDirectory))
|
||||
_ = Directory.CreateDirectory(cContentDirectory);
|
||||
string eDistanceContentTicksDirectory = Path.Combine(eResultsFullGroupDirectory, ticks.ToString());
|
||||
if (!Directory.Exists(eDistanceContentTicksDirectory))
|
||||
_ = Directory.CreateDirectory(eDistanceContentTicksDirectory);
|
||||
string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, resultSettings.ResultContent);
|
||||
if (!Directory.Exists(d2FacePartsContentDirectory))
|
||||
_ = Directory.CreateDirectory(d2FacePartsContentDirectory);
|
||||
string forceSingleImageHumanized = nameof(IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title);
|
||||
string message = $") Building Save Container Collection - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
||||
compare.ConstructProgressBar(onlyOne.Count, message);
|
||||
foreach (KeyValuePair<string, LocationContainer> keyValuePair in onlyOne)
|
||||
{
|
||||
if (distanceSettings.SaveIndividually)
|
||||
break;
|
||||
locationContainer = keyValuePair.Value;
|
||||
if (locationContainer.LengthPermyriad is null || locationContainer.LengthSource is null)
|
||||
continue;
|
||||
segmentB = locationContainer.LengthPermyriad.Value.ToString().PadLeft(2, '0')[..2];
|
||||
if (locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName is null)
|
||||
continue;
|
||||
isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName.KeyTicks);
|
||||
recordB = Get(useFiltersCounter, distanceSettings.SaveIndividually, sortingContainersAny, forceSingleImageHumanized, locationContainer.LengthPermyriad, locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName);
|
||||
recordC = Get(eDistanceContentTicksDirectory, recordB, locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName, segmentB);
|
||||
if (string.IsNullOrEmpty(recordC.Directory) || string.IsNullOrEmpty(recordC.PersonDirectory))
|
||||
continue;
|
||||
directory = recordC.Directory;
|
||||
if (!string.IsNullOrEmpty(recordC.DebugDirectory))
|
||||
results.Add(SaveContainer.Get(recordC.DebugDirectory));
|
||||
if (locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName is null)
|
||||
{
|
||||
if (!distanceSettings.SaveSortingWithoutPerson)
|
||||
throw new NotSupportedException();
|
||||
if (recordC.Ticks is null)
|
||||
continue;
|
||||
}
|
||||
results.Add(SaveContainer.Get(recordC.PersonDirectory));
|
||||
facesDirectory = locationContainer.LengthSource.DirectoryFullPath;
|
||||
faceFileHolder = FileHolder.Get(locationContainer.LengthSource.FullName);
|
||||
checkFile = Path.Combine(directory, $"{locationContainer.LengthSource.Name}");
|
||||
shortcutFile = Path.Combine(recordC.PersonDirectory, $"{locationContainer.LengthSource.Name}.lnk");
|
||||
resizeContentDirectory = GetResizeContentDirectory(resultSettings, cContentDirectory, locationContainer.LengthSource);
|
||||
facePartsDirectory = GetFacePartsDirectoryX(resultSettings, d2FacePartsContentDirectory, locationContainer.LengthSource);
|
||||
hiddenFaceFileHolder = FileHolder.Get(Path.Combine(facesDirectory, $"{locationContainer.LengthSource.NameWithoutExtension}{compareSettings.FacesHiddenFileNameExtension}"));
|
||||
facePartsFileHolder = FileHolder.Get(Path.Combine(facePartsDirectory, $"{locationContainer.LengthSource.NameWithoutExtension}{compareSettings.FacesPartsFileNameExtension}"));
|
||||
resizedFileHolder = FileHolder.Get(Path.Combine(resizeContentDirectory, $"{locationContainer.LengthSource.FileNameFirstSegment}{Path.GetExtension(locationContainer.LengthSource.NameWithoutExtension)}"));
|
||||
saveContainer = SaveContainer.Get(checkFile, directory, faceFileHolder, hiddenFaceFileHolder, facePartsFileHolder, resizedFileHolder, shortcutFile);
|
||||
results.Add(saveContainer);
|
||||
}
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private static RecordB Get(int? useFiltersCounter, bool saveIndividually, bool sortingContainersAny, string forceSingleImageHumanized, int? distancePermyriad, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName) =>
|
||||
Get(useFiltersCounter, saveIndividually, sortingContainersAny, forceSingleImageHumanized, distancePermyriad, personKeyFormattedAndKeyTicksAndDisplayDirectoryName is null ? null : IMapLogic.Mapping, personKeyFormattedAndKeyTicksAndDisplayDirectoryName?.DisplayDirectoryName);
|
||||
|
||||
private static RecordC Get(string eDistanceContentTicksDirectory, RecordB recordB, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName, string segmentB)
|
||||
{
|
||||
RecordC result;
|
||||
if (string.IsNullOrEmpty(personKeyFormattedAndKeyTicksAndDisplayDirectoryName?.DisplayDirectoryName))
|
||||
throw new NotImplementedException();
|
||||
long? ticks = null;
|
||||
string? debugDirectory = Path.Combine(eDistanceContentTicksDirectory, recordB.ByValue, personKeyFormattedAndKeyTicksAndDisplayDirectoryName.KeyFormatted, personKeyFormattedAndKeyTicksAndDisplayDirectoryName.DisplayDirectoryName);
|
||||
string? directory = Path.Combine(eDistanceContentTicksDirectory, recordB.ByValue, personKeyFormattedAndKeyTicksAndDisplayDirectoryName.KeyFormatted, segmentB);
|
||||
string? personDirectory = Path.Combine(directory, personKeyFormattedAndKeyTicksAndDisplayDirectoryName.DisplayDirectoryName, "lnk");
|
||||
result = new(debugDirectory, directory, ticks, personDirectory);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal record RecordA(long? Ticks, string? Directory);
|
||||
|
||||
internal record RecordB(string ByValue, bool IsByMapping, bool IsBySorting);
|
||||
|
||||
internal record RecordC(string? DebugDirectory, string? Directory, long? Ticks, string? PersonDirectory);
|
||||
|
||||
}
|
@ -9,49 +9,69 @@ namespace View_by_Distance.Distance.Models.Stateless;
|
||||
public interface IDistance
|
||||
{
|
||||
|
||||
static ReadOnlyCollection<ExifDirectory> TestStatic_GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections) =>
|
||||
GetMapped(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, ticks, readOnlyCollections);
|
||||
static ReadOnlyCollection<ExifDirectory> GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections) =>
|
||||
MappedLogicA.GetMapped(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, ticks, readOnlyCollections);
|
||||
static string Get(bool saveIndividually, string forceSingleImageHumanized, int by, bool isDefaultName) =>
|
||||
$"{by switch
|
||||
{
|
||||
IMapLogic.Mapping => nameof(IMapLogic.Mapping),
|
||||
IMapLogic.Sorting => saveIndividually ?
|
||||
nameof(IMapLogic.Individually) :
|
||||
nameof(IMapLogic.Sorting),
|
||||
IMapLogic.ForceSingleImage => forceSingleImageHumanized,
|
||||
_ => throw new NotImplementedException()
|
||||
}}{(!isDefaultName ? "-A" : "-Z")}";
|
||||
|
||||
static ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> TestStatic_Extract(ICompareSettings compareSettings, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
Extract(compareSettings, exifDirectories);
|
||||
static ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> Extract(ICompareSettings compareSettings, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
MappedLogicA.Extract(compareSettings, exifDirectories);
|
||||
|
||||
static ReadOnlyCollection<ExifDirectory> TestStatic_GetMappedExifDirectoryWithEncoding(ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
GetMappedExifDirectoryWithEncoding(compare, ticks, exifDirectories);
|
||||
static ReadOnlyCollection<ExifDirectory> GetMappedExifDirectoryWithEncoding(ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
FaceEncodingLogic.GetMappedExifDirectoryWithEncoding(compare, ticks, exifDirectories);
|
||||
|
||||
static ReadOnlyCollection<LocationContainer> TestStatic_GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, ticks, readOnlyCollections, keyValuePairs, exifDirectories);
|
||||
static ReadOnlyCollection<LocationContainer> GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
FilterLogicA.GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, ticks, readOnlyCollections, keyValuePairs, exifDirectories);
|
||||
|
||||
static ReadOnlyCollection<LocationContainer> TestStatic_GetPostFilterLocationContainer(ReadOnlyCollection<LocationContainer> preFiltered, DistanceLimits distanceLimits) =>
|
||||
GetPostFilterLocationContainer(preFiltered, distanceLimits);
|
||||
static ReadOnlyCollection<LocationContainer> GetPostFilterLocationContainer(ReadOnlyCollection<LocationContainer> preFiltered, DistanceLimits distanceLimits) =>
|
||||
FilterLogicC.GetPostFilterLocationContainer(preFiltered, distanceLimits);
|
||||
|
||||
static ReadOnlyCollection<LocationContainer> TestStatic_GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) =>
|
||||
GetMatrixLocationContainers(distanceSettings, compareSettings, compare, ticks, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered);
|
||||
static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) =>
|
||||
FilterLogicC.GetMatrixLocationContainers(distanceSettings, compareSettings, compare, ticks, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered);
|
||||
|
||||
static ReadOnlyDictionary<string, LocationContainer> TestStatic_GetOnlyOne(DistanceSettings distanceSettings, ReadOnlyCollection<LocationContainer> matrix) =>
|
||||
GetOnlyOne(distanceSettings, matrix);
|
||||
static ReadOnlyDictionary<string, LocationContainer> GetOnlyOne(DistanceSettings distanceSettings, ReadOnlyCollection<LocationContainer> matrix) =>
|
||||
public static ReadOnlyDictionary<string, LocationContainer> GetOnlyOne(DistanceSettings distanceSettings, ReadOnlyCollection<LocationContainer> matrix) =>
|
||||
FilterLogicC.GetOnlyOne(distanceSettings, matrix);
|
||||
|
||||
static ReadOnlyCollection<SaveContainer> TestStatic_GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) =>
|
||||
GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, ticks, outputResolution, onlyOne);
|
||||
static ReadOnlyCollection<SaveContainer> GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) =>
|
||||
FilterLogicD.GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, ticks, outputResolution, onlyOne);
|
||||
public static ReadOnlyCollection<ExifDirectory> GetMappedExifDirectoryWithEncoding(ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
FaceEncodingLogic.GetMappedExifDirectoryWithEncoding(compare, ticks, exifDirectories);
|
||||
|
||||
static void TestStatic_SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) =>
|
||||
SaveContainers(distanceSettings, compareSettings, compare, ticks, updated, saveContainers);
|
||||
static void SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) =>
|
||||
public static ReadOnlyCollection<LocationContainer> GetPostFilterLocationContainer(ReadOnlyCollection<LocationContainer> preFiltered, DistanceLimits distanceLimits) =>
|
||||
FilterLogicC.GetPostFilterLocationContainer(preFiltered, distanceLimits);
|
||||
|
||||
public static ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> Extract(ICompareSettings compareSettings, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
MappedLogicA.Extract(compareSettings, exifDirectories);
|
||||
|
||||
public static void SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) =>
|
||||
FilterLogicD.SaveContainers(distanceSettings, compareSettings, compare, ticks, updated, saveContainers);
|
||||
|
||||
public static ReadOnlyCollection<SaveContainer> GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) =>
|
||||
FilterLogicD.GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, ticks, outputResolution, onlyOne);
|
||||
|
||||
public static ReadOnlyCollection<ExifDirectory> GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections) =>
|
||||
MappedLogicA.GetMapped(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, ticks, readOnlyCollections);
|
||||
|
||||
public static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) =>
|
||||
FilterLogicC.GetMatrixLocationContainers(distanceSettings, compareSettings, compare, ticks, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered);
|
||||
|
||||
public static ReadOnlyCollection<LocationContainer> GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
FilterLogicA.GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, ticks, readOnlyCollections, keyValuePairs, exifDirectories);
|
||||
|
||||
internal static ReadOnlyDictionary<string, LocationContainer> TestStatic_GetOnlyOne(DistanceSettings distanceSettings, ReadOnlyCollection<LocationContainer> matrix) =>
|
||||
GetOnlyOne(distanceSettings, matrix);
|
||||
|
||||
internal static ReadOnlyCollection<ExifDirectory> TestStatic_GetMappedExifDirectoryWithEncoding(ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
GetMappedExifDirectoryWithEncoding(compare, ticks, exifDirectories);
|
||||
|
||||
internal static ReadOnlyCollection<LocationContainer> TestStatic_GetPostFilterLocationContainer(ReadOnlyCollection<LocationContainer> preFiltered, DistanceLimits distanceLimits) =>
|
||||
GetPostFilterLocationContainer(preFiltered, distanceLimits);
|
||||
|
||||
internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> TestStatic_Extract(ICompareSettings compareSettings, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
Extract(compareSettings, exifDirectories);
|
||||
|
||||
internal static void TestStatic_SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) =>
|
||||
SaveContainers(distanceSettings, compareSettings, compare, ticks, updated, saveContainers);
|
||||
|
||||
internal static ReadOnlyCollection<SaveContainer> TestStatic_GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) =>
|
||||
GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, ticks, outputResolution, onlyOne);
|
||||
|
||||
internal static ReadOnlyCollection<ExifDirectory> TestStatic_GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections) =>
|
||||
GetMapped(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, ticks, readOnlyCollections);
|
||||
|
||||
internal static ReadOnlyCollection<LocationContainer> TestStatic_GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) =>
|
||||
GetMatrixLocationContainers(distanceSettings, compareSettings, compare, ticks, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered);
|
||||
|
||||
internal static ReadOnlyCollection<LocationContainer> TestStatic_GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
|
||||
GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, ticks, readOnlyCollections, keyValuePairs, exifDirectories);
|
||||
|
||||
}
|
@ -14,33 +14,53 @@ internal static class MappedLogicA
|
||||
string? PersonDisplayDirectoryName,
|
||||
FilePath FilePath);
|
||||
|
||||
private static List<MappedFile> GetDisplayDirectoryAllFiles(PeopleSettings peopleSettings, ICompareSettings compareSettings, ReadOnlyCollections readOnlyCollections)
|
||||
internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> Extract(ICompareSettings compareSettings, ReadOnlyCollection<ExifDirectory> exifDirectories)
|
||||
{
|
||||
List<MappedFile> results = [];
|
||||
FilePath filePath;
|
||||
MappedFile mappedFile;
|
||||
string personKeyFormatted;
|
||||
List<string> distinct = [];
|
||||
PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName personKeyFormattedAndKeyTicksAndDisplayDirectoryName;
|
||||
foreach (PersonContainer personContainer in readOnlyCollections.PersonContainers)
|
||||
Dictionary<int, ReadOnlyDictionary<int, FilePath>> results = [];
|
||||
int? wholePercentages;
|
||||
Dictionary<int, FilePath>? keyValues;
|
||||
Dictionary<int, Dictionary<int, FilePath>> keyValuePairs = [];
|
||||
foreach (ExifDirectory exifDirectory in exifDirectories)
|
||||
{
|
||||
if (personContainer.Key is null)
|
||||
if (exifDirectory.FilePath.Id is null)
|
||||
continue;
|
||||
for (int i = personContainer.DisplayDirectoryAllFilePaths.Count - 1; i > -1; i--)
|
||||
if (!keyValuePairs.TryGetValue(exifDirectory.FilePath.Id.Value, out keyValues))
|
||||
{
|
||||
filePath = personContainer.DisplayDirectoryAllFilePaths[i];
|
||||
if (filePath.ExtensionLowered != compareSettings.FacesFileNameExtension)
|
||||
continue;
|
||||
if (distinct.Contains(filePath.Name))
|
||||
continue;
|
||||
distinct.Add(filePath.Name);
|
||||
personKeyFormatted = IPersonBirthday.GetFormatted(peopleSettings.PersonBirthdayFormat, personContainer.Key.Value);
|
||||
personKeyFormattedAndKeyTicksAndDisplayDirectoryName = new(personKeyFormatted, personContainer.Key.Value, filePath.Name);
|
||||
mappedFile = new(personKeyFormattedAndKeyTicksAndDisplayDirectoryName, personContainer.DisplayDirectoryName, filePath);
|
||||
results.Add(mappedFile);
|
||||
keyValuePairs.Add(exifDirectory.FilePath.Id.Value, []);
|
||||
if (!keyValuePairs.TryGetValue(exifDirectory.FilePath.Id.Value, out keyValues))
|
||||
throw new Exception();
|
||||
}
|
||||
wholePercentages = IMapping.GetWholePercentages(compareSettings, exifDirectory.FilePath);
|
||||
if (wholePercentages is null)
|
||||
continue;
|
||||
keyValues.Add(wholePercentages.Value, exifDirectory.FilePath);
|
||||
}
|
||||
return results;
|
||||
foreach (KeyValuePair<int, Dictionary<int, FilePath>> keyValuePair in keyValuePairs)
|
||||
results.Add(keyValuePair.Key, keyValuePair.Value.AsReadOnly());
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
internal static ReadOnlyCollection<ExifDirectory> GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections)
|
||||
{
|
||||
List<ExifDirectory> results = [];
|
||||
string eDistanceContentDirectory = Path.GetFullPath(IResult.GetResultsDateGroupDirectory(resultSettings, nameof(E_Distance), resultSettings.ResultContent));
|
||||
ReadOnlyCollection<MappedLogicB.Record> records = MappedLogicB.DeleteEmptyDirectoriesAndGetCollection(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, ticks, eDistanceContentDirectory, readOnlyCollections);
|
||||
ReadOnlyCollection<MappedFile> mappedFiles = GetMappedFiles(resultSettings, metadataSettings, peopleSettings, compareSettings, readOnlyCollections, records);
|
||||
if (mappedFiles.Count > 0)
|
||||
{
|
||||
int maxDegreeOfParallelism = compareSettings.MaxDegreeOfParallelism;
|
||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
string message = $") Building Mapped Face Files Collection - {totalSeconds} total second(s)";
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
ReadOnlyDictionary<int, List<FilePathAndWholePercentages>> skipNotSkipCollection = readOnlyCollections.SkipNotSkipCollection;
|
||||
compare.ConstructProgressBar(mappedFiles.Count, message);
|
||||
_ = Parallel.For(0, mappedFiles.Count, parallelOptions, (i, state) =>
|
||||
{
|
||||
compare.Tick();
|
||||
MappedParallelFor(resultSettings, metadataSettings, distanceSettings, compareSettings, results, skipNotSkipCollection, mappedFiles[i]);
|
||||
});
|
||||
}
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<MappedFile> GetMappedFiles(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, ICompareSettings compareSettings, ReadOnlyCollections readOnlyCollections, ReadOnlyCollection<MappedLogicB.Record> records)
|
||||
@ -102,6 +122,35 @@ internal static class MappedLogicA
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private static List<MappedFile> GetDisplayDirectoryAllFiles(PeopleSettings peopleSettings, ICompareSettings compareSettings, ReadOnlyCollections readOnlyCollections)
|
||||
{
|
||||
List<MappedFile> results = [];
|
||||
FilePath filePath;
|
||||
MappedFile mappedFile;
|
||||
string personKeyFormatted;
|
||||
List<string> distinct = [];
|
||||
PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName personKeyFormattedAndKeyTicksAndDisplayDirectoryName;
|
||||
foreach (PersonContainer personContainer in readOnlyCollections.PersonContainers)
|
||||
{
|
||||
if (personContainer.Key is null)
|
||||
continue;
|
||||
for (int i = personContainer.DisplayDirectoryAllFilePaths.Count - 1; i > -1; i--)
|
||||
{
|
||||
filePath = personContainer.DisplayDirectoryAllFilePaths[i];
|
||||
if (filePath.ExtensionLowered != compareSettings.FacesFileNameExtension)
|
||||
continue;
|
||||
if (distinct.Contains(filePath.Name))
|
||||
continue;
|
||||
distinct.Add(filePath.Name);
|
||||
personKeyFormatted = IPersonBirthday.GetFormatted(peopleSettings.PersonBirthdayFormat, personContainer.Key.Value);
|
||||
personKeyFormattedAndKeyTicksAndDisplayDirectoryName = new(personKeyFormatted, personContainer.Key.Value, filePath.Name);
|
||||
mappedFile = new(personKeyFormattedAndKeyTicksAndDisplayDirectoryName, personContainer.DisplayDirectoryName, filePath);
|
||||
results.Add(mappedFile);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void MappedParallelFor(ResultSettings resultSettings, MetadataSettings metadataSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, List<ExifDirectory> exifDirectories, ReadOnlyDictionary<int, List<FilePathAndWholePercentages>> skipCollection, MappedFile mappedFile)
|
||||
{
|
||||
int? id;
|
||||
@ -152,53 +201,4 @@ internal static class MappedLogicA
|
||||
exifDirectories.Add(exifDirectory);
|
||||
}
|
||||
|
||||
internal static ReadOnlyCollection<ExifDirectory> GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections)
|
||||
{
|
||||
List<ExifDirectory> results = [];
|
||||
string eDistanceContentDirectory = Path.GetFullPath(IResult.GetResultsDateGroupDirectory(resultSettings, nameof(E_Distance), resultSettings.ResultContent));
|
||||
ReadOnlyCollection<MappedLogicB.Record> records = MappedLogicB.DeleteEmptyDirectoriesAndGetCollection(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, ticks, eDistanceContentDirectory, readOnlyCollections);
|
||||
ReadOnlyCollection<MappedFile> mappedFiles = GetMappedFiles(resultSettings, metadataSettings, peopleSettings, compareSettings, readOnlyCollections, records);
|
||||
if (mappedFiles.Count > 0)
|
||||
{
|
||||
int maxDegreeOfParallelism = compareSettings.MaxDegreeOfParallelism;
|
||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
string message = $") Building Mapped Face Files Collection - {totalSeconds} total second(s)";
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
ReadOnlyDictionary<int, List<FilePathAndWholePercentages>> skipNotSkipCollection = readOnlyCollections.SkipNotSkipCollection;
|
||||
compare.ConstructProgressBar(mappedFiles.Count, message);
|
||||
_ = Parallel.For(0, mappedFiles.Count, parallelOptions, (i, state) =>
|
||||
{
|
||||
compare.Tick();
|
||||
MappedParallelFor(resultSettings, metadataSettings, distanceSettings, compareSettings, results, skipNotSkipCollection, mappedFiles[i]);
|
||||
});
|
||||
}
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> Extract(ICompareSettings compareSettings, ReadOnlyCollection<ExifDirectory> exifDirectories)
|
||||
{
|
||||
Dictionary<int, ReadOnlyDictionary<int, FilePath>> results = [];
|
||||
int? wholePercentages;
|
||||
Dictionary<int, FilePath>? keyValues;
|
||||
Dictionary<int, Dictionary<int, FilePath>> keyValuePairs = [];
|
||||
foreach (ExifDirectory exifDirectory in exifDirectories)
|
||||
{
|
||||
if (exifDirectory.FilePath.Id is null)
|
||||
continue;
|
||||
if (!keyValuePairs.TryGetValue(exifDirectory.FilePath.Id.Value, out keyValues))
|
||||
{
|
||||
keyValuePairs.Add(exifDirectory.FilePath.Id.Value, []);
|
||||
if (!keyValuePairs.TryGetValue(exifDirectory.FilePath.Id.Value, out keyValues))
|
||||
throw new Exception();
|
||||
}
|
||||
wholePercentages = IMapping.GetWholePercentages(compareSettings, exifDirectory.FilePath);
|
||||
if (wholePercentages is null)
|
||||
continue;
|
||||
keyValues.Add(wholePercentages.Value, exifDirectory.FilePath);
|
||||
}
|
||||
foreach (KeyValuePair<int, Dictionary<int, FilePath>> keyValuePair in keyValuePairs)
|
||||
results.Add(keyValuePair.Key, keyValuePair.Value.AsReadOnly());
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
}
|
@ -24,327 +24,6 @@ internal static class MappedLogicB
|
||||
bool? IsLocationContainerDebugDirectory,
|
||||
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(DistanceSettings distanceSettings, 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(distanceSettings.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 = distanceSettings.LocationContainerDebugDirectory is null ? null : ticksDirectoryNameFirstSegment.EndsWith(distanceSettings.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 && distanceSettings.ReMap)
|
||||
throw new Exception($"Please Consolidate <{string.Join(Environment.NewLine, compare)}>");
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void Individually(ICompareSettings compareSettings, 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 == compareSettings.FacesFileNameExtension select l.FullName).ToArray();
|
||||
else
|
||||
facesFileNames = (from l in collection where l.Extension == compareSettings.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(ResultSettings resultSettings, MetadataSettings metadataSettings, ICompareSettings compareSettings, 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 = FileHolder.Get(file);
|
||||
filePath = FilePath.Get(resultSettings, metadataSettings, fileHolder, index: null);
|
||||
if (filePath.Id is null)
|
||||
continue;
|
||||
wholePercentages = IMapping.GetWholePercentages(compareSettings, 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 = FileHolder.Get(checkFile);
|
||||
filePath = FilePath.Get(resultSettings, metadataSettings, 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 ReadOnlyCollection<Record> DeleteEmptyDirectoriesAndGetCollection(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string eDistanceContentDirectory, ReadOnlyCollections readOnlyCollections)
|
||||
{
|
||||
List<Record> results = [];
|
||||
@ -526,4 +205,325 @@ internal static class MappedLogicB
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private static List<TicksDirectory> UpdateDateVerifyAndGetTicksDirectories(DistanceSettings distanceSettings, 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(distanceSettings.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 = distanceSettings.LocationContainerDebugDirectory is null ? null : ticksDirectoryNameFirstSegment.EndsWith(distanceSettings.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 && distanceSettings.ReMap)
|
||||
throw new Exception($"Please Consolidate <{string.Join(Environment.NewLine, compare)}>");
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void Individually(ICompareSettings compareSettings, 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 == compareSettings.FacesFileNameExtension select l.FullName).ToArray();
|
||||
else
|
||||
facesFileNames = (from l in collection where l.Extension == compareSettings.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(ResultSettings resultSettings, MetadataSettings metadataSettings, ICompareSettings compareSettings, 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 = FileHolder.Get(file);
|
||||
filePath = FilePath.Get(resultSettings, metadataSettings, fileHolder, index: null);
|
||||
if (filePath.Id is null)
|
||||
continue;
|
||||
wholePercentages = IMapping.GetWholePercentages(compareSettings, 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 = FileHolder.Get(checkFile);
|
||||
filePath = FilePath.Get(resultSettings, metadataSettings, 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;
|
||||
}
|
||||
|
||||
}
|
@ -54,51 +54,7 @@ internal static class Get
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
internal static Action<string> SetExifDirectoryCollection(IRename rename, ResultSettings resultSettings, MetadataSettings metadataSettings, IRenameSettings renameSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups)
|
||||
{
|
||||
return file =>
|
||||
{
|
||||
rename.Tick();
|
||||
ExifDirectory exifDirectory;
|
||||
MetadataGroup metadataGroup;
|
||||
DeterministicHashCode deterministicHashCode;
|
||||
FileHolder fileHolder = FileHolder.Get(file);
|
||||
bool fastForwardMovingPictureExpertsGroupUsed;
|
||||
MinimumYearAndPathCombined minimumYearAndPathCombined;
|
||||
FilePath? fastForwardMovingPictureExpertsGroupFilePath;
|
||||
ReadOnlyCollection<string>? fastForwardMovingPictureExpertsGroupFiles;
|
||||
FilePath filePath = FilePath.Get(resultSettings, metadataSettings, fileHolder, index: null);
|
||||
string key = $"{Path.Combine(fileHolder.DirectoryFullPath ?? throw new NotSupportedException(), fileHolder.NameWithoutExtension)}";
|
||||
if (distinct.Contains(key))
|
||||
throw new NotSupportedException("Turn off parallelism when sidecar files are present!");
|
||||
if (renameSettings.SkipIdFiles && filePath.Id is not null && (filePath.IsIntelligentIdFormat || filePath.SortOrder is null))
|
||||
return;
|
||||
if (filePath.Id is not null)
|
||||
{
|
||||
fastForwardMovingPictureExpertsGroupFiles = null;
|
||||
deterministicHashCode = new(null, filePath.Id, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
fastForwardMovingPictureExpertsGroupFiles = rename.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(renameSettings, filePath);
|
||||
fastForwardMovingPictureExpertsGroupFilePath = fastForwardMovingPictureExpertsGroupFiles.Count == 0 ? null : FilePath.Get(resultSettings, metadataSettings, FileHolder.Get(fastForwardMovingPictureExpertsGroupFiles[0]), index: null);
|
||||
deterministicHashCode = fastForwardMovingPictureExpertsGroupFilePath is null ? rename.GetDeterministicHashCode(filePath) : rename.GetDeterministicHashCode(fastForwardMovingPictureExpertsGroupFilePath);
|
||||
}
|
||||
filePath = FilePath.Get(filePath, deterministicHashCode);
|
||||
fastForwardMovingPictureExpertsGroupUsed = fastForwardMovingPictureExpertsGroupFiles is not null && fastForwardMovingPictureExpertsGroupFiles.Count > 0;
|
||||
(minimumYearAndPathCombined, exifDirectory) = metadata.GetMetadataCollection(resultSettings, metadataSettings, filePath);
|
||||
metadataGroup = new(fastForwardMovingPictureExpertsGroupUsed, filePath, minimumYearAndPathCombined, exifDirectory, new([]));
|
||||
lock (metadataGroups)
|
||||
metadataGroups.Add(metadataGroup);
|
||||
if (fastForwardMovingPictureExpertsGroupUsed && fastForwardMovingPictureExpertsGroupFiles is not null)
|
||||
{
|
||||
foreach (string fastForwardMovingPictureExpertsGroupFile in fastForwardMovingPictureExpertsGroupFiles)
|
||||
File.Delete(fastForwardMovingPictureExpertsGroupFile);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
internal static Action<string> SetExifDirectoryCollection(IWindows windows, ResultSettings resultSettings, MetadataSettings metadataSettings, IWindowsSettings windowsSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups)
|
||||
internal static Action<string> SetExifDirectoryCollection(IWindows windows, ResultSettings resultSettings, MetadataSettings metadataSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups)
|
||||
{
|
||||
return file =>
|
||||
{
|
||||
@ -125,7 +81,7 @@ internal static class Get
|
||||
}
|
||||
else
|
||||
{
|
||||
fastForwardMovingPictureExpertsGroupFiles = windows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(windowsSettings, httpClient, filePath);
|
||||
fastForwardMovingPictureExpertsGroupFiles = windows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(resultSettings, httpClient, filePath);
|
||||
fastForwardMovingPictureExpertsGroupFilePath = fastForwardMovingPictureExpertsGroupFiles.Count == 0 ? null : FilePath.Get(resultSettings, metadataSettings, FileHolder.Get(fastForwardMovingPictureExpertsGroupFiles[0]), index: null);
|
||||
deterministicHashCode = fastForwardMovingPictureExpertsGroupFilePath is null ? windows.GetDeterministicHashCode(httpClient, filePath) : windows.GetDeterministicHashCode(httpClient, fastForwardMovingPictureExpertsGroupFilePath);
|
||||
}
|
||||
@ -145,4 +101,48 @@ internal static class Get
|
||||
};
|
||||
}
|
||||
|
||||
internal static Action<string> SetExifDirectoryCollection(IRename rename, ResultSettings resultSettings, MetadataSettings metadataSettings, IRenameSettings renameSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups)
|
||||
{
|
||||
return file =>
|
||||
{
|
||||
rename.Tick();
|
||||
ExifDirectory exifDirectory;
|
||||
MetadataGroup metadataGroup;
|
||||
DeterministicHashCode deterministicHashCode;
|
||||
FileHolder fileHolder = FileHolder.Get(file);
|
||||
bool fastForwardMovingPictureExpertsGroupUsed;
|
||||
MinimumYearAndPathCombined minimumYearAndPathCombined;
|
||||
FilePath? fastForwardMovingPictureExpertsGroupFilePath;
|
||||
ReadOnlyCollection<string>? fastForwardMovingPictureExpertsGroupFiles;
|
||||
FilePath filePath = FilePath.Get(resultSettings, metadataSettings, fileHolder, index: null);
|
||||
string key = $"{Path.Combine(fileHolder.DirectoryFullPath ?? throw new NotSupportedException(), fileHolder.NameWithoutExtension)}";
|
||||
if (distinct.Contains(key))
|
||||
throw new NotSupportedException("Turn off parallelism when sidecar files are present!");
|
||||
if (renameSettings.SkipIdFiles && filePath.Id is not null && (filePath.IsIntelligentIdFormat || filePath.SortOrder is null))
|
||||
return;
|
||||
if (filePath.Id is not null)
|
||||
{
|
||||
fastForwardMovingPictureExpertsGroupFiles = null;
|
||||
deterministicHashCode = new(null, filePath.Id, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
fastForwardMovingPictureExpertsGroupFiles = rename.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(resultSettings, filePath);
|
||||
fastForwardMovingPictureExpertsGroupFilePath = fastForwardMovingPictureExpertsGroupFiles.Count == 0 ? null : FilePath.Get(resultSettings, metadataSettings, FileHolder.Get(fastForwardMovingPictureExpertsGroupFiles[0]), index: null);
|
||||
deterministicHashCode = fastForwardMovingPictureExpertsGroupFilePath is null ? rename.GetDeterministicHashCode(filePath) : rename.GetDeterministicHashCode(fastForwardMovingPictureExpertsGroupFilePath);
|
||||
}
|
||||
filePath = FilePath.Get(filePath, deterministicHashCode);
|
||||
fastForwardMovingPictureExpertsGroupUsed = fastForwardMovingPictureExpertsGroupFiles is not null && fastForwardMovingPictureExpertsGroupFiles.Count > 0;
|
||||
(minimumYearAndPathCombined, exifDirectory) = metadata.GetMetadataCollection(resultSettings, metadataSettings, filePath);
|
||||
metadataGroup = new(fastForwardMovingPictureExpertsGroupUsed, filePath, minimumYearAndPathCombined, exifDirectory, new([]));
|
||||
lock (metadataGroups)
|
||||
metadataGroups.Add(metadataGroup);
|
||||
if (fastForwardMovingPictureExpertsGroupUsed && fastForwardMovingPictureExpertsGroupFiles is not null)
|
||||
{
|
||||
foreach (string fastForwardMovingPictureExpertsGroupFile in fastForwardMovingPictureExpertsGroupFiles)
|
||||
File.Delete(fastForwardMovingPictureExpertsGroupFile);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -72,9 +72,9 @@ public interface IMetadata
|
||||
static ReadOnlyDictionary<string, List<FileHolder>> GetKeyValuePairs(IEnumerable<NginxFileSystem> collection) =>
|
||||
Get.GetKeyValuePairs(collection);
|
||||
|
||||
Action<string> TestStatic_SetExifDirectoryCollection(IWindows windows, ResultSettings resultSettings, MetadataSettings metadataSettings, IWindowsSettings windowsSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) =>
|
||||
SetExifDirectoryCollection(windows, resultSettings, metadataSettings, windowsSettings, metadata, distinct, metadataGroups);
|
||||
static Action<string> SetExifDirectoryCollection(IWindows windows, ResultSettings resultSettings, MetadataSettings metadataSettings, IWindowsSettings windowsSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) =>
|
||||
Get.SetExifDirectoryCollection(windows, resultSettings, metadataSettings, windowsSettings, metadata, distinct, metadataGroups);
|
||||
Action<string> TestStatic_SetExifDirectoryCollection(IWindows windows, ResultSettings resultSettings, MetadataSettings metadataSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) =>
|
||||
SetExifDirectoryCollection(windows, resultSettings, metadataSettings, metadata, distinct, metadataGroups);
|
||||
static Action<string> SetExifDirectoryCollection(IWindows windows, ResultSettings resultSettings, MetadataSettings metadataSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) =>
|
||||
Get.SetExifDirectoryCollection(windows, resultSettings, metadataSettings, metadata, distinct, metadataGroups);
|
||||
|
||||
}
|
@ -9,7 +9,6 @@ public record RenameSettings(string Company,
|
||||
Dictionary<string, string?> DirectoryDictionary,
|
||||
string? FirstPassFile,
|
||||
bool ForceNewId,
|
||||
string[] IgnoreExtensions,
|
||||
bool InPlace,
|
||||
bool InPlaceMoveDirectory,
|
||||
bool InPlaceWithOriginalName,
|
||||
@ -20,9 +19,7 @@ public record RenameSettings(string Company,
|
||||
string RelativePropertyCollectionFile,
|
||||
bool RequireRootDirectoryExists,
|
||||
string[] SidecarExtensions,
|
||||
bool SkipIdFiles,
|
||||
string[] ValidImageFormatExtensions,
|
||||
string[] ValidVideoFormatExtensions) : Shared.Models.Properties.IRenameSettings
|
||||
bool SkipIdFiles) : Shared.Models.Properties.IRenameSettings
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
|
785
Rename/Rename.cs
785
Rename/Rename.cs
@ -11,7 +11,6 @@ using View_by_Distance.Metadata.Models;
|
||||
using View_by_Distance.Metadata.Models.Stateless;
|
||||
using View_by_Distance.Rename.Models;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Properties;
|
||||
using View_by_Distance.Shared.Models.Stateless;
|
||||
|
||||
namespace View_by_Distance.Rename;
|
||||
@ -35,39 +34,58 @@ public partial class Rename : IRename, IDisposable
|
||||
private ProgressBar? _ProgressBar;
|
||||
private readonly ProgressBarOptions _ProgressBarOptions;
|
||||
|
||||
public Rename(List<string> args, ILogger<Program>? logger, AppSettings appSettings, bool isSilent, IConsole console)
|
||||
{
|
||||
if (isSilent)
|
||||
{ }
|
||||
if (args is null)
|
||||
throw new NullReferenceException(nameof(args));
|
||||
if (console is null)
|
||||
throw new NullReferenceException(nameof(console));
|
||||
IRename rename = this;
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
_ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
RenameWork(logger, appSettings, rename, ticks);
|
||||
}
|
||||
|
||||
void IRename.Tick() =>
|
||||
_ProgressBar?.Tick();
|
||||
|
||||
void IRename.ConstructProgressBar(int maxTicks, string message)
|
||||
{
|
||||
_ProgressBar?.Dispose();
|
||||
_ProgressBar = new(maxTicks, message, _ProgressBarOptions);
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
_ProgressBar?.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
ReadOnlyCollection<string> IRename.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(IRenameSettings renameSettings, FilePath filePath)
|
||||
void IRename.ConstructProgressBar(int maxTicks, string message)
|
||||
{
|
||||
_ProgressBar?.Dispose();
|
||||
_ProgressBar = new(maxTicks, message, _ProgressBarOptions);
|
||||
}
|
||||
|
||||
DeterministicHashCode IRename.GetDeterministicHashCode(FilePath filePath)
|
||||
{
|
||||
DeterministicHashCode result;
|
||||
int? id;
|
||||
int? width;
|
||||
int? height;
|
||||
try
|
||||
{
|
||||
#pragma warning disable CA1416
|
||||
using Image image = Image.FromFile(filePath.FullName);
|
||||
width = image.Width;
|
||||
height = image.Height;
|
||||
using Bitmap bitmap = new(image);
|
||||
Rectangle rectangle = new(0, 0, image.Width, image.Height);
|
||||
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||
IntPtr intPtr = bitmapData.Scan0;
|
||||
int length = bitmapData.Stride * bitmap.Height;
|
||||
byte[] bytes = new byte[length];
|
||||
Marshal.Copy(intPtr, bytes, 0, length);
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
#pragma warning restore CA1416
|
||||
id = IId.GetDeterministicHashCode(bytes);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
id = null;
|
||||
width = null;
|
||||
height = null;
|
||||
}
|
||||
result = new(height, id, width);
|
||||
return result;
|
||||
}
|
||||
|
||||
ReadOnlyCollection<string> IRename.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(ResultSettings resultSettings, FilePath filePath)
|
||||
{
|
||||
List<string> results = [];
|
||||
bool isValidVideoFormatExtensions = renameSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered);
|
||||
bool isValidVideoFormatExtensions = resultSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered);
|
||||
if (isValidVideoFormatExtensions)
|
||||
{
|
||||
bool check;
|
||||
@ -97,40 +115,241 @@ public partial class Rename : IRename, IDisposable
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
#pragma warning disable CA1416
|
||||
|
||||
DeterministicHashCode IRename.GetDeterministicHashCode(FilePath filePath)
|
||||
public Rename(List<string> args, ILogger<Program>? logger, AppSettings appSettings, bool isSilent, IConsole console)
|
||||
{
|
||||
DeterministicHashCode result;
|
||||
int? id;
|
||||
int? width;
|
||||
int? height;
|
||||
try
|
||||
{
|
||||
using Image image = Image.FromFile(filePath.FullName);
|
||||
width = image.Width;
|
||||
height = image.Height;
|
||||
using Bitmap bitmap = new(image);
|
||||
Rectangle rectangle = new(0, 0, image.Width, image.Height);
|
||||
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||
IntPtr intPtr = bitmapData.Scan0;
|
||||
int length = bitmapData.Stride * bitmap.Height;
|
||||
byte[] bytes = new byte[length];
|
||||
Marshal.Copy(intPtr, bytes, 0, length);
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
id = IId.GetDeterministicHashCode(bytes);
|
||||
if (isSilent)
|
||||
{ }
|
||||
if (args is null)
|
||||
throw new NullReferenceException(nameof(args));
|
||||
if (console is null)
|
||||
throw new NullReferenceException(nameof(console));
|
||||
IRename rename = this;
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
_ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
RenameWork(logger, appSettings, rename, ticks);
|
||||
}
|
||||
|
||||
private void RenameWork(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks)
|
||||
{
|
||||
ReadOnlyCollection<int> ids = GetIds(appSettings.RenameSettings);
|
||||
string sourceDirectory = Path.GetFullPath(appSettings.ResultSettings.RootDirectory);
|
||||
if (!Directory.Exists(sourceDirectory))
|
||||
_ = Directory.CreateDirectory(sourceDirectory);
|
||||
logger?.LogInformation("{Ticks} {RootDirectory}", ticks, sourceDirectory);
|
||||
ReadOnlyCollection<string> files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories).ToArray().AsReadOnly();
|
||||
if (files.Count > 0)
|
||||
_ = IPath.DeleteEmptyDirectories(appSettings.ResultSettings.RootDirectory);
|
||||
ReadOnlyCollection<Record> recordCollection = GetRecordCollection(logger, appSettings, rename, ticks, ids, sourceDirectory, files);
|
||||
SaveIdentifiersToDisk(ticks, appSettings, recordCollection);
|
||||
if (appSettings.RenameSettings.InPlace || appSettings.RenameSettings.InPlaceWithOriginalName)
|
||||
{
|
||||
if (recordCollection.Count > 0)
|
||||
recordCollection = new([]);
|
||||
string aMetadataSingletonDirectory = IResult.GetResultsGroupDirectory(appSettings.ResultSettings, nameof(A_Metadata));
|
||||
_ = IPath.DeleteEmptyDirectories(aMetadataSingletonDirectory);
|
||||
}
|
||||
if (!appSettings.RenameSettings.OnlySaveIdentifiersToDisk)
|
||||
{
|
||||
DirectoryInfo directoryInfo = new(sourceDirectory);
|
||||
ReadOnlyCollection<ToDo> toDoCollection = GetToDoCollection(appSettings, directoryInfo, ids, files, recordCollection);
|
||||
ReadOnlyCollection<string> lines = RenameFilesInDirectories(appSettings.RenameSettings, rename, toDoCollection);
|
||||
if (lines.Count != 0)
|
||||
{
|
||||
File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines);
|
||||
_ = IPath.DeleteEmptyDirectories(directoryInfo.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<int> GetIds(RenameSettings renameSettings)
|
||||
{
|
||||
ReadOnlyCollection<int> results;
|
||||
string? propertyCollectionFile = string.IsNullOrEmpty(renameSettings.RelativePropertyCollectionFile) ? null : renameSettings.RelativePropertyCollectionFile;
|
||||
string? json = !File.Exists(propertyCollectionFile) ? null : File.ReadAllText(propertyCollectionFile);
|
||||
Identifier[]? identifiers = json is null ? null : JsonSerializer.Deserialize(json, IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
|
||||
if (identifiers is null && !string.IsNullOrEmpty(renameSettings.RelativePropertyCollectionFile))
|
||||
throw new Exception($"Invalid {nameof(renameSettings.RelativePropertyCollectionFile)}");
|
||||
results = identifiers is null ? new([]) : new((from l in identifiers select l.Id).ToArray());
|
||||
return results;
|
||||
}
|
||||
|
||||
private ReadOnlyCollection<Record> GetRecordCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks, ReadOnlyCollection<int> ids, string sourceDirectory, ReadOnlyCollection<string> files)
|
||||
{
|
||||
ReadOnlyCollection<Record> results;
|
||||
List<FirstPass> collection;
|
||||
string? checkFile = string.IsNullOrEmpty(appSettings.RenameSettings.FirstPassFile) ? null : Path.Combine(sourceDirectory, appSettings.RenameSettings.FirstPassFile);
|
||||
if (string.IsNullOrEmpty(checkFile) || !File.Exists(checkFile))
|
||||
collection = GetRecordCollection(logger, appSettings, rename, ticks, ids, sourceDirectory, files, checkFile);
|
||||
else
|
||||
{
|
||||
string json = File.ReadAllText(checkFile);
|
||||
collection = JsonSerializer.Deserialize(json, FirstPassCollectionSourceGenerationContext.Default.ListFirstPass) ?? throw new Exception();
|
||||
}
|
||||
if (appSettings.RenameSettings.JustMediaDate)
|
||||
results = new([]);
|
||||
else
|
||||
results = GetRecordCollection(appSettings, collection);
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<FirstPass> GetRecordCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks, ReadOnlyCollection<int> ids, string sourceDirectory, ReadOnlyCollection<string> files, string? checkFile)
|
||||
{
|
||||
List<FirstPass> results;
|
||||
FirstPass firstPass;
|
||||
A_Metadata metadata = new(appSettings.ResultSettings, appSettings.MetadataSettings);
|
||||
int appSettingsMaxDegreeOfParallelism = appSettings.RenameSettings.MaxDegreeOfParallelism;
|
||||
int filesCount = appSettingsMaxDegreeOfParallelism == 1 ? files.Count : 123000;
|
||||
rename.ConstructProgressBar(filesCount, "EnumerateFiles load");
|
||||
if (appSettingsMaxDegreeOfParallelism == 1)
|
||||
{
|
||||
ReadOnlyDictionary<string, List<FileHolder>> keyValuePairs = IMetadata.GetKeyValuePairs(files);
|
||||
results = GetFirstPassCollection(logger, appSettings, rename, ticks, ids, metadata, keyValuePairs);
|
||||
}
|
||||
else
|
||||
{
|
||||
results = [];
|
||||
List<string> distinct = [];
|
||||
List<MetadataGroup> metadataGroups = [];
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = appSettingsMaxDegreeOfParallelism };
|
||||
files.AsParallel().ForAll(IMetadata.SetExifDirectoryCollection(rename, appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.RenameSettings, metadata, distinct, metadataGroups));
|
||||
Thread.Sleep(500);
|
||||
foreach (MetadataGroup metadataGroup in metadataGroups)
|
||||
{
|
||||
if (metadataGroup.FastForwardMovingPictureExpertsGroupUsed || !appSettings.RenameSettings.InPlaceMoveDirectory || !appSettings.ResultSettings.ValidVideoFormatExtensions.Contains(metadataGroup.FilePath.ExtensionLowered))
|
||||
firstPass = new(metadataGroup.ExifDirectory, metadataGroup.FastForwardMovingPictureExpertsGroupUsed, metadataGroup.MinimumYearAndPathCombined, metadataGroup.SidecarFiles.ToArray());
|
||||
else
|
||||
firstPass = new(metadataGroup.ExifDirectory, FastForwardMovingPictureExpertsGroupUsed: true, metadataGroup.MinimumYearAndPathCombined, metadataGroup.SidecarFiles.ToArray());
|
||||
results.Add(firstPass);
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(checkFile))
|
||||
{
|
||||
string json = JsonSerializer.Serialize(results, FirstPassCollectionSourceGenerationContext.Default.ListFirstPass);
|
||||
File.WriteAllText(Path.Combine(sourceDirectory, $"{ticks}.json"), json);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<FirstPass> GetFirstPassCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks, ReadOnlyCollection<int> ids, A_Metadata metadata, ReadOnlyDictionary<string, List<FileHolder>> keyValuePairs)
|
||||
{
|
||||
List<FirstPass> results = [];
|
||||
int index = -1;
|
||||
TimeSpan timeSpan;
|
||||
foreach (KeyValuePair<string, List<FileHolder>> keyValuePair in keyValuePairs)
|
||||
{
|
||||
index += 1;
|
||||
rename.Tick();
|
||||
if (keyValuePair.Value.Count > 1 && !appSettings.RenameSettings.ForceNewId)
|
||||
{
|
||||
if (appSettings.RenameSettings.InPlaceMoveDirectory)
|
||||
continue;
|
||||
throw new NotSupportedException($"When sidecar files are present {nameof(appSettings.RenameSettings.ForceNewId)} must be true!");
|
||||
}
|
||||
if (keyValuePair.Value.Count > 2)
|
||||
throw new NotSupportedException("Too many sidecar files!");
|
||||
SetFirstPassCollection(logger, appSettings, rename, ids, metadata, index, keyValuePair, results);
|
||||
timeSpan = new(DateTime.Now.Ticks - ticks);
|
||||
if (timeSpan.TotalMilliseconds > appSettings.RenameSettings.MaxMilliSecondsPerCall)
|
||||
break;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private void SetFirstPassCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, ReadOnlyCollection<int> ids, A_Metadata metadata, int index, KeyValuePair<string, List<FileHolder>> keyValuePair, List<FirstPass> results)
|
||||
{
|
||||
FilePath filePath;
|
||||
FirstPass firstPass;
|
||||
string directoryName;
|
||||
ExifDirectory exifDirectory;
|
||||
List<FileHolder> sidecarFiles;
|
||||
DeterministicHashCode deterministicHashCode;
|
||||
bool fastForwardMovingPictureExpertsGroupUsed;
|
||||
MinimumYearAndPathCombined minimumYearAndPathCombined;
|
||||
FilePath? fastForwardMovingPictureExpertsGroupFilePath;
|
||||
ReadOnlyCollection<string>? fastForwardMovingPictureExpertsGroupFiles;
|
||||
foreach (FileHolder fileHolder in keyValuePair.Value)
|
||||
{
|
||||
if (appSettings.RenameSettings.SidecarExtensions.Contains(fileHolder.ExtensionLowered))
|
||||
continue;
|
||||
if (appSettings.ResultSettings.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
|
||||
continue;
|
||||
filePath = FilePath.Get(appSettings.ResultSettings, appSettings.MetadataSettings, fileHolder, index);
|
||||
if (appSettings.RenameSettings.SkipIdFiles && filePath.Id is not null && (filePath.IsIntelligentIdFormat || filePath.SortOrder is not null))
|
||||
continue;
|
||||
if (!appSettings.RenameSettings.ForceNewId && filePath.Id is not null)
|
||||
{
|
||||
fastForwardMovingPictureExpertsGroupFiles = null;
|
||||
deterministicHashCode = new(null, filePath.Id, null);
|
||||
directoryName = Path.GetFileName(filePath.DirectoryFullPath);
|
||||
if (appSettings.RenameSettings.InPlaceWithOriginalName || (appSettings.RenameSettings.InPlace && directoryName.EndsWith(filePath.Id.Value.ToString())))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
fastForwardMovingPictureExpertsGroupFiles = rename.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(appSettings.ResultSettings, filePath);
|
||||
fastForwardMovingPictureExpertsGroupFilePath = fastForwardMovingPictureExpertsGroupFiles.Count == 0 ? null : FilePath.Get(appSettings.ResultSettings, appSettings.MetadataSettings, FileHolder.Get(fastForwardMovingPictureExpertsGroupFiles[0]), index);
|
||||
deterministicHashCode = fastForwardMovingPictureExpertsGroupFilePath is null ? rename.GetDeterministicHashCode(filePath) : rename.GetDeterministicHashCode(fastForwardMovingPictureExpertsGroupFilePath);
|
||||
}
|
||||
sidecarFiles = [];
|
||||
filePath = FilePath.Get(filePath, deterministicHashCode);
|
||||
for (int i = 0; i < keyValuePair.Value.Count; i++)
|
||||
{
|
||||
if (appSettings.RenameSettings.JustMediaDate && filePath.HasDateTimeOriginal is not null && filePath.HasDateTimeOriginal.Value)
|
||||
JustMediaDate(logger, appSettings, metadata, filePath);
|
||||
if (keyValuePair.Value[i].ExtensionLowered == fileHolder.ExtensionLowered)
|
||||
continue;
|
||||
sidecarFiles.Add(keyValuePair.Value[i]);
|
||||
}
|
||||
try
|
||||
{ (minimumYearAndPathCombined, exifDirectory) = metadata.GetMetadataCollection(appSettings.ResultSettings, appSettings.MetadataSettings, filePath); }
|
||||
catch (Exception)
|
||||
{
|
||||
id = null;
|
||||
width = null;
|
||||
height = null;
|
||||
logger?.LogWarning("<{filePath}>", filePath.FullName);
|
||||
continue;
|
||||
}
|
||||
fastForwardMovingPictureExpertsGroupUsed = fastForwardMovingPictureExpertsGroupFiles is not null && fastForwardMovingPictureExpertsGroupFiles.Count > 0;
|
||||
if (fastForwardMovingPictureExpertsGroupUsed && fastForwardMovingPictureExpertsGroupFiles is not null)
|
||||
{
|
||||
foreach (string fastForwardMovingPictureExpertsGroupFile in fastForwardMovingPictureExpertsGroupFiles)
|
||||
File.Delete(fastForwardMovingPictureExpertsGroupFile);
|
||||
}
|
||||
if (appSettings.RenameSettings.InPlace || appSettings.RenameSettings.InPlaceWithOriginalName)
|
||||
NonParallelismAndInPlace(appSettings, rename, ids, exifDirectory, minimumYearAndPathCombined, fastForwardMovingPictureExpertsGroupUsed, sidecarFiles.ToArray());
|
||||
if (!fastForwardMovingPictureExpertsGroupUsed && appSettings.RenameSettings.InPlaceMoveDirectory && appSettings.ResultSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered))
|
||||
fastForwardMovingPictureExpertsGroupUsed = true;
|
||||
firstPass = new(exifDirectory, fastForwardMovingPictureExpertsGroupUsed, minimumYearAndPathCombined, sidecarFiles.ToArray());
|
||||
results.Add(firstPass);
|
||||
}
|
||||
result = new(height, id, width);
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning restore CA1416
|
||||
private void JustMediaDate(ILogger<Program>? logger, AppSettings appSettings, A_Metadata metadata, FilePath filePath)
|
||||
{
|
||||
ExifDirectory? exifDirectory;
|
||||
MinimumYearAndPathCombined? minimumYearAndPathCombined;
|
||||
try
|
||||
{ (minimumYearAndPathCombined, exifDirectory) = metadata.GetMetadataCollection(appSettings.ResultSettings, appSettings.MetadataSettings, filePath); }
|
||||
catch (Exception)
|
||||
{
|
||||
exifDirectory = null;
|
||||
minimumYearAndPathCombined = null;
|
||||
logger?.LogWarning("<{filePath}>", filePath.FullName);
|
||||
}
|
||||
if (exifDirectory is null || minimumYearAndPathCombined is null)
|
||||
logger?.LogWarning("<{filePath}>", filePath.FullName);
|
||||
else
|
||||
{
|
||||
DateTime? dateTime = IDate.GetDateTimeOriginal(exifDirectory);
|
||||
if (dateTime is null)
|
||||
logger?.LogWarning("<{filePath}>", filePath.FullName);
|
||||
else
|
||||
{
|
||||
File.SetCreationTime(filePath.FullName, dateTime.Value);
|
||||
Thread.Sleep(500);
|
||||
File.SetLastWriteTime(filePath.FullName, dateTime.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void NonParallelismAndInPlace(AppSettings appSettings, IRename rename, ReadOnlyCollection<int> ids, ExifDirectory exifDirectory, MinimumYearAndPathCombined minimumYearAndPathCombined, bool fastForwardMovingPictureExpertsGroupUsed, FileHolder[] sidecarFiles)
|
||||
{
|
||||
@ -189,126 +408,6 @@ public partial class Rename : IRename, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
private void JustMediaDate(ILogger<Program>? logger, AppSettings appSettings, A_Metadata metadata, FilePath filePath)
|
||||
{
|
||||
ExifDirectory? exifDirectory;
|
||||
MinimumYearAndPathCombined? minimumYearAndPathCombined;
|
||||
try
|
||||
{ (minimumYearAndPathCombined, exifDirectory) = metadata.GetMetadataCollection(appSettings.ResultSettings, appSettings.MetadataSettings, filePath); }
|
||||
catch (Exception)
|
||||
{
|
||||
exifDirectory = null;
|
||||
minimumYearAndPathCombined = null;
|
||||
logger?.LogWarning("<{filePath}>", filePath.FullName);
|
||||
}
|
||||
if (exifDirectory is null || minimumYearAndPathCombined is null)
|
||||
logger?.LogWarning("<{filePath}>", filePath.FullName);
|
||||
else
|
||||
{
|
||||
DateTime? dateTime = IDate.GetDateTimeOriginal(exifDirectory);
|
||||
if (dateTime is null)
|
||||
logger?.LogWarning("<{filePath}>", filePath.FullName);
|
||||
else
|
||||
{
|
||||
File.SetCreationTime(filePath.FullName, dateTime.Value);
|
||||
Thread.Sleep(500);
|
||||
File.SetLastWriteTime(filePath.FullName, dateTime.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetFirstPassCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, ReadOnlyCollection<int> ids, A_Metadata metadata, int index, KeyValuePair<string, List<FileHolder>> keyValuePair, List<FirstPass> results)
|
||||
{
|
||||
FilePath filePath;
|
||||
FirstPass firstPass;
|
||||
string directoryName;
|
||||
ExifDirectory exifDirectory;
|
||||
List<FileHolder> sidecarFiles;
|
||||
DeterministicHashCode deterministicHashCode;
|
||||
bool fastForwardMovingPictureExpertsGroupUsed;
|
||||
MinimumYearAndPathCombined minimumYearAndPathCombined;
|
||||
FilePath? fastForwardMovingPictureExpertsGroupFilePath;
|
||||
ReadOnlyCollection<string>? fastForwardMovingPictureExpertsGroupFiles;
|
||||
foreach (FileHolder fileHolder in keyValuePair.Value)
|
||||
{
|
||||
if (appSettings.RenameSettings.SidecarExtensions.Contains(fileHolder.ExtensionLowered))
|
||||
continue;
|
||||
if (appSettings.RenameSettings.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
|
||||
continue;
|
||||
filePath = FilePath.Get(appSettings.ResultSettings, appSettings.MetadataSettings, fileHolder, index);
|
||||
if (appSettings.RenameSettings.SkipIdFiles && filePath.Id is not null && (filePath.IsIntelligentIdFormat || filePath.SortOrder is not null))
|
||||
continue;
|
||||
if (!appSettings.RenameSettings.ForceNewId && filePath.Id is not null)
|
||||
{
|
||||
fastForwardMovingPictureExpertsGroupFiles = null;
|
||||
deterministicHashCode = new(null, filePath.Id, null);
|
||||
directoryName = Path.GetFileName(filePath.DirectoryFullPath);
|
||||
if (appSettings.RenameSettings.InPlaceWithOriginalName || (appSettings.RenameSettings.InPlace && directoryName.EndsWith(filePath.Id.Value.ToString())))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
fastForwardMovingPictureExpertsGroupFiles = rename.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(appSettings.RenameSettings, filePath);
|
||||
fastForwardMovingPictureExpertsGroupFilePath = fastForwardMovingPictureExpertsGroupFiles.Count == 0 ? null : FilePath.Get(appSettings.ResultSettings, appSettings.MetadataSettings, FileHolder.Get(fastForwardMovingPictureExpertsGroupFiles[0]), index);
|
||||
deterministicHashCode = fastForwardMovingPictureExpertsGroupFilePath is null ? rename.GetDeterministicHashCode(filePath) : rename.GetDeterministicHashCode(fastForwardMovingPictureExpertsGroupFilePath);
|
||||
}
|
||||
sidecarFiles = [];
|
||||
filePath = FilePath.Get(filePath, deterministicHashCode);
|
||||
for (int i = 0; i < keyValuePair.Value.Count; i++)
|
||||
{
|
||||
if (appSettings.RenameSettings.JustMediaDate && filePath.HasDateTimeOriginal is not null && filePath.HasDateTimeOriginal.Value)
|
||||
JustMediaDate(logger, appSettings, metadata, filePath);
|
||||
if (keyValuePair.Value[i].ExtensionLowered == fileHolder.ExtensionLowered)
|
||||
continue;
|
||||
sidecarFiles.Add(keyValuePair.Value[i]);
|
||||
}
|
||||
try
|
||||
{ (minimumYearAndPathCombined, exifDirectory) = metadata.GetMetadataCollection(appSettings.ResultSettings, appSettings.MetadataSettings, filePath); }
|
||||
catch (Exception)
|
||||
{
|
||||
logger?.LogWarning("<{filePath}>", filePath.FullName);
|
||||
continue;
|
||||
}
|
||||
fastForwardMovingPictureExpertsGroupUsed = fastForwardMovingPictureExpertsGroupFiles is not null && fastForwardMovingPictureExpertsGroupFiles.Count > 0;
|
||||
if (fastForwardMovingPictureExpertsGroupUsed && fastForwardMovingPictureExpertsGroupFiles is not null)
|
||||
{
|
||||
foreach (string fastForwardMovingPictureExpertsGroupFile in fastForwardMovingPictureExpertsGroupFiles)
|
||||
File.Delete(fastForwardMovingPictureExpertsGroupFile);
|
||||
}
|
||||
if (appSettings.RenameSettings.InPlace || appSettings.RenameSettings.InPlaceWithOriginalName)
|
||||
NonParallelismAndInPlace(appSettings, rename, ids, exifDirectory, minimumYearAndPathCombined, fastForwardMovingPictureExpertsGroupUsed, sidecarFiles.ToArray());
|
||||
if (!fastForwardMovingPictureExpertsGroupUsed && appSettings.RenameSettings.InPlaceMoveDirectory && appSettings.RenameSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered))
|
||||
fastForwardMovingPictureExpertsGroupUsed = true;
|
||||
firstPass = new(exifDirectory, fastForwardMovingPictureExpertsGroupUsed, minimumYearAndPathCombined, sidecarFiles.ToArray());
|
||||
results.Add(firstPass);
|
||||
}
|
||||
}
|
||||
|
||||
private List<FirstPass> GetFirstPassCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks, ReadOnlyCollection<int> ids, A_Metadata metadata, ReadOnlyDictionary<string, List<FileHolder>> keyValuePairs)
|
||||
{
|
||||
List<FirstPass> results = [];
|
||||
int index = -1;
|
||||
TimeSpan timeSpan;
|
||||
foreach (KeyValuePair<string, List<FileHolder>> keyValuePair in keyValuePairs)
|
||||
{
|
||||
index += 1;
|
||||
rename.Tick();
|
||||
if (keyValuePair.Value.Count > 1 && !appSettings.RenameSettings.ForceNewId)
|
||||
{
|
||||
if (appSettings.RenameSettings.InPlaceMoveDirectory)
|
||||
continue;
|
||||
throw new NotSupportedException($"When sidecar files are present {nameof(appSettings.RenameSettings.ForceNewId)} must be true!");
|
||||
}
|
||||
if (keyValuePair.Value.Count > 2)
|
||||
throw new NotSupportedException("Too many sidecar files!");
|
||||
SetFirstPassCollection(logger, appSettings, rename, ids, metadata, index, keyValuePair, results);
|
||||
timeSpan = new(DateTime.Now.Ticks - ticks);
|
||||
if (timeSpan.TotalMilliseconds > appSettings.RenameSettings.MaxMilliSecondsPerCall)
|
||||
break;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<Record> GetRecordCollection(AppSettings appSettings, List<FirstPass> collection)
|
||||
{
|
||||
List<Record> results = [];
|
||||
@ -336,172 +435,22 @@ public partial class Rename : IRename, IDisposable
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private List<FirstPass> GetRecordCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks, ReadOnlyCollection<int> ids, string sourceDirectory, ReadOnlyCollection<string> files, string? checkFile)
|
||||
{
|
||||
List<FirstPass> results;
|
||||
FirstPass firstPass;
|
||||
A_Metadata metadata = new(appSettings.ResultSettings, appSettings.MetadataSettings);
|
||||
int appSettingsMaxDegreeOfParallelism = appSettings.RenameSettings.MaxDegreeOfParallelism;
|
||||
int filesCount = appSettingsMaxDegreeOfParallelism == 1 ? files.Count : 123000;
|
||||
rename.ConstructProgressBar(filesCount, "EnumerateFiles load");
|
||||
if (appSettingsMaxDegreeOfParallelism == 1)
|
||||
{
|
||||
ReadOnlyDictionary<string, List<FileHolder>> keyValuePairs = IMetadata.GetKeyValuePairs(files);
|
||||
results = GetFirstPassCollection(logger, appSettings, rename, ticks, ids, metadata, keyValuePairs);
|
||||
}
|
||||
else
|
||||
{
|
||||
results = [];
|
||||
List<string> distinct = [];
|
||||
List<MetadataGroup> metadataGroups = [];
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = appSettingsMaxDegreeOfParallelism };
|
||||
files.AsParallel().ForAll(IMetadata.SetExifDirectoryCollection(rename, appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.RenameSettings, metadata, distinct, metadataGroups));
|
||||
Thread.Sleep(500);
|
||||
foreach (MetadataGroup metadataGroup in metadataGroups)
|
||||
{
|
||||
if (metadataGroup.FastForwardMovingPictureExpertsGroupUsed || !appSettings.RenameSettings.InPlaceMoveDirectory || !appSettings.RenameSettings.ValidVideoFormatExtensions.Contains(metadataGroup.FilePath.ExtensionLowered))
|
||||
firstPass = new(metadataGroup.ExifDirectory, metadataGroup.FastForwardMovingPictureExpertsGroupUsed, metadataGroup.MinimumYearAndPathCombined, metadataGroup.SidecarFiles.ToArray());
|
||||
else
|
||||
firstPass = new(metadataGroup.ExifDirectory, FastForwardMovingPictureExpertsGroupUsed: true, metadataGroup.MinimumYearAndPathCombined, metadataGroup.SidecarFiles.ToArray());
|
||||
results.Add(firstPass);
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(checkFile))
|
||||
{
|
||||
string json = JsonSerializer.Serialize(results, FirstPassCollectionSourceGenerationContext.Default.ListFirstPass);
|
||||
File.WriteAllText(Path.Combine(sourceDirectory, $"{ticks}.json"), json);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private ReadOnlyCollection<Record> GetRecordCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks, ReadOnlyCollection<int> ids, string sourceDirectory, ReadOnlyCollection<string> files)
|
||||
{
|
||||
ReadOnlyCollection<Record> results;
|
||||
List<FirstPass> collection;
|
||||
string? checkFile = string.IsNullOrEmpty(appSettings.RenameSettings.FirstPassFile) ? null : Path.Combine(sourceDirectory, appSettings.RenameSettings.FirstPassFile);
|
||||
if (string.IsNullOrEmpty(checkFile) || !File.Exists(checkFile))
|
||||
collection = GetRecordCollection(logger, appSettings, rename, ticks, ids, sourceDirectory, files, checkFile);
|
||||
else
|
||||
{
|
||||
string json = File.ReadAllText(checkFile);
|
||||
collection = JsonSerializer.Deserialize(json, FirstPassCollectionSourceGenerationContext.Default.ListFirstPass) ?? throw new Exception();
|
||||
}
|
||||
if (appSettings.RenameSettings.JustMediaDate)
|
||||
results = new([]);
|
||||
else
|
||||
results = GetRecordCollection(appSettings, collection);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void VerifyIntMinValueLength(MetadataSettings metadataSettings, ReadOnlyCollection<Record> recordCollection)
|
||||
private static void SaveIdentifiersToDisk(long ticks, AppSettings appSettings, ReadOnlyCollection<Record> recordCollection)
|
||||
{
|
||||
string paddedId;
|
||||
Identifier identifier;
|
||||
List<Identifier> identifiers = [];
|
||||
string aMetadataCollectionDirectory = IResult.GetResultsDateGroupDirectory(appSettings.ResultSettings, nameof(A_Metadata), appSettings.ResultSettings.ResultCollection);
|
||||
foreach (Record record in recordCollection)
|
||||
{
|
||||
if (record.ExifDirectory.FilePath.Id is null)
|
||||
continue;
|
||||
if (metadataSettings.IntMinValueLength < record.ExifDirectory.FilePath.Id.Value.ToString().Length)
|
||||
throw new NotSupportedException();
|
||||
paddedId = IId.GetPaddedId(appSettings.ResultSettings, appSettings.MetadataSettings, record.ExifDirectory.FilePath.Id.Value, record.HasIgnoreKeyword, record.HasDateTimeOriginal, index: null);
|
||||
identifier = new([], record.HasDateTimeOriginal, record.ExifDirectory.FilePath.Id.Value, record.ExifDirectory.FilePath.Length, paddedId, record.DateTime.Ticks);
|
||||
identifiers.Add(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetTFW(Record record, bool? isWrongYear) =>
|
||||
string.Concat(record.HasDateTimeOriginal ? "T" : "F", isWrongYear is not null && isWrongYear.Value ? "W" : record.FastForwardMovingPictureExpertsGroupUsed ? "V" : "I");
|
||||
|
||||
private static string GetDirectoryName(string year, string tfw, string prefix, string? splat, int seasonValue, string seasonName, string makerSplit) =>
|
||||
splat is null ? $"{prefix}{year} {tfw}{year}.{seasonValue} {seasonName}{makerSplit}" : $"{prefix}{year} {tfw}{year}{splat}";
|
||||
|
||||
private static string? GetCheckDirectory(AppSettings appSettings, DirectoryInfo directoryInfo, Record record, ReadOnlyCollection<int> ids, bool multipleDirectoriesWithFiles, string paddedId)
|
||||
{
|
||||
string? result;
|
||||
string year = record.DateTime.Year.ToString();
|
||||
string checkDirectoryName = Path.GetFileName(record.ExifDirectory.FilePath.DirectoryFullPath);
|
||||
if (multipleDirectoriesWithFiles && !checkDirectoryName.Contains(year))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
(bool? isWrongYear, string[] years) = IDate.IsWrongYear(directoryInfo, record.ExifDirectory.FilePath, record.ExifDirectory);
|
||||
if (appSettings.RenameSettings.InPlaceMoveDirectory && !record.ExifDirectory.FilePath.FileNameFirstSegment.Contains(paddedId))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
if (record.ExifDirectory.FilePath.FullName[..2] != directoryInfo.FullName[..2])
|
||||
isWrongYear = null;
|
||||
string directoryName;
|
||||
string tfw = GetTFW(record, isWrongYear);
|
||||
string? maker = IMetadata.GetMaker(record.ExifDirectory);
|
||||
string rootDirectory = appSettings.ResultSettings.RootDirectory;
|
||||
string[] segments = checkDirectoryName.Split(years, StringSplitOptions.None);
|
||||
(int seasonValue, string seasonName) = IDate.GetSeason(record.DateTime.DayOfYear);
|
||||
string? splat = checkDirectoryName.Length > 3 && checkDirectoryName[^3..][1] == '!' ? checkDirectoryName[^3..] : null;
|
||||
string contains = record.ExifDirectory.FilePath.Id is null || ids.Contains(record.ExifDirectory.FilePath.Id.Value) ? "_ Exists _" : "_ New-Destination _";
|
||||
string makerSplit = string.IsNullOrEmpty(maker) ? string.IsNullOrEmpty(appSettings.RenameSettings.DefaultMaker) ? string.Empty : appSettings.RenameSettings.DefaultMaker : $" {maker.Split(' ')[0]}";
|
||||
if (!string.IsNullOrEmpty(splat) || isWrongYear is null || isWrongYear.Value || appSettings.RenameSettings.DirectoryDictionary.Count < 2)
|
||||
directoryName = GetDirectoryName(year, tfw, segments[0], splat, seasonValue, seasonName, makerSplit);
|
||||
else
|
||||
{
|
||||
directoryName = record.DateTime.ToString("yyyy-MM-dd");
|
||||
if (appSettings.RenameSettings.DirectoryDictionary.TryGetValue(directoryName, out string? value) && !string.IsNullOrEmpty(value))
|
||||
directoryName = value;
|
||||
}
|
||||
result = Path.GetFullPath(Path.Combine(rootDirectory, contains, directoryName));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<ToDo> GetSidecarFiles(AppSettings appSettings, Record record, List<string> distinct, string checkDirectory, string paddedId)
|
||||
{
|
||||
List<ToDo> results = [];
|
||||
ToDo toDo;
|
||||
string checkFile;
|
||||
FilePath filePath;
|
||||
string checkFileExtension;
|
||||
foreach (FileHolder fileHolder in record.SidecarFiles)
|
||||
{
|
||||
checkFileExtension = fileHolder.ExtensionLowered;
|
||||
filePath = FilePath.Get(appSettings.ResultSettings, appSettings.MetadataSettings, fileHolder, index: null);
|
||||
checkFile = Path.Combine(checkDirectory, $"{paddedId}{checkFileExtension}");
|
||||
if (checkFile == filePath.FullName)
|
||||
continue;
|
||||
if (File.Exists(checkFile))
|
||||
{
|
||||
checkFile = string.Concat(checkFile, ".del");
|
||||
if (File.Exists(checkFile))
|
||||
continue;
|
||||
}
|
||||
if (distinct.Contains(checkFile))
|
||||
continue;
|
||||
distinct.Add(checkFile);
|
||||
toDo = new(Directory: checkDirectory,
|
||||
FileInfo: new(filePath.FullName),
|
||||
File: checkFile,
|
||||
JsonFile: false);
|
||||
results.Add(toDo);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static bool? GetDirectoryCheck(ResultSettings resultSettings)
|
||||
{
|
||||
bool? result = null;
|
||||
IEnumerable<string> files;
|
||||
string[] directories = Directory.GetDirectories(resultSettings.RootDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||
foreach (string directory in directories)
|
||||
{
|
||||
files = Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories);
|
||||
foreach (string _ in files)
|
||||
{
|
||||
if (result is null)
|
||||
result = false;
|
||||
else if (result.Value)
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
if (result is not null && result.Value)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
string json = JsonSerializer.Serialize(identifiers.OrderBy(l => l.PaddedId).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
|
||||
_ = IPath.WriteAllText(Path.Combine(aMetadataCollectionDirectory, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<ToDo> GetToDoCollection(AppSettings appSettings, DirectoryInfo directoryInfo, ReadOnlyCollection<int> ids, ReadOnlyCollection<string> files, ReadOnlyCollection<Record> recordCollection)
|
||||
@ -589,17 +538,114 @@ public partial class Rename : IRename, IDisposable
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private static void VerifyDirectories(ReadOnlyCollection<ToDo> toDoCollection)
|
||||
private static bool? GetDirectoryCheck(ResultSettings resultSettings)
|
||||
{
|
||||
List<string> distinct = [];
|
||||
foreach (ToDo toDo in toDoCollection)
|
||||
bool? result = null;
|
||||
IEnumerable<string> files;
|
||||
string[] directories = Directory.GetDirectories(resultSettings.RootDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||
foreach (string directory in directories)
|
||||
{
|
||||
if (toDo.Directory is null || distinct.Contains(toDo.Directory))
|
||||
continue;
|
||||
if (!Directory.Exists(toDo.Directory))
|
||||
_ = Directory.CreateDirectory(toDo.Directory);
|
||||
distinct.Add(toDo.Directory);
|
||||
files = Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories);
|
||||
foreach (string _ in files)
|
||||
{
|
||||
if (result is null)
|
||||
result = false;
|
||||
else if (result.Value)
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
if (result is not null && result.Value)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void VerifyIntMinValueLength(MetadataSettings metadataSettings, ReadOnlyCollection<Record> recordCollection)
|
||||
{
|
||||
foreach (Record record in recordCollection)
|
||||
{
|
||||
if (record.ExifDirectory.FilePath.Id is null)
|
||||
continue;
|
||||
if (metadataSettings.IntMinValueLength < record.ExifDirectory.FilePath.Id.Value.ToString().Length)
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
private static string? GetCheckDirectory(AppSettings appSettings, DirectoryInfo directoryInfo, Record record, ReadOnlyCollection<int> ids, bool multipleDirectoriesWithFiles, string paddedId)
|
||||
{
|
||||
string? result;
|
||||
string year = record.DateTime.Year.ToString();
|
||||
string checkDirectoryName = Path.GetFileName(record.ExifDirectory.FilePath.DirectoryFullPath);
|
||||
if (multipleDirectoriesWithFiles && !checkDirectoryName.Contains(year))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
(bool? isWrongYear, string[] years) = IDate.IsWrongYear(directoryInfo, record.ExifDirectory.FilePath, record.ExifDirectory);
|
||||
if (appSettings.RenameSettings.InPlaceMoveDirectory && !record.ExifDirectory.FilePath.FileNameFirstSegment.Contains(paddedId))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
if (record.ExifDirectory.FilePath.FullName[..2] != directoryInfo.FullName[..2])
|
||||
isWrongYear = null;
|
||||
string directoryName;
|
||||
string tfw = GetTFW(record, isWrongYear);
|
||||
string? maker = IMetadata.GetMaker(record.ExifDirectory);
|
||||
string rootDirectory = appSettings.ResultSettings.RootDirectory;
|
||||
string[] segments = checkDirectoryName.Split(years, StringSplitOptions.None);
|
||||
(int seasonValue, string seasonName) = IDate.GetSeason(record.DateTime.DayOfYear);
|
||||
string? splat = checkDirectoryName.Length > 3 && checkDirectoryName[^3..][1] == '!' ? checkDirectoryName[^3..] : null;
|
||||
string contains = record.ExifDirectory.FilePath.Id is null || ids.Contains(record.ExifDirectory.FilePath.Id.Value) ? "_ Exists _" : "_ New-Destination _";
|
||||
string makerSplit = string.IsNullOrEmpty(maker) ? string.IsNullOrEmpty(appSettings.RenameSettings.DefaultMaker) ? string.Empty : appSettings.RenameSettings.DefaultMaker : $" {maker.Split(' ')[0]}";
|
||||
if (!string.IsNullOrEmpty(splat) || isWrongYear is null || isWrongYear.Value || appSettings.RenameSettings.DirectoryDictionary.Count < 2)
|
||||
directoryName = GetDirectoryName(year, tfw, segments[0], splat, seasonValue, seasonName, makerSplit);
|
||||
else
|
||||
{
|
||||
directoryName = record.DateTime.ToString("yyyy-MM-dd");
|
||||
if (appSettings.RenameSettings.DirectoryDictionary.TryGetValue(directoryName, out string? value) && !string.IsNullOrEmpty(value))
|
||||
directoryName = value;
|
||||
}
|
||||
result = Path.GetFullPath(Path.Combine(rootDirectory, contains, directoryName));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetTFW(Record record, bool? isWrongYear) =>
|
||||
string.Concat(record.HasDateTimeOriginal ? "T" : "F", isWrongYear is not null && isWrongYear.Value ? "W" : record.FastForwardMovingPictureExpertsGroupUsed ? "V" : "I");
|
||||
|
||||
private static string GetDirectoryName(string year, string tfw, string prefix, string? splat, int seasonValue, string seasonName, string makerSplit) =>
|
||||
splat is null ? $"{prefix}{year} {tfw}{year}.{seasonValue} {seasonName}{makerSplit}" : $"{prefix}{year} {tfw}{year}{splat}";
|
||||
|
||||
private static List<ToDo> GetSidecarFiles(AppSettings appSettings, Record record, List<string> distinct, string checkDirectory, string paddedId)
|
||||
{
|
||||
List<ToDo> results = [];
|
||||
ToDo toDo;
|
||||
string checkFile;
|
||||
FilePath filePath;
|
||||
string checkFileExtension;
|
||||
foreach (FileHolder fileHolder in record.SidecarFiles)
|
||||
{
|
||||
checkFileExtension = fileHolder.ExtensionLowered;
|
||||
filePath = FilePath.Get(appSettings.ResultSettings, appSettings.MetadataSettings, fileHolder, index: null);
|
||||
checkFile = Path.Combine(checkDirectory, $"{paddedId}{checkFileExtension}");
|
||||
if (checkFile == filePath.FullName)
|
||||
continue;
|
||||
if (File.Exists(checkFile))
|
||||
{
|
||||
checkFile = string.Concat(checkFile, ".del");
|
||||
if (File.Exists(checkFile))
|
||||
continue;
|
||||
}
|
||||
if (distinct.Contains(checkFile))
|
||||
continue;
|
||||
distinct.Add(checkFile);
|
||||
toDo = new(Directory: checkDirectory,
|
||||
FileInfo: new(filePath.FullName),
|
||||
File: checkFile,
|
||||
JsonFile: false);
|
||||
results.Add(toDo);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private ReadOnlyCollection<string> RenameFilesInDirectories(RenameSettings renameSettings, IRename rename, ReadOnlyCollection<ToDo> toDoCollection)
|
||||
@ -642,65 +688,16 @@ public partial class Rename : IRename, IDisposable
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private static void SaveIdentifiersToDisk(long ticks, AppSettings appSettings, ReadOnlyCollection<Record> recordCollection)
|
||||
private static void VerifyDirectories(ReadOnlyCollection<ToDo> toDoCollection)
|
||||
{
|
||||
string paddedId;
|
||||
Identifier identifier;
|
||||
List<Identifier> identifiers = [];
|
||||
string aMetadataCollectionDirectory = IResult.GetResultsDateGroupDirectory(appSettings.ResultSettings, nameof(A_Metadata), appSettings.ResultSettings.ResultCollection);
|
||||
foreach (Record record in recordCollection)
|
||||
List<string> distinct = [];
|
||||
foreach (ToDo toDo in toDoCollection)
|
||||
{
|
||||
if (record.ExifDirectory.FilePath.Id is null)
|
||||
if (toDo.Directory is null || distinct.Contains(toDo.Directory))
|
||||
continue;
|
||||
paddedId = IId.GetPaddedId(appSettings.ResultSettings, appSettings.MetadataSettings, record.ExifDirectory.FilePath.Id.Value, record.HasIgnoreKeyword, record.HasDateTimeOriginal, index: null);
|
||||
identifier = new([], record.HasDateTimeOriginal, record.ExifDirectory.FilePath.Id.Value, record.ExifDirectory.FilePath.Length, paddedId, record.DateTime.Ticks);
|
||||
identifiers.Add(identifier);
|
||||
}
|
||||
string json = JsonSerializer.Serialize(identifiers.OrderBy(l => l.PaddedId).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
|
||||
_ = IPath.WriteAllText(Path.Combine(aMetadataCollectionDirectory, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<int> GetIds(RenameSettings renameSettings)
|
||||
{
|
||||
ReadOnlyCollection<int> results;
|
||||
string? propertyCollectionFile = string.IsNullOrEmpty(renameSettings.RelativePropertyCollectionFile) ? null : renameSettings.RelativePropertyCollectionFile;
|
||||
string? json = !File.Exists(propertyCollectionFile) ? null : File.ReadAllText(propertyCollectionFile);
|
||||
Identifier[]? identifiers = json is null ? null : JsonSerializer.Deserialize(json, IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
|
||||
if (identifiers is null && !string.IsNullOrEmpty(renameSettings.RelativePropertyCollectionFile))
|
||||
throw new Exception($"Invalid {nameof(renameSettings.RelativePropertyCollectionFile)}");
|
||||
results = identifiers is null ? new([]) : new((from l in identifiers select l.Id).ToArray());
|
||||
return results;
|
||||
}
|
||||
|
||||
private void RenameWork(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks)
|
||||
{
|
||||
ReadOnlyCollection<int> ids = GetIds(appSettings.RenameSettings);
|
||||
string sourceDirectory = Path.GetFullPath(appSettings.ResultSettings.RootDirectory);
|
||||
if (!Directory.Exists(sourceDirectory))
|
||||
_ = Directory.CreateDirectory(sourceDirectory);
|
||||
logger?.LogInformation("{Ticks} {RootDirectory}", ticks, sourceDirectory);
|
||||
ReadOnlyCollection<string> files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories).ToArray().AsReadOnly();
|
||||
if (files.Count > 0)
|
||||
_ = IPath.DeleteEmptyDirectories(appSettings.ResultSettings.RootDirectory);
|
||||
ReadOnlyCollection<Record> recordCollection = GetRecordCollection(logger, appSettings, rename, ticks, ids, sourceDirectory, files);
|
||||
SaveIdentifiersToDisk(ticks, appSettings, recordCollection);
|
||||
if (appSettings.RenameSettings.InPlace || appSettings.RenameSettings.InPlaceWithOriginalName)
|
||||
{
|
||||
if (recordCollection.Count > 0)
|
||||
recordCollection = new([]);
|
||||
string aMetadataSingletonDirectory = IResult.GetResultsGroupDirectory(appSettings.ResultSettings, nameof(A_Metadata));
|
||||
_ = IPath.DeleteEmptyDirectories(aMetadataSingletonDirectory);
|
||||
}
|
||||
if (!appSettings.RenameSettings.OnlySaveIdentifiersToDisk)
|
||||
{
|
||||
DirectoryInfo directoryInfo = new(sourceDirectory);
|
||||
ReadOnlyCollection<ToDo> toDoCollection = GetToDoCollection(appSettings, directoryInfo, ids, files, recordCollection);
|
||||
ReadOnlyCollection<string> lines = RenameFilesInDirectories(appSettings.RenameSettings, rename, toDoCollection);
|
||||
if (lines.Count != 0)
|
||||
{
|
||||
File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines);
|
||||
_ = IPath.DeleteEmptyDirectories(directoryInfo.FullName);
|
||||
}
|
||||
if (!Directory.Exists(toDo.Directory))
|
||||
_ = Directory.CreateDirectory(toDo.Directory);
|
||||
distinct.Add(toDo.Directory);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,6 @@ public interface ICompareSettings
|
||||
public string FacesFileNameExtension { init; get; }
|
||||
public string FacesHiddenFileNameExtension { init; get; }
|
||||
public string FacesPartsFileNameExtension { init; get; }
|
||||
public string[] IgnoreExtensions { init; get; }
|
||||
public int MaxDegreeOfParallelism { init; get; }
|
||||
public string[] ValidImageFormatExtensions { init; get; }
|
||||
public string[] ValidVideoFormatExtensions { init; get; }
|
||||
|
||||
}
|
@ -3,9 +3,6 @@ namespace View_by_Distance.Shared.Models.Properties;
|
||||
public interface IRenameSettings
|
||||
{
|
||||
|
||||
public string[] IgnoreExtensions { init; get; }
|
||||
public bool SkipIdFiles { init; get; }
|
||||
public string[] ValidImageFormatExtensions { init; get; }
|
||||
public string[] ValidVideoFormatExtensions { init; get; }
|
||||
|
||||
}
|
@ -3,8 +3,4 @@ namespace View_by_Distance.Shared.Models.Properties;
|
||||
public interface IWindowsSettings
|
||||
{
|
||||
|
||||
public string[] IgnoreExtensions { init; get; }
|
||||
public string[] ValidImageFormatExtensions { init; get; }
|
||||
public string[] ValidVideoFormatExtensions { init; get; }
|
||||
|
||||
}
|
@ -8,12 +8,15 @@ public record ResultSettings(string DateGroup,
|
||||
string ModelName,
|
||||
int NumberOfJitters,
|
||||
int NumberOfTimesToUpsample,
|
||||
string[] IgnoreExtensions,
|
||||
string PredictorModelName,
|
||||
int ResultAllInOneSubdirectoryLength,
|
||||
string ResultCollection,
|
||||
string ResultContent,
|
||||
string ResultSingleton,
|
||||
string RootDirectory)
|
||||
string RootDirectory,
|
||||
string[] ValidImageFormatExtensions,
|
||||
string[] ValidVideoFormatExtensions)
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
|
@ -5,44 +5,69 @@ public interface IId
|
||||
|
||||
const int DeterministicHashCode = 9876543;
|
||||
|
||||
static bool IsOffsetDeterministicHashCode(MetadataSettings metadataSettings) =>
|
||||
metadataSettings.Offset == DeterministicHashCode;
|
||||
|
||||
string TestStatic_GetIntelligentId(ResultSettings resultSettings, MetadataSettings metadataSettings, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
|
||||
GetIntelligentId(resultSettings, metadataSettings, id, hasIgnoreKeyword, hasDateTimeOriginal);
|
||||
static string GetIntelligentId(ResultSettings resultSettings, MetadataSettings metadataSettings, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
|
||||
Id.GetIntelligentId(resultSettings, metadataSettings, id, hasIgnoreKeyword, hasDateTimeOriginal);
|
||||
|
||||
int TestStatic_GetId(ResultSettings resultSettings, MetadataSettings metadataSettings, string intelligentId) =>
|
||||
GetId(resultSettings, metadataSettings, intelligentId);
|
||||
static int GetId(ResultSettings resultSettings, MetadataSettings metadataSettings, string intelligentId) =>
|
||||
Id.GetId(resultSettings, metadataSettings, intelligentId);
|
||||
|
||||
string TestStatic_GetPaddedId(ResultSettings resultSettings, MetadataSettings metadataSettings, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
|
||||
GetPaddedId(resultSettings, metadataSettings, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
|
||||
static string GetPaddedId(ResultSettings resultSettings, MetadataSettings metadataSettings, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
|
||||
Id.GetPaddedId(resultSettings, metadataSettings, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
|
||||
|
||||
bool TestStatic_NameWithoutExtensionIsIntelligentIdFormat(MetadataSettings metadataSettings, string fileNameFirstSegment) =>
|
||||
NameWithoutExtensionIsIntelligentIdFormat(metadataSettings, fileNameFirstSegment);
|
||||
static bool NameWithoutExtensionIsIntelligentIdFormat(MetadataSettings metadataSettings, string fileNameFirstSegment) =>
|
||||
fileNameFirstSegment.Length - 1 == metadataSettings.IntMinValueLength && fileNameFirstSegment[^1] is '1' or '2' or '3' or '7' or '8' or '9' && fileNameFirstSegment.All(char.IsNumber);
|
||||
|
||||
bool TestStatic_NameWithoutExtensionIsPaddedIntelligentIdFormat(MetadataSettings metadataSettings, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
||||
NameWithoutExtensionIsPaddedIntelligentIdFormat(metadataSettings, sortOrderOnlyLengthIndex, fileNameFirstSegment);
|
||||
static bool NameWithoutExtensionIsPaddedIntelligentIdFormat(MetadataSettings metadataSettings, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
||||
fileNameFirstSegment.Length == metadataSettings.IntMinValueLength + sortOrderOnlyLengthIndex + 1
|
||||
&& fileNameFirstSegment[^1] is '1' or '2' or '3' or '7' or '8' or '9'
|
||||
&& fileNameFirstSegment.All(char.IsNumber);
|
||||
|
||||
bool TestStatic_NameWithoutExtensionIsIdFormat(MetadataSettings metadataSettings, FileHolder fileHolder) =>
|
||||
NameWithoutExtensionIsIdFormat(metadataSettings, fileHolder);
|
||||
static bool NameWithoutExtensionIsIdFormat(MetadataSettings metadataSettings, FileHolder fileHolder) =>
|
||||
Id.NameWithoutExtensionIsIdFormat(metadataSettings, fileHolder.NameWithoutExtension.Split('.')[0]);
|
||||
|
||||
int TestStatic_GetDeterministicHashCode(byte[] value) =>
|
||||
GetDeterministicHashCode(value);
|
||||
static int GetDeterministicHashCode(byte[] value) =>
|
||||
public static int GetDeterministicHashCode(byte[] value) =>
|
||||
Id.GetDeterministicHashCode(value);
|
||||
|
||||
public static byte GetHasIgnoreKeyword(FilePath filePath) =>
|
||||
Id.GetHasIgnoreKeyword(filePath);
|
||||
|
||||
public static bool IsOffsetDeterministicHashCode(MetadataSettings metadataSettings) =>
|
||||
metadataSettings.Offset == DeterministicHashCode;
|
||||
|
||||
public static byte GetHasDateTimeOriginal(ResultSettings resultSettings, FilePath filePath) =>
|
||||
Id.GetHasDateTimeOriginal(resultSettings, filePath);
|
||||
|
||||
public static byte GetMissingDateTimeOriginal(ResultSettings resultSettings, FilePath filePath) =>
|
||||
Id.GetMissingDateTimeOriginal(resultSettings, filePath);
|
||||
|
||||
public static bool NameWithoutExtensionIsIdFormat(MetadataSettings metadataSettings, FileHolder fileHolder) =>
|
||||
Id.NameWithoutExtensionIsIdFormat(metadataSettings, fileHolder.NameWithoutExtension.Split('.')[0]);
|
||||
|
||||
public static int GetId(ResultSettings resultSettings, MetadataSettings metadataSettings, string intelligentId) =>
|
||||
Id.GetId(resultSettings, metadataSettings, intelligentId);
|
||||
|
||||
public static bool NameWithoutExtensionIsIntelligentIdFormat(MetadataSettings metadataSettings, string fileNameFirstSegment) =>
|
||||
fileNameFirstSegment.Length - 1 == metadataSettings.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 bool NameWithoutExtensionIsPaddedIntelligentIdFormat(MetadataSettings metadataSettings, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
||||
fileNameFirstSegment.Length == metadataSettings.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);
|
||||
|
||||
public static string GetIntelligentId(ResultSettings resultSettings, MetadataSettings metadataSettings, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
|
||||
Id.GetIntelligentId(resultSettings, metadataSettings, id, hasIgnoreKeyword, hasDateTimeOriginal);
|
||||
|
||||
public static string GetPaddedId(ResultSettings resultSettings, MetadataSettings metadataSettings, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
|
||||
Id.GetPaddedId(resultSettings, metadataSettings, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
|
||||
|
||||
internal int TestStatic_GetDeterministicHashCode(byte[] value) =>
|
||||
GetDeterministicHashCode(value);
|
||||
|
||||
internal byte TestStatic_GetHasIgnoreKeyword(FilePath filePath) =>
|
||||
GetHasIgnoreKeyword(filePath);
|
||||
|
||||
internal byte TestStatic_GetHasDateTimeOriginal(ResultSettings resultSettings, FilePath filePath) =>
|
||||
GetHasDateTimeOriginal(resultSettings, filePath);
|
||||
|
||||
internal byte TestStatic_GetMissingDateTimeOriginal(ResultSettings resultSettings, FilePath filePath) =>
|
||||
GetMissingDateTimeOriginal(resultSettings, filePath);
|
||||
|
||||
internal bool TestStatic_NameWithoutExtensionIsIdFormat(MetadataSettings metadataSettings, FileHolder fileHolder) =>
|
||||
NameWithoutExtensionIsIdFormat(metadataSettings, fileHolder);
|
||||
|
||||
internal int TestStatic_GetId(ResultSettings resultSettings, MetadataSettings metadataSettings, string intelligentId) =>
|
||||
GetId(resultSettings, metadataSettings, intelligentId);
|
||||
|
||||
internal bool TestStatic_NameWithoutExtensionIsIntelligentIdFormat(MetadataSettings metadataSettings, string fileNameFirstSegment) =>
|
||||
NameWithoutExtensionIsIntelligentIdFormat(metadataSettings, fileNameFirstSegment);
|
||||
|
||||
internal bool TestStatic_NameWithoutExtensionIsPaddedIntelligentIdFormat(MetadataSettings metadataSettings, int sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
|
||||
NameWithoutExtensionIsPaddedIntelligentIdFormat(metadataSettings, sortOrderOnlyLengthIndex, fileNameFirstSegment);
|
||||
|
||||
internal string TestStatic_GetIntelligentId(ResultSettings resultSettings, MetadataSettings metadataSettings, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
|
||||
GetIntelligentId(resultSettings, metadataSettings, id, hasIgnoreKeyword, hasDateTimeOriginal);
|
||||
|
||||
internal string TestStatic_GetPaddedId(ResultSettings resultSettings, MetadataSettings metadataSettings, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
|
||||
GetPaddedId(resultSettings, metadataSettings, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
|
||||
|
||||
}
|
@ -1,12 +1,11 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using View_by_Distance.Shared.Models.Properties;
|
||||
|
||||
namespace View_by_Distance.Shared.Models.Stateless;
|
||||
|
||||
public interface IRename
|
||||
{
|
||||
|
||||
ReadOnlyCollection<string> ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(IRenameSettings renameSettings, FilePath filePath);
|
||||
ReadOnlyCollection<string> ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(ResultSettings resultSettings, FilePath filePath);
|
||||
DeterministicHashCode GetDeterministicHashCode(FilePath filePath);
|
||||
void ConstructProgressBar(int maxTicks, string message);
|
||||
void Tick();
|
||||
|
@ -1,12 +1,11 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using View_by_Distance.Shared.Models.Properties;
|
||||
|
||||
namespace View_by_Distance.Shared.Models.Stateless;
|
||||
|
||||
public interface IWindows
|
||||
{
|
||||
|
||||
ReadOnlyCollection<string> ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(IWindowsSettings windowsSettings, HttpClient? httpClient, FilePath filePath);
|
||||
ReadOnlyCollection<string> ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(ResultSettings resultSettings, HttpClient? httpClient, FilePath filePath);
|
||||
DeterministicHashCode GetDeterministicHashCode(HttpClient? httpClient, FilePath filePath);
|
||||
DeterministicHashCode GetDeterministicHashCode(HttpClient httpClient, Uri uri);
|
||||
void ConstructProgressBar(int maxTicks, string message);
|
||||
|
@ -5,19 +5,34 @@ namespace View_by_Distance.Shared.Models.Stateless;
|
||||
internal abstract class Id
|
||||
{
|
||||
|
||||
internal static bool NameWithoutExtensionIsIdFormat(MetadataSettings metadataSettings, string fileNameFirstSegment)
|
||||
internal static int GetDeterministicHashCode(byte[] value)
|
||||
{
|
||||
bool result;
|
||||
if (fileNameFirstSegment.Length < 5 || fileNameFirstSegment.Length > metadataSettings.IntMinValueLength)
|
||||
result = false;
|
||||
else
|
||||
int result;
|
||||
unchecked
|
||||
{
|
||||
bool skipOneAllAreNumbers = fileNameFirstSegment[1..].All(char.IsNumber);
|
||||
result = (skipOneAllAreNumbers && fileNameFirstSegment[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileNameFirstSegment[0]));
|
||||
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 byte GetHasDateTimeOriginal(ResultSettings resultSettings, FilePath filePath) =>
|
||||
(byte)(!resultSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered) ? filePath.Id > -1 ? 9 : 1 : filePath.Id > -1 ? 6 : 4);
|
||||
|
||||
internal static byte GetMissingDateTimeOriginal(ResultSettings resultSettings, FilePath filePath) =>
|
||||
(byte)(!resultSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered) ? filePath.Id > -1 ? 7 : 3 : 5);
|
||||
|
||||
internal static int GetId(ResultSettings resultSettings, MetadataSettings metadataSettings, string intelligentId)
|
||||
{
|
||||
int result;
|
||||
@ -28,13 +43,26 @@ internal abstract class Id
|
||||
_ = 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')
|
||||
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')
|
||||
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 bool NameWithoutExtensionIsIdFormat(MetadataSettings metadataSettings, string fileNameFirstSegment)
|
||||
{
|
||||
bool result;
|
||||
if (fileNameFirstSegment.Length < 5 || fileNameFirstSegment.Length > metadataSettings.IntMinValueLength)
|
||||
result = false;
|
||||
else
|
||||
{
|
||||
bool skipOneAllAreNumbers = fileNameFirstSegment[1..].All(char.IsNumber);
|
||||
result = (skipOneAllAreNumbers && fileNameFirstSegment[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileNameFirstSegment[0]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0060
|
||||
internal static string GetIntelligentId(ResultSettings resultSettings, MetadataSettings metadataSettings, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal)
|
||||
#pragma warning restore IDE0060
|
||||
@ -80,23 +108,4 @@ internal abstract class Id
|
||||
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,35 +5,29 @@ namespace View_by_Distance.Shared.Models.Stateless;
|
||||
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;
|
||||
if (forceExtensionToLower)
|
||||
Dictionary<byte, List<string>> results = [];
|
||||
List<string>? c;
|
||||
foreach (CombinedEnumAndIndex cei in collection)
|
||||
{
|
||||
string extension = Path.GetExtension(path);
|
||||
string extensionLowered = Path.GetExtension(path).ToLower();
|
||||
if (extension != extensionLowered)
|
||||
if (!results.TryGetValue(cei.Enum, out c))
|
||||
{
|
||||
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}");
|
||||
results.Add(cei.Enum, []);
|
||||
if (!results.TryGetValue(cei.Enum, out c))
|
||||
throw new Exception();
|
||||
}
|
||||
c.Add(cei.Combined);
|
||||
}
|
||||
result = path[length..].Replace(@"\", "/");
|
||||
return result;
|
||||
return Convert(results);
|
||||
}
|
||||
|
||||
internal static bool DeleteEmptyDirectories(string rootDirectory)
|
||||
private static ReadOnlyDictionary<int, ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> Convert(Dictionary<int, Dictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> keyValuePairs)
|
||||
{
|
||||
bool result;
|
||||
List<string> results = [];
|
||||
DeleteEmptyDirectories(rootDirectory, results);
|
||||
result = results.Count > 0;
|
||||
return result;
|
||||
Dictionary<int, ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> results = [];
|
||||
foreach (KeyValuePair<int, Dictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> keyValuePair in keyValuePairs)
|
||||
results.Add(keyValuePair.Key, new(keyValuePair.Value));
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
internal static void DeleteEmptyDirectories(string rootDirectory, List<string> deletedDirectories)
|
||||
@ -71,45 +65,56 @@ internal abstract class XPath
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool WriteAllText(string path, string contents, bool updateDateWhenMatches, bool compareBeforeWrite, DateTime? updateToWhenMatches)
|
||||
internal static byte GetEnum(FilePath filePath) =>
|
||||
GetEnum(filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal);
|
||||
|
||||
private static byte GetEnum(bool? ik, bool? dto)
|
||||
{
|
||||
bool result;
|
||||
string text;
|
||||
if (!compareBeforeWrite)
|
||||
result = true;
|
||||
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
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
text = string.Empty;
|
||||
else
|
||||
text = File.ReadAllText(path);
|
||||
result = text != contents;
|
||||
if (!result && updateDateWhenMatches)
|
||||
{
|
||||
if (updateToWhenMatches is null)
|
||||
File.SetLastWriteTime(path, DateTime.Now);
|
||||
else
|
||||
File.SetLastWriteTime(path, updateToWhenMatches.Value);
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
if (path.Contains("()"))
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("{}") && !path.EndsWith(".json"))
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("[]") && !path.EndsWith(".json"))
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
|
||||
File.WriteAllText(path, contents);
|
||||
else
|
||||
File.WriteAllText(path, contents);
|
||||
}
|
||||
throw new Exception();
|
||||
return result;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
List<string> results = [];
|
||||
@ -146,83 +151,15 @@ internal abstract class XPath
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static List<string> GetDirectories(string directory)
|
||||
internal static bool DeleteEmptyDirectories(string rootDirectory)
|
||||
{
|
||||
bool result;
|
||||
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 (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;
|
||||
DeleteEmptyDirectories(rootDirectory, results);
|
||||
result = results.Count > 0;
|
||||
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)
|
||||
{
|
||||
bool check;
|
||||
@ -265,49 +202,117 @@ internal abstract class XPath
|
||||
}
|
||||
}
|
||||
|
||||
private static byte GetEnum(bool? ik, bool? dto)
|
||||
internal static void ChangeDateForEmptyDirectories(string rootDirectory, long ticks)
|
||||
{
|
||||
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;
|
||||
DateTime dateTime = new(ticks);
|
||||
IEnumerable<string> fileSystemEntries;
|
||||
string[] directories;
|
||||
if (!Directory.Exists(rootDirectory))
|
||||
directories = [];
|
||||
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;
|
||||
}
|
||||
|
||||
internal static byte GetEnum(FilePath filePath) =>
|
||||
GetEnum(filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal);
|
||||
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;
|
||||
}
|
||||
|
||||
private static CombinedEnumAndIndex GetCombinedEnumAndIndex(int resultAllInOneSubdirectoryLength, FilePath filePath, string fileNameWithoutExtension)
|
||||
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(ResultSettings resultSettings, FilePath filePath)
|
||||
{
|
||||
CombinedEnumAndIndex result;
|
||||
if (filePath.Id is not null)
|
||||
result = GetCombinedEnumAndIndex(resultSettings, filePath, filePath.Id.Value.ToString());
|
||||
else
|
||||
result = GetCombinedEnumAndIndex(resultSettings, filePath, filePath.NameWithoutExtension);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static CombinedEnumAndIndex GetCombinedEnumAndIndex(ResultSettings resultSettings, FilePath filePath, string fileNameWithoutExtension)
|
||||
{
|
||||
CombinedEnumAndIndex result;
|
||||
byte @enum;
|
||||
int converted;
|
||||
string combined;
|
||||
byte missingDateTimeOriginal = IId.GetMissingDateTimeOriginal(resultSettings, filePath);
|
||||
if (filePath.HasIgnoreKeyword is null || filePath.HasDateTimeOriginal is null)
|
||||
throw new NotImplementedException();
|
||||
if (filePath.HasIgnoreKeyword.Value)
|
||||
@enum = IId.GetHasIgnoreKeyword(filePath);
|
||||
else if (!filePath.HasDateTimeOriginal.Value)
|
||||
@enum = missingDateTimeOriginal;
|
||||
else
|
||||
@enum = IId.GetHasDateTimeOriginal(resultSettings, filePath);
|
||||
string fileNameBeforeFirst = fileNameWithoutExtension.Split('.')[0];
|
||||
byte @enum = GetEnum(filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal);
|
||||
string check = fileNameBeforeFirst.Length < resultAllInOneSubdirectoryLength ?
|
||||
new('-', resultAllInOneSubdirectoryLength) :
|
||||
fileNameBeforeFirst[^resultAllInOneSubdirectoryLength..];
|
||||
string check = fileNameBeforeFirst.Length < resultSettings.ResultAllInOneSubdirectoryLength ?
|
||||
new('-', resultSettings.ResultAllInOneSubdirectoryLength) :
|
||||
fileNameBeforeFirst[^resultSettings.ResultAllInOneSubdirectoryLength..];
|
||||
if (check.Any(l => !char.IsNumber(l)))
|
||||
{
|
||||
combined = $"{@enum}{new('-', resultAllInOneSubdirectoryLength)}";
|
||||
converted = int.Parse($"1{new string('0', resultAllInOneSubdirectoryLength)}");
|
||||
combined = $"{@enum}{new('-', resultSettings.ResultAllInOneSubdirectoryLength)}";
|
||||
converted = int.Parse($"1{new string('0', resultSettings.ResultAllInOneSubdirectoryLength)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -318,16 +323,66 @@ internal abstract class XPath
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static CombinedEnumAndIndex GetCombinedEnumAndIndex(ResultSettings resultSettings, FilePath filePath)
|
||||
internal static bool WriteAllText(string path, string contents, bool updateDateWhenMatches, bool compareBeforeWrite, DateTime? updateToWhenMatches)
|
||||
{
|
||||
CombinedEnumAndIndex result;
|
||||
if (filePath.Id is not null)
|
||||
result = GetCombinedEnumAndIndex(resultSettings.ResultAllInOneSubdirectoryLength, filePath, filePath.Id.Value.ToString());
|
||||
bool result;
|
||||
string text;
|
||||
if (!compareBeforeWrite)
|
||||
result = true;
|
||||
else
|
||||
result = GetCombinedEnumAndIndex(resultSettings.ResultAllInOneSubdirectoryLength, filePath, filePath.NameWithoutExtension);
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
text = string.Empty;
|
||||
else
|
||||
text = File.ReadAllText(path);
|
||||
result = text != contents;
|
||||
if (!result && updateDateWhenMatches)
|
||||
{
|
||||
if (updateToWhenMatches is null)
|
||||
File.SetLastWriteTime(path, DateTime.Now);
|
||||
else
|
||||
File.SetLastWriteTime(path, updateToWhenMatches.Value);
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
if (path.Contains("()"))
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("{}") && !path.EndsWith(".json"))
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("[]") && !path.EndsWith(".json"))
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
|
||||
File.WriteAllText(path, contents);
|
||||
else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
|
||||
File.WriteAllText(path, contents);
|
||||
else
|
||||
File.WriteAllText(path, contents);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static ReadOnlyDictionary<int, ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> GetKeyValuePairs(ResultSettings resultSettings, string? resultsFullGroupDirectory, string[]? jsonGroups)
|
||||
{
|
||||
Dictionary<int, Dictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> results = [];
|
||||
if (jsonGroups is not null)
|
||||
{
|
||||
DateTime dateTime = DateTime.Now;
|
||||
ReadOnlyCollection<int> years = GetYears(resultSettings);
|
||||
Dictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>? k;
|
||||
ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePairs = GetKeyValuePairs(resultSettings, resultsFullGroupDirectory, jsonGroups, dateTime);
|
||||
foreach (int year in years)
|
||||
{
|
||||
results.Add(year, []);
|
||||
if (!results.TryGetValue(year, out k))
|
||||
throw new NullReferenceException(nameof(k));
|
||||
foreach (KeyValuePair<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePair in keyValuePairs)
|
||||
k.Add(keyValuePair.Key, keyValuePair.Value);
|
||||
}
|
||||
}
|
||||
return Convert(results);
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<int> GetYears(ResultSettings resultSettings)
|
||||
{
|
||||
List<int> results = [];
|
||||
@ -337,44 +392,6 @@ internal abstract class XPath
|
||||
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();
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
results.Add(cei.Enum, []);
|
||||
if (!results.TryGetValue(cei.Enum, out c))
|
||||
throw new Exception();
|
||||
}
|
||||
c.Add(cei.Combined);
|
||||
}
|
||||
return Convert(results);
|
||||
}
|
||||
|
||||
private static ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> GetKeyValuePairs(ResultSettings resultSettings, string? resultsFullGroupDirectory, string[]? jsonGroups, DateTime dateTime)
|
||||
{
|
||||
Dictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> results = [];
|
||||
@ -428,33 +445,25 @@ internal abstract class XPath
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private static ReadOnlyDictionary<int, ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> Convert(Dictionary<int, Dictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> keyValuePairs)
|
||||
private static byte[] GetBytes() =>
|
||||
[
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9
|
||||
];
|
||||
|
||||
private static ReadOnlyDictionary<byte, ReadOnlyCollection<string>> Convert(Dictionary<byte, List<string>> keyValuePairs)
|
||||
{
|
||||
Dictionary<int, ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> results = [];
|
||||
foreach (KeyValuePair<int, Dictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> keyValuePair in keyValuePairs)
|
||||
Dictionary<byte, ReadOnlyCollection<string>> results = [];
|
||||
foreach (KeyValuePair<byte, List<string>> keyValuePair in keyValuePairs)
|
||||
results.Add(keyValuePair.Key, new(keyValuePair.Value));
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
internal static ReadOnlyDictionary<int, ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> GetKeyValuePairs(ResultSettings resultSettings, string? resultsFullGroupDirectory, string[]? jsonGroups)
|
||||
{
|
||||
Dictionary<int, Dictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>> results = [];
|
||||
if (jsonGroups is not null)
|
||||
{
|
||||
DateTime dateTime = DateTime.Now;
|
||||
ReadOnlyCollection<int> years = GetYears(resultSettings);
|
||||
Dictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>>? k;
|
||||
ReadOnlyDictionary<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePairs = GetKeyValuePairs(resultSettings, resultsFullGroupDirectory, jsonGroups, dateTime);
|
||||
foreach (int year in years)
|
||||
{
|
||||
results.Add(year, []);
|
||||
if (!results.TryGetValue(year, out k))
|
||||
throw new NullReferenceException(nameof(k));
|
||||
foreach (KeyValuePair<string, ReadOnlyDictionary<byte, ReadOnlyCollection<string>>> keyValuePair in keyValuePairs)
|
||||
k.Add(keyValuePair.Key, keyValuePair.Value);
|
||||
}
|
||||
}
|
||||
return Convert(results);
|
||||
}
|
||||
|
||||
}
|
@ -6,12 +6,9 @@ namespace View_by_Distance.Windows.Models;
|
||||
|
||||
public record WindowsSettings(string Company,
|
||||
string? Host,
|
||||
string[] IgnoreExtensions,
|
||||
int MaxDegreeOfParallelism,
|
||||
string? Page,
|
||||
string[] SidecarExtensions,
|
||||
string[] ValidImageFormatExtensions,
|
||||
string[] ValidVideoFormatExtensions,
|
||||
bool VerifyOnly) : Shared.Models.Properties.IWindowsSettings
|
||||
{
|
||||
|
||||
|
@ -9,7 +9,6 @@ using System.Text.Json;
|
||||
using View_by_Distance.Metadata.Models;
|
||||
using View_by_Distance.Metadata.Models.Stateless;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Properties;
|
||||
using View_by_Distance.Shared.Models.Stateless;
|
||||
using View_by_Distance.Windows.Models;
|
||||
|
||||
@ -21,48 +20,93 @@ public partial class Windows : IWindows, IDisposable
|
||||
private ProgressBar? _ProgressBar;
|
||||
private readonly ProgressBarOptions _ProgressBarOptions;
|
||||
|
||||
public Windows(List<string> args, ILogger<Program>? logger, AppSettings appSettings, bool isSilent, IConsole console)
|
||||
DeterministicHashCode IWindows.GetDeterministicHashCode(HttpClient httpClient, Uri uri) =>
|
||||
GetDeterministicHashCode(httpClient, uri);
|
||||
|
||||
DeterministicHashCode IWindows.GetDeterministicHashCode(HttpClient? httpClient, FilePath filePath)
|
||||
{
|
||||
if (isSilent)
|
||||
{ }
|
||||
if (args is null)
|
||||
throw new NullReferenceException(nameof(args));
|
||||
if (console is null)
|
||||
throw new NullReferenceException(nameof(console));
|
||||
IWindows windows = this;
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
_ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
WindowsWork(logger, appSettings, windows, ticks);
|
||||
DeterministicHashCode result;
|
||||
if (httpClient is not null)
|
||||
result = GetDeterministicHashCode(httpClient, new Uri(filePath.FullName));
|
||||
else
|
||||
{
|
||||
Stream stream = File.OpenRead(filePath.FullName);
|
||||
result = GetDeterministicHashCode(stream);
|
||||
stream.Dispose();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static DeterministicHashCode GetDeterministicHashCode(HttpClient httpClient, Uri uri)
|
||||
{
|
||||
DeterministicHashCode result;
|
||||
Stream stream = GetStream(httpClient, uri);
|
||||
result = GetDeterministicHashCode(stream);
|
||||
stream.Dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Stream GetStream(HttpClient httpClient, Uri uri)
|
||||
{
|
||||
Stream result;
|
||||
Task<Stream> task = httpClient.GetStreamAsync(uri);
|
||||
task.Wait();
|
||||
result = task.Result;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static DeterministicHashCode GetDeterministicHashCode(Stream stream)
|
||||
{
|
||||
DeterministicHashCode result;
|
||||
int? id;
|
||||
int? width;
|
||||
int? height;
|
||||
try
|
||||
{
|
||||
#pragma warning disable CA1416
|
||||
using Image image = Image.FromStream(stream);
|
||||
width = image.Width;
|
||||
height = image.Height;
|
||||
using Bitmap bitmap = new(image);
|
||||
Rectangle rectangle = new(0, 0, image.Width, image.Height);
|
||||
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||
IntPtr intPtr = bitmapData.Scan0;
|
||||
int length = bitmapData.Stride * bitmap.Height;
|
||||
byte[] bytes = new byte[length];
|
||||
Marshal.Copy(intPtr, bytes, 0, length);
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
#pragma warning restore CA1416
|
||||
id = IId.GetDeterministicHashCode(bytes);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
id = null;
|
||||
width = null;
|
||||
height = null;
|
||||
}
|
||||
result = new(height, id, width);
|
||||
return result;
|
||||
}
|
||||
|
||||
void IWindows.Tick() =>
|
||||
_ProgressBar?.Tick();
|
||||
|
||||
void IWindows.ConstructProgressBar(int maxTicks, string message)
|
||||
{
|
||||
_ProgressBar?.Dispose();
|
||||
_ProgressBar = new(maxTicks, message, _ProgressBarOptions);
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
_ProgressBar?.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private static void DownloadFile(HttpClient httpClient, FilePath filePath)
|
||||
void IWindows.ConstructProgressBar(int maxTicks, string message)
|
||||
{
|
||||
FileStream fileStream = new(filePath.FullName, FileMode.Truncate);
|
||||
Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(filePath.FullName);
|
||||
httpResponseMessage.Wait();
|
||||
Task task = httpResponseMessage.Result.Content.CopyToAsync(fileStream);
|
||||
task.Wait();
|
||||
_ProgressBar?.Dispose();
|
||||
_ProgressBar = new(maxTicks, message, _ProgressBarOptions);
|
||||
}
|
||||
|
||||
ReadOnlyCollection<string> IWindows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(IWindowsSettings WindowsSettings, HttpClient? httpClient, FilePath filePath)
|
||||
ReadOnlyCollection<string> IWindows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(ResultSettings resultSettings, HttpClient? httpClient, FilePath filePath)
|
||||
{
|
||||
List<string> results = [];
|
||||
bool isValidVideoFormatExtensions = WindowsSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered);
|
||||
bool isValidVideoFormatExtensions = resultSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered);
|
||||
if (isValidVideoFormatExtensions)
|
||||
{
|
||||
bool check;
|
||||
@ -94,75 +138,54 @@ public partial class Windows : IWindows, IDisposable
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
#pragma warning disable CA1416
|
||||
|
||||
private static DeterministicHashCode GetDeterministicHashCode(Stream stream)
|
||||
private static void DownloadFile(HttpClient httpClient, FilePath filePath)
|
||||
{
|
||||
DeterministicHashCode result;
|
||||
int? id;
|
||||
int? width;
|
||||
int? height;
|
||||
try
|
||||
{
|
||||
using Image image = Image.FromStream(stream);
|
||||
width = image.Width;
|
||||
height = image.Height;
|
||||
using Bitmap bitmap = new(image);
|
||||
Rectangle rectangle = new(0, 0, image.Width, image.Height);
|
||||
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||
IntPtr intPtr = bitmapData.Scan0;
|
||||
int length = bitmapData.Stride * bitmap.Height;
|
||||
byte[] bytes = new byte[length];
|
||||
Marshal.Copy(intPtr, bytes, 0, length);
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
id = IId.GetDeterministicHashCode(bytes);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
id = null;
|
||||
width = null;
|
||||
height = null;
|
||||
}
|
||||
result = new(height, id, width);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Stream GetStream(HttpClient httpClient, Uri uri)
|
||||
{
|
||||
Stream result;
|
||||
Task<Stream> task = httpClient.GetStreamAsync(uri);
|
||||
FileStream fileStream = new(filePath.FullName, FileMode.Truncate);
|
||||
Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(filePath.FullName);
|
||||
httpResponseMessage.Wait();
|
||||
Task task = httpResponseMessage.Result.Content.CopyToAsync(fileStream);
|
||||
task.Wait();
|
||||
result = task.Result;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static DeterministicHashCode GetDeterministicHashCode(HttpClient httpClient, Uri uri)
|
||||
public Windows(List<string> args, ILogger<Program>? logger, AppSettings appSettings, bool isSilent, IConsole console)
|
||||
{
|
||||
DeterministicHashCode result;
|
||||
Stream stream = GetStream(httpClient, uri);
|
||||
result = GetDeterministicHashCode(stream);
|
||||
stream.Dispose();
|
||||
return result;
|
||||
if (isSilent)
|
||||
{ }
|
||||
if (args is null)
|
||||
throw new NullReferenceException(nameof(args));
|
||||
if (console is null)
|
||||
throw new NullReferenceException(nameof(console));
|
||||
IWindows windows = this;
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
_ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
WindowsWork(logger, appSettings, windows, ticks);
|
||||
}
|
||||
|
||||
DeterministicHashCode IWindows.GetDeterministicHashCode(HttpClient httpClient, Uri uri) =>
|
||||
GetDeterministicHashCode(httpClient, uri);
|
||||
|
||||
DeterministicHashCode IWindows.GetDeterministicHashCode(HttpClient? httpClient, FilePath filePath)
|
||||
private void WindowsWork(ILogger<Program>? logger, AppSettings appSettings, IWindows windows, long ticks)
|
||||
{
|
||||
DeterministicHashCode result;
|
||||
if (httpClient is not null)
|
||||
result = GetDeterministicHashCode(httpClient, new Uri(filePath.FullName));
|
||||
if (appSettings.WindowsSettings.VerifyOnly && !string.IsNullOrEmpty(appSettings.WindowsSettings.Host) && !string.IsNullOrEmpty(appSettings.WindowsSettings.Page))
|
||||
Verify(logger, appSettings, windows, appSettings.WindowsSettings.Host, appSettings.WindowsSettings.Page);
|
||||
else
|
||||
{
|
||||
Stream stream = File.OpenRead(filePath.FullName);
|
||||
result = GetDeterministicHashCode(stream);
|
||||
stream.Dispose();
|
||||
string sourceDirectory = Path.GetFullPath(appSettings.ResultSettings.RootDirectory);
|
||||
WindowsWork(logger, appSettings, windows, ticks, sourceDirectory);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning restore CA1416
|
||||
private static void Verify(ILogger<Program>? logger, AppSettings appSettings, IWindows windows, string host, string page)
|
||||
{
|
||||
List<string> messages = [];
|
||||
HttpClient httpClient = new();
|
||||
int appSettingsMaxDegreeOfParallelism = appSettings.WindowsSettings.MaxDegreeOfParallelism;
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = appSettingsMaxDegreeOfParallelism };
|
||||
ReadOnlyCollection<NginxFileSystem> collection = GetRecursiveCollection(httpClient, host, page) ?? throw new Exception();
|
||||
windows.ConstructProgressBar(collection.Count, nameof(Verify));
|
||||
_ = Parallel.For(0, collection.Count, parallelOptions, (i, state) =>
|
||||
VerifyParallelFor(appSettings, windows, httpClient, collection[i], messages));
|
||||
httpClient.Dispose();
|
||||
foreach (string message in messages)
|
||||
logger?.LogWarning("{message}", message);
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<NginxFileSystem>? GetRecursiveCollection(HttpClient httpClient, string host, string page)
|
||||
{
|
||||
@ -227,19 +250,46 @@ public partial class Windows : IWindows, IDisposable
|
||||
messages.Add($"!{nginxFileSystem.Name}.StartsWith({paddedId})");
|
||||
}
|
||||
|
||||
private static void Verify(ILogger<Program>? logger, AppSettings appSettings, IWindows windows, string host, string page)
|
||||
private void WindowsWork(ILogger<Program>? logger, AppSettings appSettings, IWindows windows, long ticks, string sourceDirectory)
|
||||
{
|
||||
List<string> messages = [];
|
||||
HttpClient httpClient = new();
|
||||
ReadOnlyCollection<FirstPass> results;
|
||||
if (!Directory.Exists(sourceDirectory))
|
||||
_ = Directory.CreateDirectory(sourceDirectory);
|
||||
logger?.LogInformation("{Ticks} {RootDirectory}", ticks, sourceDirectory);
|
||||
ReadOnlyCollection<string> files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories).ToArray().AsReadOnly();
|
||||
if (files.Count > 0)
|
||||
_ = IPath.DeleteEmptyDirectories(appSettings.ResultSettings.RootDirectory);
|
||||
A_Metadata metadata = new(appSettings.ResultSettings, appSettings.MetadataSettings);
|
||||
int appSettingsMaxDegreeOfParallelism = appSettings.WindowsSettings.MaxDegreeOfParallelism;
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = appSettingsMaxDegreeOfParallelism };
|
||||
ReadOnlyCollection<NginxFileSystem> collection = GetRecursiveCollection(httpClient, host, page) ?? throw new Exception();
|
||||
windows.ConstructProgressBar(collection.Count, nameof(Verify));
|
||||
_ = Parallel.For(0, collection.Count, parallelOptions, (i, state) =>
|
||||
VerifyParallelFor(appSettings, windows, httpClient, collection[i], messages));
|
||||
httpClient.Dispose();
|
||||
foreach (string message in messages)
|
||||
logger?.LogWarning("{message}", message);
|
||||
int filesCount = appSettingsMaxDegreeOfParallelism == 1 ? files.Count : 123000;
|
||||
windows.ConstructProgressBar(filesCount, "EnumerateFiles load");
|
||||
if (appSettingsMaxDegreeOfParallelism == 1)
|
||||
results = WindowsSynchronousWork(logger, appSettings, windows, files, metadata);
|
||||
else
|
||||
results = WindowsAsynchronousWork(appSettings, windows, files, metadata, appSettingsMaxDegreeOfParallelism);
|
||||
string json = JsonSerializer.Serialize(results, FirstPassCollectionSourceGenerationContext.Default.ListFirstPass);
|
||||
File.WriteAllText(Path.Combine(sourceDirectory, $"{ticks}.json"), json);
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<FirstPass> WindowsSynchronousWork(ILogger<Program>? logger, AppSettings appSettings, IWindows windows, IEnumerable<string> files, A_Metadata metadata)
|
||||
{
|
||||
List<FirstPass> results = [];
|
||||
int index = -1;
|
||||
ReadOnlyDictionary<string, List<FileHolder>> keyValuePairs;
|
||||
if (string.IsNullOrEmpty(appSettings.WindowsSettings.Host) || string.IsNullOrEmpty(appSettings.WindowsSettings.Page))
|
||||
keyValuePairs = IMetadata.GetKeyValuePairs(files);
|
||||
else
|
||||
{
|
||||
ReadOnlyCollection<NginxFileSystem> collection = GetRecursiveCollection(appSettings.WindowsSettings.Host, appSettings.WindowsSettings.Page);
|
||||
keyValuePairs = IMetadata.GetKeyValuePairs(collection);
|
||||
}
|
||||
foreach (KeyValuePair<string, List<FileHolder>> keyValuePair in keyValuePairs)
|
||||
{
|
||||
if (keyValuePair.Value.Count > 2)
|
||||
throw new NotSupportedException("Too many sidecar files!");
|
||||
index = WindowsSynchronousWork(logger, appSettings, windows, metadata, results, index, keyValuePair);
|
||||
}
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<NginxFileSystem> GetRecursiveCollection(string host, string page)
|
||||
@ -270,7 +320,7 @@ public partial class Windows : IWindows, IDisposable
|
||||
{
|
||||
if (appSettings.WindowsSettings.SidecarExtensions.Contains(fileHolder.ExtensionLowered))
|
||||
continue;
|
||||
if (appSettings.WindowsSettings.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
|
||||
if (appSettings.ResultSettings.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
|
||||
continue;
|
||||
filePath = FilePath.Get(appSettings.ResultSettings, appSettings.MetadataSettings, fileHolder, result);
|
||||
if (filePath.Id is not null && (filePath.IsIntelligentIdFormat || filePath.SortOrder is not null))
|
||||
@ -285,7 +335,7 @@ public partial class Windows : IWindows, IDisposable
|
||||
}
|
||||
else
|
||||
{
|
||||
fastForwardMovingPictureExpertsGroupFiles = windows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(appSettings.WindowsSettings, httpClient, filePath);
|
||||
fastForwardMovingPictureExpertsGroupFiles = windows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(appSettings.ResultSettings, httpClient, filePath);
|
||||
fastForwardMovingPictureExpertsGroupFilePath = fastForwardMovingPictureExpertsGroupFiles.Count == 0 ? null : FilePath.Get(appSettings.ResultSettings, appSettings.MetadataSettings, FileHolder.Get(fastForwardMovingPictureExpertsGroupFiles[0]), result);
|
||||
deterministicHashCode = fastForwardMovingPictureExpertsGroupFilePath is null ? windows.GetDeterministicHashCode(httpClient, filePath) : windows.GetDeterministicHashCode(httpClient, fastForwardMovingPictureExpertsGroupFilePath);
|
||||
}
|
||||
@ -310,7 +360,7 @@ public partial class Windows : IWindows, IDisposable
|
||||
foreach (string fastForwardMovingPictureExpertsGroupFile in fastForwardMovingPictureExpertsGroupFiles)
|
||||
File.Delete(fastForwardMovingPictureExpertsGroupFile);
|
||||
}
|
||||
if (!fastForwardMovingPictureExpertsGroupUsed && appSettings.WindowsSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered))
|
||||
if (!fastForwardMovingPictureExpertsGroupUsed && appSettings.ResultSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered))
|
||||
fastForwardMovingPictureExpertsGroupUsed = true;
|
||||
firstPass = new(exifDirectory, fastForwardMovingPictureExpertsGroupUsed, minimumYearAndPathCombined, sidecarFiles.ToArray());
|
||||
results.Add(firstPass);
|
||||
@ -318,27 +368,6 @@ public partial class Windows : IWindows, IDisposable
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<FirstPass> WindowsSynchronousWork(ILogger<Program>? logger, AppSettings appSettings, IWindows windows, IEnumerable<string> files, A_Metadata metadata)
|
||||
{
|
||||
List<FirstPass> results = [];
|
||||
int index = -1;
|
||||
ReadOnlyDictionary<string, List<FileHolder>> keyValuePairs;
|
||||
if (string.IsNullOrEmpty(appSettings.WindowsSettings.Host) || string.IsNullOrEmpty(appSettings.WindowsSettings.Page))
|
||||
keyValuePairs = IMetadata.GetKeyValuePairs(files);
|
||||
else
|
||||
{
|
||||
ReadOnlyCollection<NginxFileSystem> collection = GetRecursiveCollection(appSettings.WindowsSettings.Host, appSettings.WindowsSettings.Page);
|
||||
keyValuePairs = IMetadata.GetKeyValuePairs(collection);
|
||||
}
|
||||
foreach (KeyValuePair<string, List<FileHolder>> keyValuePair in keyValuePairs)
|
||||
{
|
||||
if (keyValuePair.Value.Count > 2)
|
||||
throw new NotSupportedException("Too many sidecar files!");
|
||||
index = WindowsSynchronousWork(logger, appSettings, windows, metadata, results, index, keyValuePair);
|
||||
}
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private ReadOnlyCollection<FirstPass> WindowsAsynchronousWork(AppSettings appSettings, IWindows windows, ReadOnlyCollection<string> files, A_Metadata metadata, int appSettingsMaxDegreeOfParallelism)
|
||||
{
|
||||
List<FirstPass> results = [];
|
||||
@ -346,12 +375,12 @@ public partial class Windows : IWindows, IDisposable
|
||||
List<string> distinct = [];
|
||||
List<MetadataGroup> metadataGroups = [];
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = appSettingsMaxDegreeOfParallelism };
|
||||
files.AsParallel().ForAll(IMetadata.SetExifDirectoryCollection(windows, appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.WindowsSettings, metadata, distinct, metadataGroups));
|
||||
files.AsParallel().ForAll(IMetadata.SetExifDirectoryCollection(windows, appSettings.ResultSettings, appSettings.MetadataSettings, metadata, distinct, metadataGroups));
|
||||
if (_ProgressBar?.CurrentTick != results.Count)
|
||||
throw new NotSupportedException();
|
||||
foreach (MetadataGroup metadataGroup in metadataGroups)
|
||||
{
|
||||
if (metadataGroup.FastForwardMovingPictureExpertsGroupUsed || !appSettings.WindowsSettings.ValidVideoFormatExtensions.Contains(metadataGroup.FilePath.ExtensionLowered))
|
||||
if (metadataGroup.FastForwardMovingPictureExpertsGroupUsed || !appSettings.ResultSettings.ValidVideoFormatExtensions.Contains(metadataGroup.FilePath.ExtensionLowered))
|
||||
firstPass = new(metadataGroup.ExifDirectory, metadataGroup.FastForwardMovingPictureExpertsGroupUsed, metadataGroup.MinimumYearAndPathCombined, metadataGroup.SidecarFiles.ToArray());
|
||||
else
|
||||
firstPass = new(metadataGroup.ExifDirectory, FastForwardMovingPictureExpertsGroupUsed: true, metadataGroup.MinimumYearAndPathCombined, metadataGroup.SidecarFiles.ToArray());
|
||||
@ -360,36 +389,4 @@ public partial class Windows : IWindows, IDisposable
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private void WindowsWork(ILogger<Program>? logger, AppSettings appSettings, IWindows windows, long ticks, string sourceDirectory)
|
||||
{
|
||||
ReadOnlyCollection<FirstPass> results;
|
||||
if (!Directory.Exists(sourceDirectory))
|
||||
_ = Directory.CreateDirectory(sourceDirectory);
|
||||
logger?.LogInformation("{Ticks} {RootDirectory}", ticks, sourceDirectory);
|
||||
ReadOnlyCollection<string> files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories).ToArray().AsReadOnly();
|
||||
if (files.Count > 0)
|
||||
_ = IPath.DeleteEmptyDirectories(appSettings.ResultSettings.RootDirectory);
|
||||
A_Metadata metadata = new(appSettings.ResultSettings, appSettings.MetadataSettings);
|
||||
int appSettingsMaxDegreeOfParallelism = appSettings.WindowsSettings.MaxDegreeOfParallelism;
|
||||
int filesCount = appSettingsMaxDegreeOfParallelism == 1 ? files.Count : 123000;
|
||||
windows.ConstructProgressBar(filesCount, "EnumerateFiles load");
|
||||
if (appSettingsMaxDegreeOfParallelism == 1)
|
||||
results = WindowsSynchronousWork(logger, appSettings, windows, files, metadata);
|
||||
else
|
||||
results = WindowsAsynchronousWork(appSettings, windows, files, metadata, appSettingsMaxDegreeOfParallelism);
|
||||
string json = JsonSerializer.Serialize(results, FirstPassCollectionSourceGenerationContext.Default.ListFirstPass);
|
||||
File.WriteAllText(Path.Combine(sourceDirectory, $"{ticks}.json"), json);
|
||||
}
|
||||
|
||||
private void WindowsWork(ILogger<Program>? logger, AppSettings appSettings, IWindows windows, long ticks)
|
||||
{
|
||||
if (appSettings.WindowsSettings.VerifyOnly && !string.IsNullOrEmpty(appSettings.WindowsSettings.Host) && !string.IsNullOrEmpty(appSettings.WindowsSettings.Page))
|
||||
Verify(logger, appSettings, windows, appSettings.WindowsSettings.Host, appSettings.WindowsSettings.Page);
|
||||
else
|
||||
{
|
||||
string sourceDirectory = Path.GetFullPath(appSettings.ResultSettings.RootDirectory);
|
||||
WindowsWork(logger, appSettings, windows, ticks, sourceDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user