Switch to ExifDirectory from Property

This commit is contained in:
2025-04-06 18:23:57 -07:00
parent 3f7affceef
commit c7ded16e50
50 changed files with 2647 additions and 1846 deletions

View File

@ -1,4 +1,4 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Phares.Shared;
using System.Globalization;
@ -96,203 +96,6 @@ public class DateGroup
throw new Exception("Change configuration!");
}
private static bool WriteAllText(string path, string contents, bool compareBeforeWrite)
{
bool result;
string text;
if (!compareBeforeWrite)
result = true;
else
{
if (!File.Exists(path))
text = string.Empty;
else
text = File.ReadAllText(path);
result = text != contents;
}
if (result)
{
if (path.Contains("()"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("[]") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
File.WriteAllText(path, contents);
else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
File.WriteAllText(path, contents);
else
File.WriteAllText(path, contents);
}
return result;
}
private List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> GetMoveFileCollection(string destinationDirectory, string topDirectory, Item[] filteredItems)
{
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> results = [];
char flag;
string day;
int season;
string year;
string month;
string? check;
string fileName;
string? pathRoot;
DateTime dateTime;
string seasonName;
string weekOfYear;
bool? isWrongYear;
string seasonValue;
string directoryName;
string topDirectoryName;
List<DateTime> dateTimes;
string[]? matches = null;
string[] directorySegments;
List<string> destinationCollection;
List<string> directoryNames = [];
List<string> topDirectorySegments = [];
StringBuilder destinationDirectoryName = new();
Calendar calendar = new CultureInfo("en-US").Calendar;
for (int z = 1; z < 3; z++)
{
if (z == 1)
{
check = Path.Combine(destinationDirectory, ".");
pathRoot = Path.GetPathRoot(destinationDirectory);
}
else if (z == 2)
{
check = Path.Combine(topDirectory, ".");
pathRoot = Path.GetPathRoot(topDirectory);
}
else
throw new Exception();
if (string.IsNullOrEmpty(pathRoot))
continue;
for (int i = 0; i < int.MaxValue; i++)
{
check = Path.GetDirectoryName(check);
if (string.IsNullOrEmpty(check) || check == pathRoot)
break;
directoryName = Path.GetFileName(check);
directorySegments = directoryName.Split(' ');
topDirectorySegments.AddRange(directorySegments);
(_, matches) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(directorySegments, string.Empty);
if (matches.Length != 0)
break;
}
if (matches is not null && matches.Length != 0)
break;
}
foreach (Item item in filteredItems)
{
directoryNames.Clear();
destinationCollection = [];
_ = destinationDirectoryName.Clear();
if (item.Property is not null)
dateTimes = item.Property.GetDateTimes();
else
dateTimes = [new(item.FilePath.LastWriteTicks)];
if (item.Property is not null && item.Property.DateTimeOriginal is not null)
dateTime = item.Property.DateTimeOriginal.Value;
else if (item.Property is null)
dateTime = new(item.FilePath.LastWriteTicks);
else
dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
day = dateTime.ToString("MM-dd");
month = dateTime.ToString("MMMM");
if (item.Property?.Id is null)
{
flag = '#';
isWrongYear = null;
}
else
{
(isWrongYear, _) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(item.FilePath, item.Property.DateTimeOriginal, dateTimes);
if (isWrongYear is null)
flag = '#';
else if (isWrongYear.Value)
flag = '~';
else
{
if (item.Property.DateTimeOriginal is not null && dateTime.DayOfYear != item.Property.DateTimeOriginal.Value.DayOfYear && Math.Abs(new TimeSpan(dateTime.Ticks - item.Property.DateTimeOriginal.Value.Ticks).TotalHours) > 8)
flag = '^';
else
flag = '=';
}
}
(season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
if ((from l in topDirectorySegments where l == "Christmas" select true).Any())
seasonValue = string.Empty;
else
seasonValue = $".{season}";
if (isWrongYear is null || !isWrongYear.Value)
year = $"{flag}{dateTime:yyyy}{seasonValue}";
else if (matches is null || matches.Length < 3)
year = "----";
else
{
if (matches[0][0] != '~')
year = $"{flag}{matches[0].Split('.')[0]}{seasonValue}";
else
year = $"{flag}{matches[0][1..].Split('.')[0]}{seasonValue}";
}
topDirectoryName = Path.GetFileName(topDirectory);
weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
if (_Configuration.ByHash)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.BySeason && topDirectoryName.Length == 1 && topDirectoryName[0] == '_')
directoryNames.Add($"{year} {seasonName}");
else
{
if (!_Configuration.KeepFullPath)
{
if (topDirectoryName.Length > 1)
_ = destinationDirectoryName.Append(topDirectoryName);
if (_Configuration.BySeason)
directoryNames.AddRange([$"{destinationDirectoryName} {year} {seasonName}"]);
else if (_Configuration.ByDay)
directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year}-{day}"]);
else if (_Configuration.ByWeek)
directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year} {month}"]);
else
throw new Exception();
}
else
{
foreach (string sourceDirectoryNameSegment in topDirectorySegments)
{
if (matches is not null && matches.Contains(sourceDirectoryNameSegment))
_ = destinationDirectoryName.Append(year);
else
_ = destinationDirectoryName.Append(sourceDirectoryNameSegment);
}
if (_Configuration.BySeason)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.ByDay)
directoryNames.Add($"{weekOfYear}) {year} {day}");
else if (_Configuration.ByWeek)
directoryNames.Add($"{weekOfYear}) {month} {year}");
else
throw new Exception();
}
}
if (!_Configuration.ByHash || item.Property?.Id is null)
fileName = item.FilePath.Name;
else
fileName = $"{item.Property.Id.Value}{item.FilePath.ExtensionLowered}";
destinationCollection.Add(destinationDirectory);
destinationCollection.AddRange(directoryNames);
destinationCollection.Add(fileName);
if (item.Property is null)
results.Add(new(item, item.FilePath.LastWriteTicks, dateTime.Ticks, destinationCollection.ToArray()));
else
results.Add(new(item, item.Property.LastWriteTime.Ticks, dateTime.Ticks, destinationCollection.ToArray()));
}
return results;
}
private A_Property GetPropertyLogic(bool reverse, string outputExtension, string aResultsFullGroupDirectory)
{
A_Property result;
@ -302,54 +105,64 @@ public class DateGroup
return result;
}
private static Item[] GetFilterItems(Container.Models.Container container)
private static void CreateDateShortcut(Property.Models.Configuration configuration, Container.Models.Container[] containers)
{
List<Item> results = [];
foreach (Item item in container.Items)
{
if (item.FilePath is not null)
results.Add(item);
}
return results.ToArray();
}
private (Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] GetFileMoveCollectionAll(Property.Models.Configuration configuration, string destinationRoot, Container.Models.Container[] containers)
{
(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] results;
Item[] filteredItems;
string? topDirectory;
string? checkDirectory;
string destinationDirectory;
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollection = [];
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollectionDirectory;
string path;
string fileName;
string directory;
DateTime dateTime;
int selectedTotal;
const int minimum = 3;
List<DateTime> dateTimes;
List<Item> selectedItems;
const int maximumHours = 24;
string? relativePathDirectory;
WindowsShortcut windowsShortcut;
TimeSpan threeStandardDeviationHigh;
string aPropertyContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "()");
foreach (Container.Models.Container container in containers)
{
if (container.Items.Count == 0)
continue;
if (!_Configuration.KeepFullPath)
destinationDirectory = destinationRoot;
else
destinationDirectory = string.Concat(destinationRoot, container.SourceDirectory[configuration.RootDirectory.Length..]);
checkDirectory = Path.GetFullPath(container.SourceDirectory);
for (int z = 0; z < int.MaxValue; z++)
selectedTotal = 0;
threeStandardDeviationHigh = Property.Models.Stateless.IProperty.GetThreeStandardDeviationHigh(minimum, container);
if (threeStandardDeviationHigh.TotalHours > maximumHours)
threeStandardDeviationHigh = new(maximumHours, 0, 0);
for (int i = 0; i < container.Items.Count; i++)
{
if (checkDirectory == configuration.RootDirectory)
break;
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory))
break;
(i, dateTimes, selectedItems) = Property.Models.Stateless.IProperty.Get(container, threeStandardDeviationHigh, i);
selectedTotal += selectedItems.Count;
foreach (Item item in selectedItems)
{
if (item.ExifDirectory is null)
continue;
relativePathDirectory = Path.GetDirectoryName(item.RelativePath);
if (string.IsNullOrEmpty(relativePathDirectory))
continue;
if (item.ExifDirectory is null)
dateTime = new(item.FilePath.LastWriteTicks);
else if (item.ExifDirectory is not null && item.ExifDirectory.DateTimeOriginal is not null)
dateTime = item.ExifDirectory.DateTimeOriginal.Value;
else
dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.ExifDirectory);
path = Path.GetFullPath($"{configuration.RootDirectory}{item.RelativePath[..^5]}");
directory = Path.Combine($"{aPropertyContentDirectory}{relativePathDirectory}", $"{dateTimes.Min():yyyy-MM-dd_HH-mm-ss}---{dateTimes.Max():yyyy-MM-dd_HH-mm-ss}");
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
fileName = Path.Combine(directory, $"{Path.GetFileName(item.RelativePath[..^5])}.lnk");
if (File.Exists(fileName))
continue;
windowsShortcut = new() { Path = path };
windowsShortcut.Save(fileName);
windowsShortcut.Dispose();
if (!File.Exists(fileName))
continue;
File.SetLastWriteTime(fileName, dateTime);
}
}
if (string.IsNullOrEmpty(checkDirectory))
if (selectedTotal < container.Items.Count && selectedTotal < (from l in container.Items where l.Property is not null select true).Count())
continue;
topDirectory = checkDirectory;
filteredItems = GetFilterItems(container);
if (filteredItems.Length == 0)
continue;
fileMoveCollectionDirectory = GetMoveFileCollection(destinationDirectory, topDirectory, filteredItems);
fileMoveCollection.AddRange(fileMoveCollectionDirectory);
}
results = (from l in fileMoveCollection orderby l.MinimumDateTimeTicks descending, l.LastWriteTimeTicks descending select l).ToArray();
return results;
}
private void MoveFiles(Property.Models.Configuration configuration, string destinationRoot, Container.Models.Container[] containers)
@ -453,64 +266,251 @@ public class DateGroup
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(configuration.RootDirectory);
}
private static void CreateDateShortcut(Property.Models.Configuration configuration, Container.Models.Container[] containers)
private (Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] GetFileMoveCollectionAll(Property.Models.Configuration configuration, string destinationRoot, Container.Models.Container[] containers)
{
string path;
string fileName;
string directory;
DateTime dateTime;
int selectedTotal;
const int minimum = 3;
List<DateTime> dateTimes;
List<Item> selectedItems;
const int maximumHours = 24;
string? relativePathDirectory;
WindowsShortcut windowsShortcut;
TimeSpan threeStandardDeviationHigh;
string aPropertyContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "()");
(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)[] results;
Item[] filteredItems;
string? topDirectory;
string? checkDirectory;
string destinationDirectory;
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollection = [];
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> fileMoveCollectionDirectory;
foreach (Container.Models.Container container in containers)
{
if (container.Items.Count == 0)
continue;
selectedTotal = 0;
threeStandardDeviationHigh = Property.Models.Stateless.IProperty.GetThreeStandardDeviationHigh(minimum, container);
if (threeStandardDeviationHigh.TotalHours > maximumHours)
threeStandardDeviationHigh = new(maximumHours, 0, 0);
for (int i = 0; i < container.Items.Count; i++)
if (!_Configuration.KeepFullPath)
destinationDirectory = destinationRoot;
else
destinationDirectory = string.Concat(destinationRoot, container.SourceDirectory[configuration.RootDirectory.Length..]);
checkDirectory = Path.GetFullPath(container.SourceDirectory);
for (int z = 0; z < int.MaxValue; z++)
{
(i, dateTimes, selectedItems) = Property.Models.Stateless.IProperty.Get(container, threeStandardDeviationHigh, i);
selectedTotal += selectedItems.Count;
foreach (Item item in selectedItems)
if (checkDirectory == configuration.RootDirectory)
break;
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory))
break;
}
if (string.IsNullOrEmpty(checkDirectory))
continue;
topDirectory = checkDirectory;
filteredItems = GetFilterItems(container);
if (filteredItems.Length == 0)
continue;
fileMoveCollectionDirectory = GetMoveFileCollection(destinationDirectory, topDirectory, filteredItems);
fileMoveCollection.AddRange(fileMoveCollectionDirectory);
}
results = (from l in fileMoveCollection orderby l.MinimumDateTimeTicks descending, l.LastWriteTimeTicks descending select l).ToArray();
return results;
}
private static Item[] GetFilterItems(Container.Models.Container container)
{
List<Item> results = [];
foreach (Item item in container.Items)
{
if (item.FilePath is not null)
results.Add(item);
}
return results.ToArray();
}
private List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> GetMoveFileCollection(string destinationDirectory, string topDirectory, Item[] filteredItems)
{
List<(Item Item, long LastWriteTimeTicks, long MinimumDateTimeTicks, string[] Destination)> results = [];
char flag;
string day;
int season;
string year;
string month;
string? check;
string fileName;
string? pathRoot;
DateTime dateTime;
string seasonName;
string weekOfYear;
bool? isWrongYear;
string seasonValue;
string directoryName;
string topDirectoryName;
List<DateTime> dateTimes;
string[]? matches = null;
string[] directorySegments;
List<string> destinationCollection;
List<string> directoryNames = [];
List<string> topDirectorySegments = [];
StringBuilder destinationDirectoryName = new();
Calendar calendar = new CultureInfo("en-US").Calendar;
for (int z = 1; z < 3; z++)
{
if (z == 1)
{
check = Path.Combine(destinationDirectory, ".");
pathRoot = Path.GetPathRoot(destinationDirectory);
}
else if (z == 2)
{
check = Path.Combine(topDirectory, ".");
pathRoot = Path.GetPathRoot(topDirectory);
}
else
throw new Exception();
if (string.IsNullOrEmpty(pathRoot))
continue;
for (int i = 0; i < int.MaxValue; i++)
{
check = Path.GetDirectoryName(check);
if (string.IsNullOrEmpty(check) || check == pathRoot)
break;
directoryName = Path.GetFileName(check);
directorySegments = directoryName.Split(' ');
topDirectorySegments.AddRange(directorySegments);
(_, matches) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(directorySegments, string.Empty);
if (matches.Length != 0)
break;
}
if (matches is not null && matches.Length != 0)
break;
}
foreach (Item item in filteredItems)
{
directoryNames.Clear();
destinationCollection = [];
_ = destinationDirectoryName.Clear();
if (item.ExifDirectory is not null)
dateTimes = item.ExifDirectory.GetDateTimes();
else
dateTimes = [new(item.FilePath.LastWriteTicks)];
if (item.ExifDirectory is not null && item.ExifDirectory.DateTimeOriginal is not null)
dateTime = item.ExifDirectory.DateTimeOriginal.Value;
else if (item.ExifDirectory is null)
dateTime = new(item.FilePath.LastWriteTicks);
else
dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.ExifDirectory);
day = dateTime.ToString("MM-dd");
month = dateTime.ToString("MMMM");
if (item.ExifDirectory?.FilePath.Id is null)
{
flag = '#';
isWrongYear = null;
}
else
{
(isWrongYear, _) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(item.FilePath, item.ExifDirectory.DateTimeOriginal, dateTimes);
if (isWrongYear is null)
flag = '#';
else if (isWrongYear.Value)
flag = '~';
else
{
if (item.Property is null)
continue;
relativePathDirectory = Path.GetDirectoryName(item.RelativePath);
if (string.IsNullOrEmpty(relativePathDirectory))
continue;
if (item.Property is null)
dateTime = new(item.FilePath.LastWriteTicks);
else if (item.Property is not null && item.Property.DateTimeOriginal is not null)
dateTime = item.Property.DateTimeOriginal.Value;
if (item.ExifDirectory.DateTimeOriginal is not null && dateTime.DayOfYear != item.ExifDirectory.DateTimeOriginal.Value.DayOfYear && Math.Abs(new TimeSpan(dateTime.Ticks - item.ExifDirectory.DateTimeOriginal.Value.Ticks).TotalHours) > 8)
flag = '^';
else
dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
path = Path.GetFullPath($"{configuration.RootDirectory}{item.RelativePath[..^5]}");
directory = Path.Combine($"{aPropertyContentDirectory}{relativePathDirectory}", $"{dateTimes.Min():yyyy-MM-dd_HH-mm-ss}---{dateTimes.Max():yyyy-MM-dd_HH-mm-ss}");
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
fileName = Path.Combine(directory, $"{Path.GetFileName(item.RelativePath[..^5])}.lnk");
if (File.Exists(fileName))
continue;
windowsShortcut = new() { Path = path };
windowsShortcut.Save(fileName);
windowsShortcut.Dispose();
if (!File.Exists(fileName))
continue;
File.SetLastWriteTime(fileName, dateTime);
flag = '=';
}
}
if (selectedTotal < container.Items.Count && selectedTotal < (from l in container.Items where l.Property is not null select true).Count())
continue;
(season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
if ((from l in topDirectorySegments where l == "Christmas" select true).Any())
seasonValue = string.Empty;
else
seasonValue = $".{season}";
if (isWrongYear is null || !isWrongYear.Value)
year = $"{flag}{dateTime:yyyy}{seasonValue}";
else if (matches is null || matches.Length < 3)
year = "----";
else
{
if (matches[0][0] != '~')
year = $"{flag}{matches[0].Split('.')[0]}{seasonValue}";
else
year = $"{flag}{matches[0][1..].Split('.')[0]}{seasonValue}";
}
topDirectoryName = Path.GetFileName(topDirectory);
weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
if (_Configuration.ByHash)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.BySeason && topDirectoryName.Length == 1 && topDirectoryName[0] == '_')
directoryNames.Add($"{year} {seasonName}");
else
{
if (!_Configuration.KeepFullPath)
{
if (topDirectoryName.Length > 1)
_ = destinationDirectoryName.Append(topDirectoryName);
if (_Configuration.BySeason)
directoryNames.AddRange([$"{destinationDirectoryName} {year} {seasonName}"]);
else if (_Configuration.ByDay)
directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year}-{day}"]);
else if (_Configuration.ByWeek)
directoryNames.AddRange([$"{destinationDirectoryName} {year}", $"{weekOfYear}) {year} {month}"]);
else
throw new Exception();
}
else
{
foreach (string sourceDirectoryNameSegment in topDirectorySegments)
{
if (matches is not null && matches.Contains(sourceDirectoryNameSegment))
_ = destinationDirectoryName.Append(year);
else
_ = destinationDirectoryName.Append(sourceDirectoryNameSegment);
}
if (_Configuration.BySeason)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.ByDay)
directoryNames.Add($"{weekOfYear}) {year} {day}");
else if (_Configuration.ByWeek)
directoryNames.Add($"{weekOfYear}) {month} {year}");
else
throw new Exception();
}
}
if (!_Configuration.ByHash || item.ExifDirectory?.FilePath.Id is null)
fileName = item.FilePath.Name;
else
fileName = $"{item.ExifDirectory.FilePath.Id.Value}{item.FilePath.ExtensionLowered}";
destinationCollection.Add(destinationDirectory);
destinationCollection.AddRange(directoryNames);
destinationCollection.Add(fileName);
if (item.ExifDirectory is null)
results.Add(new(item, item.FilePath.LastWriteTicks, dateTime.Ticks, destinationCollection.ToArray()));
else
results.Add(new(item, item.ExifDirectory.LastWriteTime.Ticks, dateTime.Ticks, destinationCollection.ToArray()));
}
return results;
}
private static bool WriteAllText(string path, string contents, bool compareBeforeWrite)
{
bool result;
string text;
if (!compareBeforeWrite)
result = true;
else
{
if (!File.Exists(path))
text = string.Empty;
else
text = File.ReadAllText(path);
result = text != contents;
}
if (result)
{
if (path.Contains("()"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("[]") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
File.WriteAllText(path, contents);
else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
File.WriteAllText(path, contents);
else
File.WriteAllText(path, contents);
}
return result;
}
}