LocationContainerDirectoryPattern

This commit is contained in:
Mike Phares 2023-09-10 00:20:01 -07:00
parent 4b8b942528
commit 5633430bfb
14 changed files with 659 additions and 609 deletions

1
.gitignore vendored
View File

@ -454,6 +454,7 @@ $RECYCLE.BIN/
!.vscode/extensions.json !.vscode/extensions.json
!Instance/.vscode/appsettings.example.json !Instance/.vscode/appsettings.example.json
!Rename/.vscode/appsettings.example.json !Rename/.vscode/appsettings.example.json
Shared/.vscode/ged
#VSCode Settings => mklink /J "VSCode Settings" "C:\Users\phares\AppData\Roaming\Code\User" #VSCode Settings => mklink /J "VSCode Settings" "C:\Users\phares\AppData\Roaming\Code\User"
globalStorage/ globalStorage/

View File

@ -843,6 +843,7 @@ public partial class DlibDotNet
configuration.FaceConfidencePercent, configuration.FaceConfidencePercent,
configuration.FaceDistancePermyriad, configuration.FaceDistancePermyriad,
configuration.LocationContainerDebugDirectory, configuration.LocationContainerDebugDirectory,
configuration.LocationContainerDirectoryPattern,
configuration.LocationContainerDistanceTake, configuration.LocationContainerDistanceTake,
configuration.LocationContainerDistanceTolerance, configuration.LocationContainerDistanceTolerance,
configuration.LocationDigits, configuration.LocationDigits,

View File

@ -33,6 +33,7 @@ public class Configuration
public string[]? LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } public string[]? LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; }
public bool? LoadPhotoPrismLocations { get; set; } public bool? LoadPhotoPrismLocations { get; set; }
public string? LocationContainerDebugDirectory { get; set; } public string? LocationContainerDebugDirectory { get; set; }
public string? LocationContainerDirectoryPattern { get; set; }
public int? LocationContainerDistanceTake { get; set; } public int? LocationContainerDistanceTake { get; set; }
public float? LocationContainerDistanceTolerance { get; set; } public float? LocationContainerDistanceTolerance { get; set; }
public int? LocationDigits { get; set; } public int? LocationDigits { get; set; }
@ -133,6 +134,7 @@ public class Configuration
// if (configuration?.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions)); // if (configuration?.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions));
if (configuration?.LoadPhotoPrismLocations is null) throw new NullReferenceException(nameof(configuration.LoadPhotoPrismLocations)); if (configuration?.LoadPhotoPrismLocations is null) throw new NullReferenceException(nameof(configuration.LoadPhotoPrismLocations));
if (configuration?.LocationContainerDebugDirectory is null) throw new NullReferenceException(nameof(configuration.LocationContainerDebugDirectory)); if (configuration?.LocationContainerDebugDirectory is null) throw new NullReferenceException(nameof(configuration.LocationContainerDebugDirectory));
if (configuration?.LocationContainerDirectoryPattern is null) throw new NullReferenceException(nameof(configuration.LocationContainerDirectoryPattern));
if (configuration?.LocationContainerDistanceTake is null) throw new NullReferenceException(nameof(configuration.LocationContainerDistanceTake)); if (configuration?.LocationContainerDistanceTake is null) throw new NullReferenceException(nameof(configuration.LocationContainerDistanceTake));
// if (configuration?.LocationContainerDistanceTolerance is null) throw new NullReferenceException(nameof(configuration.LocationContainerDistanceTolerance)); // if (configuration?.LocationContainerDistanceTolerance is null) throw new NullReferenceException(nameof(configuration.LocationContainerDistanceTolerance));
if (configuration?.LocationDigits is null) throw new NullReferenceException(nameof(configuration.LocationDigits)); if (configuration?.LocationDigits is null) throw new NullReferenceException(nameof(configuration.LocationDigits));
@ -220,6 +222,7 @@ public class Configuration
configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions ?? Array.Empty<string>(), configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions ?? Array.Empty<string>(),
configuration.LoadPhotoPrismLocations.Value, configuration.LoadPhotoPrismLocations.Value,
configuration.LocationContainerDebugDirectory, configuration.LocationContainerDebugDirectory,
configuration.LocationContainerDirectoryPattern,
configuration.LocationContainerDistanceTake.Value, configuration.LocationContainerDistanceTake.Value,
configuration.LocationContainerDistanceTolerance, configuration.LocationContainerDistanceTolerance,
configuration.LocationDigits.Value, configuration.LocationDigits.Value,

View File

@ -27,6 +27,7 @@ public record Configuration(Property.Models.Configuration PropertyConfiguration,
string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions,
bool LoadPhotoPrismLocations, bool LoadPhotoPrismLocations,
string LocationContainerDebugDirectory, string LocationContainerDebugDirectory,
string LocationContainerDirectoryPattern,
int LocationContainerDistanceTake, int LocationContainerDistanceTake,
float? LocationContainerDistanceTolerance, float? LocationContainerDistanceTolerance,
int LocationDigits, int LocationDigits,

View File

@ -6,6 +6,7 @@ public record Configuration(bool DeletePossibleDuplicates,
int FaceConfidencePercent, int FaceConfidencePercent,
int FaceDistancePermyriad, int FaceDistancePermyriad,
string LocationContainerDebugDirectory, string LocationContainerDebugDirectory,
string LocationContainerDirectoryPattern,
int LocationContainerDistanceTake, int LocationContainerDistanceTake,
float? LocationContainerDistanceTolerance, float? LocationContainerDistanceTolerance,
int LocationDigits, int LocationDigits,

View File

@ -21,7 +21,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
internal record Record(string? DebugDirectory, internal record Record(string? DebugDirectory,
string? Directory, string? Directory,
long? Ticks, long? Ticks,
string PersonDirectory); string? PersonDirectory);
public void SaveContainers(int? updated, List<SaveContainer> saveContainers) public void SaveContainers(int? updated, List<SaveContainer> saveContainers)
{ {
@ -263,7 +263,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
readOnlyPersonKeyFormattedCollection = new(personKeyFormattedCollection); readOnlyPersonKeyFormattedCollection = new(personKeyFormattedCollection);
readOnlyPersonKeyFormattedToNewestPersonKeyFormatted = new(personKeyFormattedToNewestPersonKeyFormatted); readOnlyPersonKeyFormattedToNewestPersonKeyFormatted = new(personKeyFormattedToNewestPersonKeyFormatted);
} }
List<Stateless.MapLogic.Record> records = Stateless.MapLogic.DeleteEmptyDirectoriesAndGetCollection(configuration, ticks, eDistanceContentDirectory, readOnlyPersonKeyFormattedToNewestPersonKeyFormatted, readOnlyPersonKeyFormattedCollection); List<Stateless.Record> records = Stateless.DistanceLogic.DeleteEmptyDirectoriesAndGetCollection(configuration, ticks, eDistanceContentDirectory, readOnlyPersonKeyFormattedToNewestPersonKeyFormatted, readOnlyPersonKeyFormattedCollection);
ReadOnlyCollection<(Stateless.MapLogic.PersonKeyFormattedIdThenWholePercentages, PersonContainer)> readOnlyPossiblyNewPersonDisplayDirectoryNamesAndPersonContainer; ReadOnlyCollection<(Stateless.MapLogic.PersonKeyFormattedIdThenWholePercentages, PersonContainer)> readOnlyPossiblyNewPersonDisplayDirectoryNamesAndPersonContainer;
ReadOnlyCollection<Stateless.MapLogic.PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection = Stateless.MapLogic.GetPersonKeyFormattedIdThenWholePercentages(configuration, ticks, records); ReadOnlyCollection<Stateless.MapLogic.PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection = Stateless.MapLogic.GetPersonKeyFormattedIdThenWholePercentages(configuration, ticks, records);
// //
@ -509,12 +509,12 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
long? ticks; long? ticks;
string? directory; string? directory;
string? debugDirectory; string? debugDirectory;
string personDirectory; string? personDirectory;
if (question.MappingFromPerson is null) if (question.MappingFromPerson is null)
{ {
debugDirectory = null; debugDirectory = null;
(ticks, directory) = GetDirectory(configuration, saveIndividually, padLeft, question.SegmentC, by, question.MappingFromItem); (ticks, directory) = GetDirectory(configuration, saveIndividually, padLeft, question.SegmentC, by, question.MappingFromItem);
personDirectory = directory is null ? string.Empty : Path.Combine(directory, $"X+{ticks}"); personDirectory = directory is null ? null : Path.Combine(directory, $"X+{ticks}");
} }
else else
{ {
@ -551,6 +551,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
FileHolder faceFileHolder; FileHolder faceFileHolder;
string facePartsDirectory; string facePartsDirectory;
SaveContainer? saveContainer; SaveContainer? saveContainer;
int? distancePermyriad = null;
FileHolder facePartsFileHolder; FileHolder facePartsFileHolder;
FileHolder hiddenFaceFileHolder; FileHolder hiddenFaceFileHolder;
ReadOnlyDictionary<int, Mapping>? wholePercentagesToMapping; ReadOnlyDictionary<int, Mapping>? wholePercentagesToMapping;
@ -570,7 +571,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
continue; continue;
if (mapping.MappingFromFilterPost.IsFocusPerson is not null && !mapping.MappingFromFilterPost.IsFocusPerson.Value) if (mapping.MappingFromFilterPost.IsFocusPerson is not null && !mapping.MappingFromFilterPost.IsFocusPerson.Value)
continue; continue;
(by, isByMapping, isBySorting) = Stateless.MapLogic.Get(useFiltersCounter, saveIndividually, sortingContainersAny, forceSingleImageHumanized, mapping); (by, isByMapping, isBySorting) = Stateless.MapLogic.Get(useFiltersCounter, saveIndividually, sortingContainersAny, forceSingleImageHumanized, distancePermyriad, mapping);
if (isByMapping && !saveMapped) if (isByMapping && !saveMapped)
continue; continue;
if (!isBySorting || mapping.SortingContainer is null) if (!isBySorting || mapping.SortingContainer is null)
@ -586,8 +587,8 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
continue; continue;
} }
record = Get(_Configuration, saveIndividually, by, mapping, padLeft); record = Get(_Configuration, saveIndividually, by, mapping, padLeft);
if (string.IsNullOrEmpty(record.Directory)) if (string.IsNullOrEmpty(record.Directory) || string.IsNullOrEmpty(record.PersonDirectory))
throw new NotSupportedException(); continue;
directory = record.Directory; directory = record.Directory;
if (mapping.MappingFromPerson is not null) if (mapping.MappingFromPerson is not null)
{ {
@ -736,7 +737,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
foreach (SortingContainer sortingContainer in sortingContainers) foreach (SortingContainer sortingContainer in sortingContainers)
{ {
if (sortingContainer.Question is null) if (sortingContainer.Question is null)
throw new NotSupportedException(); continue;
if (sortingContainer.Source.MappingFromPerson is null) if (sortingContainer.Source.MappingFromPerson is null)
{ {
sortingContainer.Question.UpdateMappingFromUnknownPerson(_Configuration.SaveIndividually, sortingContainer); sortingContainer.Question.UpdateMappingFromUnknownPerson(_Configuration.SaveIndividually, sortingContainer);
@ -788,6 +789,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
SaveContainer? saveContainer; SaveContainer? saveContainer;
FileHolder? facePartsFileHolder; FileHolder? facePartsFileHolder;
FileHolder? hiddenFaceFileHolder; FileHolder? hiddenFaceFileHolder;
bool sortingContainersAny = sortingContainers.Count > 0;
int padLeft = _Configuration.FaceDistancePermyriad.ToString().Length; int padLeft = _Configuration.FaceDistancePermyriad.ToString().Length;
string forceSingleImageHumanized = nameof(Shared.Models.Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title); string forceSingleImageHumanized = nameof(Shared.Models.Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title);
foreach (SortingContainer sortingContainer in sortingContainers) foreach (SortingContainer sortingContainer in sortingContainers)
@ -795,15 +797,15 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
if (sortingContainer.Question is null) if (sortingContainer.Question is null)
throw new NotSupportedException(); throw new NotSupportedException();
isCounterPersonYear = sortingContainer.Source.MappingFromPerson is not null && IPersonBirthday.IsCounterPersonYear(sortingContainer.Source.MappingFromPerson.PersonKey); isCounterPersonYear = sortingContainer.Source.MappingFromPerson is not null && IPersonBirthday.IsCounterPersonYear(sortingContainer.Source.MappingFromPerson.PersonKey);
(by, _, isBySorting) = Stateless.MapLogic.Get(useFiltersCounter, _Configuration.SaveIndividually, sortingContainers.Count > 0, forceSingleImageHumanized, sortingContainer.Question); (by, _, isBySorting) = Stateless.MapLogic.Get(useFiltersCounter, _Configuration.SaveIndividually, sortingContainersAny, forceSingleImageHumanized, sortingContainer.Sorting.DistancePermyriad, sortingContainer.Question);
question = sortingContainer.Question.MappingFromPerson is null ? sortingContainer.Source : sortingContainer.Question; question = sortingContainer.Question.MappingFromPerson is null ? sortingContainer.Source : sortingContainer.Question;
if (question is null) if (question is null)
throw new NotSupportedException(); throw new NotSupportedException();
if (question.MappingFromLocation is null) if (question.MappingFromLocation is null)
continue; continue;
record = Get(_Configuration, _Configuration.SaveIndividually, by, question, padLeft); record = Get(_Configuration, _Configuration.SaveIndividually, by, question, padLeft);
if (string.IsNullOrEmpty(record.Directory)) if (string.IsNullOrEmpty(record.Directory) || string.IsNullOrEmpty(record.PersonDirectory))
throw new NotSupportedException(); continue;
directory = record.Directory; directory = record.Directory;
if (!string.IsNullOrEmpty(record.DebugDirectory)) if (!string.IsNullOrEmpty(record.DebugDirectory))
results.Add(new(record.DebugDirectory)); results.Add(new(record.DebugDirectory));

View File

@ -0,0 +1,452 @@
using Humanizer;
using ShellProgressBar;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Map.Models.Stateless;
internal record Record(string PersonKeyFormatted,
int DirectoryNumber,
string? PersonDisplayDirectoryName,
bool? IsDefault,
string MappedFaceFile);
internal abstract class DistanceLogic
{
internal record TicksDirectory(string Directory,
string DirectoryName,
DateTime DirectoryDateTime,
DateTime AlternateDirectoryDateTime,
float? TotalDays);
private static void MoveTo(string actionDirectory, TicksDirectory ticksDirectory, string directory, string personKeyFormatted, string yearDirectoryName, string alphaDirectoryName, string[] files, string[] facesFileNames)
{
string checkFile;
string actionDirectoryName = Path.GetFileName(actionDirectory);
string checkDirectory = actionDirectoryName.StartsWith("y", StringComparison.CurrentCultureIgnoreCase) ? Path.Combine(ticksDirectory.Directory, personKeyFormatted, yearDirectoryName, alphaDirectoryName) : Path.Combine(directory, actionDirectoryName);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
foreach (string file in files)
{
if (facesFileNames.Contains(file))
{
checkFile = Path.Combine(checkDirectory, Path.GetFileName(file));
if (File.Exists(checkFile))
continue;
File.Move(file, checkFile);
continue;
}
File.Delete(file);
}
}
private static void MoveFiles(string personKeyFormatted, string personKeyDirectory, string newestPersonKeyFormatted, string newestPersonKeyDirectory)
{
string[] files;
string checkFile;
string? checkDirectory;
string[] directories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string directory in directories)
{
checkDirectory = Path.Combine(newestPersonKeyDirectory, Path.GetFileName(directory));
if (!Directory.Exists(checkDirectory))
Directory.Move(directory, checkDirectory);
else
{
files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
foreach (string file in files)
{
if (file.Split(personKeyFormatted).Length != 2 || file.Contains(newestPersonKeyFormatted))
continue;
checkFile = file.Replace(personKeyFormatted, newestPersonKeyFormatted);
checkDirectory = Path.GetDirectoryName(checkFile);
if (checkDirectory is null)
continue;
if (File.Exists(checkFile))
continue;
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
File.Move(file, checkFile);
}
}
}
_ = IPath.DeleteEmptyDirectories(personKeyDirectory);
}
private static List<TicksDirectory> UpdateDateVerifyAndGetTicksDirectories(Configuration configuration, string eDistanceContentDirectory)
{
List<TicksDirectory> results = new();
float? totalDays;
long? next = null;
string? checkDirectory;
string ticksDirectoryName;
DateTime directoryDateTime;
DirectoryInfo directoryInfo;
long? lastDirectoryTicks = null;
DateTime dateTime = DateTime.Now;
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[] ticksDirectories = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string ticksDirectory in ticksDirectories)
{
ticksDirectoryName = Path.GetFileName(ticksDirectory);
if (ticksDirectoryName.Length < 3)
continue;
if (!long.TryParse(ticksDirectoryName, out long directoryTicks))
throw new NotSupportedException();
if (next is null)
next = new DateTime(directoryTicks).Ticks;
else
{
next += month;
checkDirectory = Path.GetDirectoryName(ticksDirectory);
if (string.IsNullOrEmpty(checkDirectory))
{
if (string.IsNullOrEmpty(checkDirectory))
continue;
checkDirectory = Path.Combine(checkDirectory, next.Value.ToString());
if (ticksDirectory == checkDirectory || !checkDirectory.EndsWith(configuration.LocationContainerDirectoryPattern))
continue;
Directory.Move(ticksDirectory, checkDirectory);
continue;
}
}
directoryInfo = new(ticksDirectory);
directoryDateTime = new DateTime(directoryTicks);
if (directoryInfo.CreationTime.Ticks != directoryTicks)
Directory.SetCreationTime(ticksDirectory, new DateTime(directoryTicks));
if (directoryInfo.LastWriteTime.Ticks != directoryTicks)
Directory.SetLastWriteTime(ticksDirectory, new DateTime(directoryTicks));
totalDays = lastDirectoryTicks is null || new TimeSpan(dateTime.Ticks - directoryTicks).TotalDays < 1 ? null : (float)new TimeSpan(directoryTicks - lastDirectoryTicks.Value).TotalDays;
results.Add(new(ticksDirectory, ticksDirectoryName, new(directoryTicks), new DateTime(directoryDateTime.Year, directoryDateTime.Month, directoryDateTime.Day).AddMonths(1), totalDays));
if (directoryDateTime.Hour == 0 && directoryDateTime.Minute == 0 && directoryDateTime.Second == 0)
continue;
lastDirectoryTicks = directoryTicks;
}
string[] compare = (from l in results where l.TotalDays is not null and < 9.95f select l.Directory).ToArray();
if (compare.Length > 0 && configuration.ReMap)
throw new Exception($"Please Consolidate <{string.Join(Environment.NewLine, compare)}>");
return results;
}
private static void Individually(Configuration configuration, TicksDirectory ticksDirectory, string directory)
{
bool isDefault;
string[] files;
FileInfo[] collection;
string[] facesFileNames;
string yearDirectoryName;
string[] yearDirectories;
string alphaDirectoryName;
string matchDirectoryName;
string personKeyFormatted;
string[] alphaDirectories;
string[] matchDirectories;
string[] actionDirectories;
string personDisplayDirectory;
string[] personKeyDirectories;
string[] segmentCDirectories = Directory.GetDirectories(directory, "*", SearchOption.TopDirectoryOnly);
foreach (string segmentCDirectory in segmentCDirectories)
{
personKeyDirectories = Directory.GetDirectories(segmentCDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string personKeyDirectory in personKeyDirectories)
{
personKeyFormatted = Path.GetFileName(personKeyDirectory);
yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string yearDirectory in yearDirectories)
{
yearDirectoryName = Path.GetFileName(yearDirectory);
if (yearDirectoryName.StartsWith('='))
Directory.Move(yearDirectory, yearDirectory.Replace('=', '~'));
}
yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string yearDirectory in yearDirectories)
{
yearDirectoryName = Path.GetFileName(yearDirectory);
matchDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly);
alphaDirectories = matchDirectories.Where(l => !long.TryParse(Path.GetFileName(l), out long a)).ToArray();
if (alphaDirectories.Length == 0)
continue;
alphaDirectoryName = Path.GetFileName(alphaDirectories[0]);
foreach (string matchDirectory in matchDirectories)
{
matchDirectoryName = Path.GetFileName(matchDirectory);
files = Directory.GetFiles(matchDirectory, "*", SearchOption.TopDirectoryOnly);
if (files.Length != 4)
continue;
collection = files.Select(l => new FileInfo(l)).ToArray();
isDefault = IPerson.IsDefaultName(alphaDirectoryName) && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]);
if (isDefault)
facesFileNames = (from l in collection where l.Extension == configuration.FacesFileNameExtension select l.FullName).ToArray();
else
facesFileNames = (from l in collection where l.Extension == configuration.FacesFileNameExtension && l.Name.Contains(matchDirectoryName) select l.FullName).ToArray();
if (facesFileNames.Length == 0)
continue;
personDisplayDirectory = Path.Combine(matchDirectory, alphaDirectoryName);
if (!Directory.Exists(personDisplayDirectory) || !Directory.Exists(matchDirectory))
continue;
_ = Process.Start("explorer", matchDirectory);
for (int i = 0; i < int.MaxValue; i++)
{
Thread.Sleep(500);
actionDirectories = Directory.GetDirectories(matchDirectory, "*", SearchOption.TopDirectoryOnly).Where(l => l != personDisplayDirectory && !l.EndsWith("Maybe")).ToArray();
if (actionDirectories.Length > 0)
{
MoveTo(actionDirectories[0], ticksDirectory, directory, personKeyFormatted, yearDirectoryName, alphaDirectoryName, files, facesFileNames);
break;
}
}
}
}
}
}
}
private static List<Record> GetRecords(Configuration configuration, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, List<string> distinct, string? personDisplayDirectoryName)
{
List<Record> results = new();
int? id;
string fileName;
string checkFile;
int? wholePercentages;
foreach (string mappedFaceFile in files)
{
if (mappedFaceFile.EndsWith(".lnk"))
continue;
(id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFaceFile);
if (id is null || wholePercentages is null)
continue;
fileName = Path.GetFileName(mappedFaceFile);
if (distinct.Contains(fileName))
{
checkFile = $"{mappedFaceFile}.dup";
if (File.Exists(checkFile))
continue;
File.Move(mappedFaceFile, checkFile);
continue;
}
distinct.Add(fileName);
results.Add(new(personKeyFormatted, directoryNumber, personDisplayDirectoryName, isDefault, mappedFaceFile));
}
return results;
}
private static void RenameUnknown(string[] files)
{
foreach (string file in files)
{
if (file.EndsWith(".unk"))
continue;
File.Move(file, $"{file}.unk");
}
}
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);
}
internal static List<Record> DeleteEmptyDirectoriesAndGetCollection(Configuration configuration, long ticks, string eDistanceContentDirectory, ReadOnlyDictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted, ReadOnlyCollection<string> personKeyFormattedCollection)
{
List<Record> results = new();
bool check;
string message;
string[] files;
bool? isDefault;
int totalSeconds;
DateTime dateTime;
TimeSpan timeSpan;
int directoryNumber;
string? checkDirectory;
ProgressBar progressBar;
string[] yearDirectories;
string personKeyFormatted;
string? personFirstInitial;
bool isReservedDirectoryName;
List<string> distinct = new();
string[] personNameDirectories;
string? newestPersonKeyFormatted;
string? personDisplayDirectoryName;
string[] personNameLinkDirectories;
string? personFirstInitialDirectory;
List<TicksDirectory> ticksDirectories;
string[] personKeyFormattedDirectories;
string manualCopyHumanized = nameof(Shared.Models.Stateless.IMapLogic.ManualCopy).Humanize(LetterCasing.Title);
string forceSingleImageHumanized = nameof(Shared.Models.Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title);
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
for (int i = 1; i < 6; i++)
{
check = false;
results.Clear();
distinct.Clear();
directoryNumber = 0;
ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(configuration, eDistanceContentDirectory);
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
message = $"{i}) {ticksDirectories.Count:000} compile from and clean ticks Director(ies) - B - {totalSeconds} total second(s)";
progressBar = new(ticksDirectories.Count, message, options);
foreach (TicksDirectory ticksDirectory in ticksDirectories)
{
if (i == 1)
progressBar.Tick();
personKeyFormattedDirectories = Directory.GetDirectories(ticksDirectory.Directory, "*", SearchOption.TopDirectoryOnly);
foreach (string personKeyFormattedDirectory in personKeyFormattedDirectories)
{
personKeyFormatted = Path.GetFileName(personKeyFormattedDirectory);
isReservedDirectoryName = personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Sorting)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Mapping)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.ManualCopy));
if (!isReservedDirectoryName && personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Individually)))
{
Individually(configuration, ticksDirectory, personKeyFormattedDirectory);
throw new Exception($"B) Move personKey directories up one from {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} and delete {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} directory!");
}
_ = personKeyFormattedToNewestPersonKeyFormatted.TryGetValue(personKeyFormatted, out newestPersonKeyFormatted);
if (personKeyFormattedToNewestPersonKeyFormatted.Count > 0 && newestPersonKeyFormatted is null)
{
timeSpan = new TimeSpan(DateTime.Now.Ticks - ticksDirectory.DirectoryDateTime.Ticks);
if (timeSpan.TotalDays > 6)
throw new Exception($"{configuration.MappingDefaultName} <{ticksDirectory.DirectoryDateTime}> are only allowed within x days!");
}
yearDirectories = Directory.GetDirectories(personKeyFormattedDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string yearDirectory in yearDirectories)
{
if (check && !Directory.Exists(yearDirectory))
continue;
if (ticksDirectory.DirectoryName != configuration.LocationContainerDebugDirectory)
{
files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
File.Delete(file);
}
if (ticksDirectory.DirectoryName == configuration.LocationContainerDebugDirectory)
{
isDefault = null;
personDisplayDirectoryName = null;
files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly);
results.AddRange(GetRecords(configuration, isDefault, files, directoryNumber, personKeyFormatted, distinct, personDisplayDirectoryName));
files = Directory.GetFiles(yearDirectory, "*.lnk", SearchOption.AllDirectories);
foreach (string file in files)
File.Delete(file);
continue;
}
personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly);
if (personNameDirectories.Length > 1)
throw new NotSupportedException();
foreach (string personNameDirectory in personNameDirectories)
{
directoryNumber++;
personDisplayDirectoryName = Path.GetFileName(personNameDirectory);
isDefault = IPerson.IsDefaultName(personDisplayDirectoryName) && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]);
if (isDefault.Value && personDisplayDirectoryName.Length == 1)
{
if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length || !DateTime.TryParseExact(personKeyFormatted, configuration.PersonBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
continue;
checkDirectory = Path.Combine(yearDirectory, $"X+{dateTime.Ticks}");
if (Directory.Exists(checkDirectory))
{
Directory.Delete(yearDirectory, recursive: true);
continue;
}
Directory.Move(personNameDirectory, checkDirectory);
if (!check)
check = true;
continue;
}
if (isDefault.Value && (ticksDirectory.DirectoryDateTime.Hour != 0 || ticksDirectory.DirectoryDateTime.Minute != 0 || ticksDirectory.DirectoryDateTime.Second != 0))
{
checkDirectory = Path.GetDirectoryName(ticksDirectory.Directory);
if (checkDirectory is null)
continue;
checkDirectory = Path.Combine(checkDirectory, ticksDirectory.AlternateDirectoryDateTime.Ticks.ToString());
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
checkDirectory = Path.Combine(checkDirectory, personKeyFormatted);
if (!Directory.Exists(checkDirectory))
{
Directory.Move(personKeyFormattedDirectory, checkDirectory);
if (!check)
check = true;
break;
}
}
files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly);
if (isReservedDirectoryName && files.Length > 0)
throw new Exception($"Move personKey directories up one from {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} and delete {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} directory!");
if (personKeyFormatted == manualCopyHumanized && files.Length > 0)
throw new Exception($"Move personKey directories up one from {manualCopyHumanized} and delete {manualCopyHumanized} directory!");
if (personKeyFormatted == forceSingleImageHumanized && files.Length > 0)
throw new Exception($"Move personKey directories up one from {forceSingleImageHumanized} and delete {forceSingleImageHumanized} directory!");
if (!isDefault.Value)
{
if (personKeyFormattedToNewestPersonKeyFormatted.Count > 0 && newestPersonKeyFormatted is null)
RenameUnknown(files);
else if (newestPersonKeyFormatted is not null && personKeyFormatted != newestPersonKeyFormatted)
{
if (!check)
check = true;
MovedToNewestPersonKeyFormatted(personKeyFormatted, newestPersonKeyFormatted, ticksDirectory, personKeyFormattedDirectory);
continue;
}
}
if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length)
continue;
if (personDisplayDirectoryName.Length == 1 || isDefault.Value || !personKeyFormattedCollection.Contains(personKeyFormatted))
personFirstInitialDirectory = personNameDirectory;
else
{
personFirstInitial = personDisplayDirectoryName[..1];
if (personFirstInitial.All(l => char.IsDigit(l)))
{
foreach (string file in files)
File.Delete(file);
files = Directory.GetFiles(personNameDirectory, "*", SearchOption.AllDirectories);
foreach (string file in files)
File.Delete(file);
_ = IPath.DeleteEmptyDirectories(personNameDirectory);
continue;
}
personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial.ToString());
if (Directory.Exists(personFirstInitialDirectory))
throw new Exception("Forgot to ...");
Directory.Move(personNameDirectory, personFirstInitialDirectory);
files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
}
results.AddRange(GetRecords(configuration, isDefault, files, directoryNumber, personKeyFormatted, distinct, personDisplayDirectoryName));
personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string personNameLinkDirectory in personNameLinkDirectories)
{
files = Directory.GetFiles(personNameLinkDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
if (!file.EndsWith(".lnk"))
continue;
File.Delete(file);
}
_ = IPath.DeleteEmptyDirectories(personNameLinkDirectory);
}
_ = IPath.DeleteEmptyDirectories(personFirstInitialDirectory);
}
_ = IPath.DeleteEmptyDirectories(yearDirectory);
}
_ = IPath.DeleteEmptyDirectories(personKeyFormattedDirectory);
}
_ = IPath.DeleteEmptyDirectories(ticksDirectory.Directory);
_ = IPath.DeleteEmptyDirectories(ticksDirectory.Directory);
}
progressBar.Dispose();
if (check)
continue;
break;
}
return results;
}
}

View File

@ -1,4 +1,3 @@
using Humanizer;
using ShellProgressBar; using ShellProgressBar;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
@ -14,12 +13,6 @@ namespace View_by_Distance.Map.Models.Stateless;
internal abstract class MapLogic internal abstract class MapLogic
{ {
internal record Record(string PersonKeyFormatted,
int DirectoryNumber,
string? PersonDisplayDirectoryName,
bool? IsDefault,
string MappedFaceFile);
internal record MappedFile(long PersonKey, internal record MappedFile(long PersonKey,
string PersonKeyFormatted, string PersonKeyFormatted,
string? PersonDisplayDirectoryName, string? PersonDisplayDirectoryName,
@ -31,12 +24,6 @@ internal abstract class MapLogic
string File, string File,
float? Percent); float? Percent);
internal record TicksDirectory(string Directory,
string DirectoryName,
DateTime DirectoryDateTime,
DateTime AlternateDirectoryDateTime,
float? TotalDays);
internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted, internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted,
string? PersonDisplayDirectoryName, string? PersonDisplayDirectoryName,
bool? IsDefault, bool? IsDefault,
@ -188,58 +175,10 @@ internal abstract class MapLogic
return new(results); return new(results);
} }
private static void MoveTo(string actionDirectory, TicksDirectory ticksDirectory, string directory, string personKeyFormatted, string yearDirectoryName, string alphaDirectoryName, string[] files, string[] facesFileNames) internal static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, MappingFromItem mappingFromItem)
{ {
string checkFile; string result = GetMappingSegmentB(ticks, personBirthday, approximateYears, mappingFromItem.GetDateTimeOriginalThenMinimumDateTime(), mappingFromItem.IsWrongYear);
string actionDirectoryName = Path.GetFileName(actionDirectory); return result;
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<MappedFile> GetDisplayDirectoryAllFiles(string fileNameExtension, string personBirthdayFormat, ReadOnlyCollection<PersonContainer> personContainers) private static List<MappedFile> GetDisplayDirectoryAllFiles(string fileNameExtension, string personBirthdayFormat, ReadOnlyCollection<PersonContainer> personContainers)
@ -293,149 +232,43 @@ internal abstract class MapLogic
} }
} }
private static List<TicksDirectory> UpdateDateVerifyAndGetTicksDirectories(Configuration configuration, string eDistanceContentDirectory) internal static string GetFacesDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dFacesContentDirectory, MappingFromItem mappingFromItem)
{ {
List<TicksDirectory> results = new(); string result;
float? totalDays; (string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, mappingFromItem.ImageFileHolder.NameWithoutExtension);
long? next = null; result = Path.Combine(dFacesContentDirectory, propertyConfiguration.ResultAllInOne, directoryName, mappingFromItem.ImageFileHolder.NameWithoutExtension);
string? checkDirectory; return result;
string ticksDirectoryName;
DateTime directoryDateTime;
DirectoryInfo directoryInfo;
long? lastDirectoryTicks = null;
DateTime dateTime = DateTime.Now;
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[] ticksDirectories = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string ticksDirectory in ticksDirectories)
{
ticksDirectoryName = Path.GetFileName(ticksDirectory);
if (!long.TryParse(ticksDirectoryName, out long directoryTicks))
throw new NotSupportedException();
if (next is null)
next = new DateTime(directoryTicks).Ticks;
else
{
next += month;
checkDirectory = Path.GetDirectoryName(ticksDirectory);
if (string.IsNullOrEmpty(checkDirectory))
{
if (!string.IsNullOrEmpty(checkDirectory))
Directory.Move(ticksDirectory, Path.Combine(checkDirectory, next.Value.ToString()));
continue;
}
}
directoryInfo = new(ticksDirectory);
directoryDateTime = new DateTime(directoryTicks);
if (directoryInfo.CreationTime.Ticks != directoryTicks)
Directory.SetCreationTime(ticksDirectory, new DateTime(directoryTicks));
if (directoryInfo.LastWriteTime.Ticks != directoryTicks)
Directory.SetLastWriteTime(ticksDirectory, new DateTime(directoryTicks));
totalDays = lastDirectoryTicks is null || new TimeSpan(dateTime.Ticks - directoryTicks).TotalDays < 1 ? null : (float)new TimeSpan(directoryTicks - lastDirectoryTicks.Value).TotalDays;
results.Add(new(ticksDirectory, ticksDirectoryName, new(directoryTicks), new DateTime(directoryDateTime.Year, directoryDateTime.Month, directoryDateTime.Day).AddMonths(1), totalDays));
if (directoryDateTime.Hour == 0 && directoryDateTime.Minute == 0 && directoryDateTime.Second == 0)
continue;
lastDirectoryTicks = directoryTicks;
}
string[] compare = (from l in results where l.TotalDays is not null and < 9.95f select l.Directory).ToArray();
if (compare.Length > 0 && configuration.ReMap)
throw new Exception($"Please Consolidate <{string.Join(Environment.NewLine, compare)}>");
return results;
} }
private static void Individually(Configuration configuration, TicksDirectory ticksDirectory, string directory) private static List<(string, long)> GetDirectoryAndTicksCollection(string[] jLinks, string personBirthdayFormat, string? rootDirectory)
{ {
bool isDefault; List<(string, long)> results = new();
string[] files; string directory;
FileInfo[] collection; DateTime dateTime;
string[] facesFileNames;
string yearDirectoryName;
string[] yearDirectories;
string alphaDirectoryName;
string matchDirectoryName;
string personKeyFormatted;
string[] alphaDirectories;
string[] matchDirectories;
string[] actionDirectories;
string personDisplayDirectory;
string[] personKeyDirectories; string[] personKeyDirectories;
string[] segmentCDirectories = Directory.GetDirectories(directory, "*", SearchOption.TopDirectoryOnly); string[] personDisplayDirectoryNames;
foreach (string segmentCDirectory in segmentCDirectories) string personKeyFormattedDirectoryName;
foreach (string jLink in jLinks)
{ {
personKeyDirectories = Directory.GetDirectories(segmentCDirectory, "*", SearchOption.TopDirectoryOnly); if (rootDirectory is null)
foreach (string personKeyDirectory in personKeyDirectories) continue;
directory = Path.Combine(rootDirectory, jLink);
if (!Directory.Exists(directory))
continue;
personDisplayDirectoryNames = Directory.GetDirectories(directory, "*", SearchOption.TopDirectoryOnly);
foreach (string personDisplayDirectoryName in personDisplayDirectoryNames)
{ {
personKeyFormatted = Path.GetFileName(personKeyDirectory); personKeyDirectories = Directory.GetDirectories(personDisplayDirectoryName, "*", SearchOption.TopDirectoryOnly);
yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string personKeyFormattedDirectory in personKeyDirectories)
foreach (string yearDirectory in yearDirectories)
{ {
yearDirectoryName = Path.GetFileName(yearDirectory); personKeyFormattedDirectoryName = Path.GetFileName(personKeyFormattedDirectory);
if (yearDirectoryName.StartsWith('=')) if (personKeyFormattedDirectoryName.Length != personBirthdayFormat.Length || !DateTime.TryParseExact(personKeyFormattedDirectoryName, personBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
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; continue;
alphaDirectoryName = Path.GetFileName(alphaDirectories[0]); results.Add((directory, dateTime.Ticks));
foreach (string matchDirectory in matchDirectories)
{
matchDirectoryName = Path.GetFileName(matchDirectory);
files = Directory.GetFiles(matchDirectory, "*", SearchOption.TopDirectoryOnly);
if (files.Length != 4)
continue;
collection = files.Select(l => new FileInfo(l)).ToArray();
isDefault = IPerson.IsDefaultName(alphaDirectoryName) && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]);
if (isDefault)
facesFileNames = (from l in collection where l.Extension == configuration.FacesFileNameExtension select l.FullName).ToArray();
else
facesFileNames = (from l in collection where l.Extension == configuration.FacesFileNameExtension && l.Name.Contains(matchDirectoryName) select l.FullName).ToArray();
if (facesFileNames.Length == 0)
continue;
personDisplayDirectory = Path.Combine(matchDirectory, alphaDirectoryName);
if (!Directory.Exists(personDisplayDirectory) || !Directory.Exists(matchDirectory))
continue;
_ = Process.Start("explorer", matchDirectory);
for (int i = 0; i < int.MaxValue; i++)
{
Thread.Sleep(500);
actionDirectories = Directory.GetDirectories(matchDirectory, "*", SearchOption.TopDirectoryOnly).Where(l => l != personDisplayDirectory && !l.EndsWith("Maybe")).ToArray();
if (actionDirectories.Length > 0)
{
MoveTo(actionDirectories[0], ticksDirectory, directory, personKeyFormatted, yearDirectoryName, alphaDirectoryName, files, facesFileNames);
break;
}
}
}
} }
} }
} }
} return results;
private static void RenameUnknown(string[] files)
{
foreach (string file in files)
{
if (file.EndsWith(".unk"))
continue;
File.Move(file, $"{file}.unk");
}
}
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 (long, PersonContainer)[] GetDistinctCollection(Configuration configuration, IEnumerable<PersonContainer> personContainers, Dictionary<long, List<PersonContainer>> personKeyToPersonContainerCollection, Dictionary<string, PersonContainer> personKeyFormattedToPersonContainer) private static (long, PersonContainer)[] GetDistinctCollection(Configuration configuration, IEnumerable<PersonContainer> personContainers, Dictionary<long, List<PersonContainer>> personKeyToPersonContainerCollection, Dictionary<string, PersonContainer> personKeyFormattedToPersonContainer)
@ -602,6 +435,7 @@ internal abstract class MapLogic
string file; string file;
long personKey; long personKey;
string fileName; string fileName;
string checkFile;
List<string> distinct = new(); List<string> distinct = new();
PersonBirthday? personBirthday; PersonBirthday? personBirthday;
results.AddRange(GetDisplayDirectoryAllFiles(configuration.FacesFileNameExtension, configuration.PersonBirthdayFormat, personContainers)); results.AddRange(GetDisplayDirectoryAllFiles(configuration.FacesFileNameExtension, configuration.PersonBirthdayFormat, personContainers));
@ -629,7 +463,10 @@ internal abstract class MapLogic
continue; continue;
if (!File.Exists(file)) if (!File.Exists(file))
continue; continue;
File.Move(file, file[..^4]); checkFile = file[..^4];
if (File.Exists(checkFile))
continue;
File.Move(file, checkFile);
results[i] = new(results[i].PersonKey, results[i].PersonKeyFormatted, results[i].PersonDisplayDirectoryName, results[i].DirectoryNumber, file[..^4]); results[i] = new(results[i].PersonKey, results[i].PersonKeyFormatted, results[i].PersonDisplayDirectoryName, results[i].DirectoryNumber, file[..^4]);
} }
return results; return results;
@ -721,12 +558,33 @@ internal abstract class MapLogic
} }
} }
internal static string GetFacesDirectory(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dFacesContentDirectory, MappingFromItem mappingFromItem) internal static (SaveContainer?, SaveContainer?) GetContainers(string facesFileNameExtension, string facePartsFileNameExtension, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dFacesContentDirectory, string d2FacePartsContentCollectionDirectory, string directory, Mapping keyMapping)
{ {
string result; SaveContainer? result;
(string directoryName, _) = IPath.GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, mappingFromItem.ImageFileHolder.NameWithoutExtension); SaveContainer? saveContainer;
result = Path.Combine(dFacesContentDirectory, propertyConfiguration.ResultAllInOne, directoryName, mappingFromItem.ImageFileHolder.NameWithoutExtension); if (keyMapping.MappingFromLocation is null)
return result; (result, saveContainer) = (null, null);
else
{
string? facePartsContentCollectionFile = GetFacePartsContentCollectionFile(facePartsFileNameExtension, d2FacePartsContentCollectionDirectory, keyMapping.MappingFromItem);
if (facePartsContentCollectionFile is null || !File.Exists(facePartsContentCollectionFile))
result = null;
else
{
string checkFile = Path.Combine(directory, $"{keyMapping.MappingFromItem.ImageFileHolder.Name}{facePartsFileNameExtension}");
result = new(checkFile, directory, new(facePartsContentCollectionFile));
}
string facesDirectory = GetFacesDirectory(propertyConfiguration, dFacesContentDirectory, keyMapping.MappingFromItem);
FileHolder faceFileHolder = new(Path.Combine(facesDirectory, $"{keyMapping.MappingFromLocation.DeterministicHashCodeKey}{keyMapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}"));
if (!faceFileHolder.Exists)
saveContainer = null;
else
{
string checkFile = Path.Combine(directory, $"{keyMapping.MappingFromLocation.DeterministicHashCodeKey}{keyMapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}");
saveContainer = new(checkFile, directory, faceFileHolder);
}
}
return (result, saveContainer);
} }
private static IEnumerable<(string, string)> GetCollection(string[] yearDirectories) private static IEnumerable<(string, string)> GetCollection(string[] yearDirectories)
@ -735,37 +593,6 @@ internal abstract class MapLogic
yield return new(l, Path.GetFileName(l)); yield return new(l, Path.GetFileName(l));
} }
private static List<(string, long)> GetDirectoryAndTicksCollection(string[] jLinks, string personBirthdayFormat, string? rootDirectory)
{
List<(string, long)> results = new();
string directory;
DateTime dateTime;
string[] personKeyDirectories;
string[] personDisplayDirectoryNames;
string personKeyFormattedDirectoryName;
foreach (string jLink in jLinks)
{
if (rootDirectory is null)
continue;
directory = Path.Combine(rootDirectory, jLink);
if (!Directory.Exists(directory))
continue;
personDisplayDirectoryNames = Directory.GetDirectories(directory, "*", SearchOption.TopDirectoryOnly);
foreach (string personDisplayDirectoryName in personDisplayDirectoryNames)
{
personKeyDirectories = Directory.GetDirectories(personDisplayDirectoryName, "*", SearchOption.TopDirectoryOnly);
foreach (string personKeyFormattedDirectory in personKeyDirectories)
{
personKeyFormattedDirectoryName = Path.GetFileName(personKeyFormattedDirectory);
if (personKeyFormattedDirectoryName.Length != personBirthdayFormat.Length || !DateTime.TryParseExact(personKeyFormattedDirectoryName, personBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
continue;
results.Add((directory, dateTime.Ticks));
}
}
}
return results;
}
private static List<(string, long)> GetGenealogicalDataCommunicationDirectories(string genealogicalDataCommunicationFile, string[] jLinks, string personBirthdayFormat) private static List<(string, long)> GetGenealogicalDataCommunicationDirectories(string genealogicalDataCommunicationFile, string[] jLinks, string personBirthdayFormat)
{ {
List<(string, long)> results; List<(string, long)> results;
@ -841,228 +668,6 @@ internal abstract class MapLogic
return results; return results;
} }
private static List<Record> GetRecords(Configuration configuration, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, List<string> distinct, string? personDisplayDirectoryName)
{
List<Record> results = new();
int? id;
string fileName;
string checkFile;
int? wholePercentages;
foreach (string mappedFaceFile in files)
{
if (mappedFaceFile.EndsWith(".lnk"))
continue;
(id, wholePercentages) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFaceFile);
if (id is null || wholePercentages is null)
continue;
fileName = Path.GetFileName(mappedFaceFile);
if (distinct.Contains(fileName))
{
checkFile = $"{mappedFaceFile}.dup";
if (File.Exists(checkFile))
continue;
File.Move(mappedFaceFile, checkFile);
continue;
}
distinct.Add(fileName);
results.Add(new(personKeyFormatted, directoryNumber, personDisplayDirectoryName, isDefault, mappedFaceFile));
}
return results;
}
internal static List<Record> DeleteEmptyDirectoriesAndGetCollection(Configuration configuration, long ticks, string eDistanceContentDirectory, ReadOnlyDictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted, ReadOnlyCollection<string> personKeyFormattedCollection)
{
List<Record> results = new();
bool check;
string message;
string[] files;
bool? isDefault;
int totalSeconds;
DateTime dateTime;
TimeSpan timeSpan;
int directoryNumber;
string? checkDirectory;
ProgressBar progressBar;
string[] yearDirectories;
string personKeyFormatted;
string? personFirstInitial;
bool isReservedDirectoryName;
List<string> distinct = new();
string[] personNameDirectories;
string? newestPersonKeyFormatted;
string? personDisplayDirectoryName;
string[] personNameLinkDirectories;
string? personFirstInitialDirectory;
List<TicksDirectory> ticksDirectories;
string[] personKeyFormattedDirectories;
string manualCopyHumanized = nameof(Shared.Models.Stateless.IMapLogic.ManualCopy).Humanize(LetterCasing.Title);
string forceSingleImageHumanized = nameof(Shared.Models.Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title);
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
for (int i = 1; i < 6; i++)
{
check = false;
results.Clear();
distinct.Clear();
directoryNumber = 0;
ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(configuration, eDistanceContentDirectory);
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
message = $"{i}) {ticksDirectories.Count:000} compile from and clean ticks Director(ies) - B - {totalSeconds} total second(s)";
progressBar = new(ticksDirectories.Count, message, options);
foreach (TicksDirectory ticksDirectory in ticksDirectories)
{
if (i == 1)
progressBar.Tick();
personKeyFormattedDirectories = Directory.GetDirectories(ticksDirectory.Directory, "*", SearchOption.TopDirectoryOnly);
foreach (string personKeyFormattedDirectory in personKeyFormattedDirectories)
{
personKeyFormatted = Path.GetFileName(personKeyFormattedDirectory);
isReservedDirectoryName = personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Sorting)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Mapping)) || personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.ManualCopy));
if (!isReservedDirectoryName && personKeyFormatted.StartsWith(nameof(Shared.Models.Stateless.IMapLogic.Individually)))
{
Individually(configuration, ticksDirectory, personKeyFormattedDirectory);
throw new Exception($"B) Move personKey directories up one from {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} and delete {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} directory!");
}
_ = personKeyFormattedToNewestPersonKeyFormatted.TryGetValue(personKeyFormatted, out newestPersonKeyFormatted);
if (personKeyFormattedToNewestPersonKeyFormatted.Count > 0 && newestPersonKeyFormatted is null)
{
timeSpan = new TimeSpan(DateTime.Now.Ticks - ticksDirectory.DirectoryDateTime.Ticks);
if (timeSpan.TotalDays > 6)
throw new Exception($"{configuration.MappingDefaultName} <{ticksDirectory.DirectoryDateTime}> are only allowed within x days!");
}
yearDirectories = Directory.GetDirectories(personKeyFormattedDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string yearDirectory in yearDirectories)
{
if (check && !Directory.Exists(yearDirectory))
continue;
if (ticksDirectory.DirectoryName != configuration.LocationContainerDebugDirectory)
{
files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
File.Delete(file);
}
if (ticksDirectory.DirectoryName == configuration.LocationContainerDebugDirectory)
{
isDefault = null;
personDisplayDirectoryName = null;
files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly);
results.AddRange(GetRecords(configuration, isDefault, files, directoryNumber, personKeyFormatted, distinct, personDisplayDirectoryName));
files = Directory.GetFiles(yearDirectory, "*.lnk", SearchOption.AllDirectories);
foreach (string file in files)
File.Delete(file);
continue;
}
personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly);
if (personNameDirectories.Length > 1)
throw new NotSupportedException();
foreach (string personNameDirectory in personNameDirectories)
{
directoryNumber++;
personDisplayDirectoryName = Path.GetFileName(personNameDirectory);
isDefault = IPerson.IsDefaultName(personDisplayDirectoryName) && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]);
if (isDefault.Value && personDisplayDirectoryName.Length == 1)
{
if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length || !DateTime.TryParseExact(personKeyFormatted, configuration.PersonBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
continue;
checkDirectory = Path.Combine(yearDirectory, $"X+{dateTime.Ticks}");
if (Directory.Exists(checkDirectory))
{
Directory.Delete(yearDirectory, recursive: true);
continue;
}
Directory.Move(personNameDirectory, checkDirectory);
if (!check)
check = true;
continue;
}
if (isDefault.Value && (ticksDirectory.DirectoryDateTime.Hour != 0 || ticksDirectory.DirectoryDateTime.Minute != 0 || ticksDirectory.DirectoryDateTime.Second != 0))
{
checkDirectory = Path.GetDirectoryName(ticksDirectory.Directory);
if (checkDirectory is null)
continue;
checkDirectory = Path.Combine(checkDirectory, ticksDirectory.AlternateDirectoryDateTime.Ticks.ToString());
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
checkDirectory = Path.Combine(checkDirectory, personKeyFormatted);
if (!Directory.Exists(checkDirectory))
{
Directory.Move(personKeyFormattedDirectory, checkDirectory);
if (!check)
check = true;
break;
}
}
files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly);
if (isReservedDirectoryName && files.Length > 0)
throw new Exception($"Move personKey directories up one from {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} and delete {nameof(Shared.Models.Stateless.IMapLogic.Sorting)} directory!");
if (personKeyFormatted == manualCopyHumanized && files.Length > 0)
throw new Exception($"Move personKey directories up one from {manualCopyHumanized} and delete {manualCopyHumanized} directory!");
if (personKeyFormatted == forceSingleImageHumanized && files.Length > 0)
throw new Exception($"Move personKey directories up one from {forceSingleImageHumanized} and delete {forceSingleImageHumanized} directory!");
if (!isDefault.Value)
{
if (personKeyFormattedToNewestPersonKeyFormatted.Count > 0 && newestPersonKeyFormatted is null)
RenameUnknown(files);
else if (newestPersonKeyFormatted is not null && personKeyFormatted != newestPersonKeyFormatted)
{
if (!check)
check = true;
MovedToNewestPersonKeyFormatted(personKeyFormatted, newestPersonKeyFormatted, ticksDirectory, personKeyFormattedDirectory);
continue;
}
}
if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length)
continue;
if (personDisplayDirectoryName.Length == 1 || isDefault.Value || !personKeyFormattedCollection.Contains(personKeyFormatted))
personFirstInitialDirectory = personNameDirectory;
else
{
personFirstInitial = personDisplayDirectoryName[..1];
if (personFirstInitial.All(l => char.IsDigit(l)))
{
foreach (string file in files)
File.Delete(file);
files = Directory.GetFiles(personNameDirectory, "*", SearchOption.AllDirectories);
foreach (string file in files)
File.Delete(file);
_ = IPath.DeleteEmptyDirectories(personNameDirectory);
continue;
}
personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial.ToString());
if (Directory.Exists(personFirstInitialDirectory))
throw new Exception("Forgot to ...");
Directory.Move(personNameDirectory, personFirstInitialDirectory);
files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
}
results.AddRange(GetRecords(configuration, isDefault, files, directoryNumber, personKeyFormatted, distinct, personDisplayDirectoryName));
personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string personNameLinkDirectory in personNameLinkDirectories)
{
files = Directory.GetFiles(personNameLinkDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
if (!file.EndsWith(".lnk"))
continue;
File.Delete(file);
}
_ = IPath.DeleteEmptyDirectories(personNameLinkDirectory);
}
_ = IPath.DeleteEmptyDirectories(personFirstInitialDirectory);
}
_ = IPath.DeleteEmptyDirectories(yearDirectory);
}
_ = IPath.DeleteEmptyDirectories(personKeyFormattedDirectory);
}
_ = IPath.DeleteEmptyDirectories(ticksDirectory.Directory);
_ = IPath.DeleteEmptyDirectories(ticksDirectory.Directory);
}
progressBar.Dispose();
if (check)
continue;
break;
}
return results;
}
internal static void SetKeyValuePairsAndAddToCollections(Configuration configuration, ReadOnlyCollection<PersonContainer> personContainers, Dictionary<long, PersonContainer> personKeyToPersonContainer, ReadOnlyCollection<PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection, Dictionary<long, int> personKeyToCount, Dictionary<string, PersonContainer> personKeyFormattedToPersonContainer, Dictionary<long, List<PersonContainer>> personKeyToPersonContainerCollection, List<(PersonKeyFormattedIdThenWholePercentages, PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) internal static void SetKeyValuePairsAndAddToCollections(Configuration configuration, ReadOnlyCollection<PersonContainer> personContainers, Dictionary<long, PersonContainer> personKeyToPersonContainer, ReadOnlyCollection<PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection, Dictionary<long, int> personKeyToCount, Dictionary<string, PersonContainer> personKeyFormattedToPersonContainer, Dictionary<long, List<PersonContainer>> personKeyToPersonContainerCollection, List<(PersonKeyFormattedIdThenWholePercentages, PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
{ {
PersonBirthday? personBirthday; PersonBirthday? personBirthday;
@ -1333,12 +938,6 @@ internal abstract class MapLogic
return result; return result;
} }
internal static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, MappingFromItem mappingFromItem)
{
string result = GetMappingSegmentB(ticks, personBirthday, approximateYears, mappingFromItem.GetDateTimeOriginalThenMinimumDateTime(), mappingFromItem.IsWrongYear);
return result;
}
internal static string? GetFacePartsContentCollectionFile(string extension, string d2FacePartsContentCollectionDirectory, MappingFromItem mappingFromItem) internal static string? GetFacePartsContentCollectionFile(string extension, string d2FacePartsContentCollectionDirectory, MappingFromItem mappingFromItem)
{ {
string? result; string? result;
@ -1373,35 +972,6 @@ internal abstract class MapLogic
return result; return result;
} }
internal static (SaveContainer?, SaveContainer?) GetContainers(string facesFileNameExtension, string facePartsFileNameExtension, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, string dFacesContentDirectory, string d2FacePartsContentCollectionDirectory, string directory, Mapping keyMapping)
{
SaveContainer? result;
SaveContainer? saveContainer;
if (keyMapping.MappingFromLocation is null)
(result, saveContainer) = (null, null);
else
{
string? facePartsContentCollectionFile = GetFacePartsContentCollectionFile(facePartsFileNameExtension, d2FacePartsContentCollectionDirectory, keyMapping.MappingFromItem);
if (facePartsContentCollectionFile is null || !File.Exists(facePartsContentCollectionFile))
result = null;
else
{
string checkFile = Path.Combine(directory, $"{keyMapping.MappingFromItem.ImageFileHolder.Name}{facePartsFileNameExtension}");
result = new(checkFile, directory, new(facePartsContentCollectionFile));
}
string facesDirectory = GetFacesDirectory(propertyConfiguration, dFacesContentDirectory, keyMapping.MappingFromItem);
FileHolder faceFileHolder = new(Path.Combine(facesDirectory, $"{keyMapping.MappingFromLocation.DeterministicHashCodeKey}{keyMapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}"));
if (!faceFileHolder.Exists)
saveContainer = null;
else
{
string checkFile = Path.Combine(directory, $"{keyMapping.MappingFromLocation.DeterministicHashCodeKey}{keyMapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}");
saveContainer = new(checkFile, directory, faceFileHolder);
}
}
return (result, saveContainer);
}
internal static (SaveContainer, SaveContainer?) GetContainers(string facesFileNameExtension, string facePartsFileNameExtension, string directory, FileHolder faceFileHolder, FileHolder facePartsFileHolder, Mapping mapping) internal static (SaveContainer, SaveContainer?) GetContainers(string facesFileNameExtension, string facePartsFileNameExtension, string directory, FileHolder faceFileHolder, FileHolder facePartsFileHolder, Mapping mapping)
{ {
string checkFile; string checkFile;
@ -1568,7 +1138,7 @@ internal abstract class MapLogic
return results; return results;
} }
internal static (string, bool, bool) Get(int? useFiltersCounter, bool saveIndividually, bool sortingContainersAny, string forceSingleImageHumanized, Mapping mapping) internal static (string, bool, bool) Get(int? useFiltersCounter, bool saveIndividually, bool sortingContainersAny, string forceSingleImageHumanized, int? distancePermyriad, Mapping mapping)
{ {
string by; string by;
bool isByMapping; bool isByMapping;
@ -1585,7 +1155,7 @@ internal abstract class MapLogic
isBySorting = mapping.By == Shared.Models.Stateless.IMapLogic.Sorting; isBySorting = mapping.By == Shared.Models.Stateless.IMapLogic.Sorting;
bool isDefaultName = mapping.MappingFromPerson is not null && IPerson.IsDefaultName(mapping.MappingFromPerson.DisplayDirectoryName); bool isDefaultName = mapping.MappingFromPerson is not null && IPerson.IsDefaultName(mapping.MappingFromPerson.DisplayDirectoryName);
if (isBySorting && mapping.MappingFromPerson is null) if (isBySorting && mapping.MappingFromPerson is null)
by = saveIndividually ? nameof(Shared.Models.Stateless.IMapLogic.Individually) : $"{nameof(Shared.Models.Stateless.IMapLogic.Sorting)} Without Person"; by = saveIndividually ? nameof(Shared.Models.Stateless.IMapLogic.Individually) : $"{nameof(Shared.Models.Stateless.IMapLogic.Sorting)} Without Person{(distancePermyriad < 2000 ? "-A" : "-Z")}";
else if (isBySorting && useFiltersCounter.HasValue) else if (isBySorting && useFiltersCounter.HasValue)
by = $"{nameof(Shared.Models.Stateless.IMapLogic.Sorting)}{(!isDefaultName ? "-A" : "-Z")} Modified Filters - {useFiltersCounter.Value}"; by = $"{nameof(Shared.Models.Stateless.IMapLogic.Sorting)}{(!isDefaultName ? "-A" : "-Z")} Modified Filters - {useFiltersCounter.Value}";
else else

View File

@ -20,7 +20,7 @@ internal abstract class RelationLogic
ReadOnlyCollection<string> Linked9, ReadOnlyCollection<string> Linked9,
ReadOnlyDictionary<string, string> MovedFiles); ReadOnlyDictionary<string, string> MovedFiles);
private static ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> GetCollections(List<LocationContainer<MetadataExtractor.Directory>> locationContainers) private static ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> GetCollections(Configuration configuration, List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{ {
List<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> results = new(); List<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> results = new();
List<LocationContainer<MetadataExtractor.Directory>>? collection; List<LocationContainer<MetadataExtractor.Directory>>? collection;
@ -29,6 +29,8 @@ internal abstract class RelationLogic
{ {
if (!locationContainer.FromDistanceContent) if (!locationContainer.FromDistanceContent)
continue; continue;
if (!locationContainer.File.Contains(configuration.LocationContainerDirectoryPattern))
continue;
if (!keyValuePairs.TryGetValue(locationContainer.PersonKey, out collection)) if (!keyValuePairs.TryGetValue(locationContainer.PersonKey, out collection))
{ {
keyValuePairs.Add(locationContainer.PersonKey, new()); keyValuePairs.Add(locationContainer.PersonKey, new());
@ -42,72 +44,7 @@ internal abstract class RelationLogic
return new(results); return new(results);
} }
private static string? GetDisplayDirectoryName(ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, long personKey, string personKeyFormatted) private static ReadOnlyDictionary<string, string> MoveFiles(Configuration configuration, bool isCounterPersonYear, string? displayDirectoryName, List<string> linked1, List<string> linked2, List<string> linked3, List<string> linked4, List<string> linked5, List<string> linked6, List<string> linked7, List<string> linked8, List<string> linked9)
{
string? result;
PersonContainer? personContainer;
List<PersonContainer>? collection;
_ = readOnlyPersonKeyToPersonContainerCollection.TryGetValue(personKey, out collection);
if (collection is not null)
result = collection[0].DisplayDirectoryName;
else
{
if (!readOnlyPersonKeyFormattedToPersonContainer.TryGetValue(personKeyFormatted, out personContainer))
result = null;
else
result = personContainer.DisplayDirectoryName;
}
return result;
}
private static void AddDisplayDirectoryNames(Configuration configuration, string eDistanceContentDirectory, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection, ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> collections)
{
bool isCounterPersonYear;
string personKeyFormatted;
string? displayDirectoryName;
string? checkDirectory = Path.Combine(eDistanceContentDirectory, configuration.LocationContainerDebugDirectory);
_ = IPath.DeleteEmptyDirectories(checkDirectory);
foreach (ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> collection in collections)
{
if (configuration.LocationContainerDistanceTolerance is null)
break;
isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(new DateTime(collection[0].PersonKey).Year);
if (isCounterPersonYear)
continue;
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, collection[0].PersonKey);
checkDirectory = Path.Combine(eDistanceContentDirectory, configuration.LocationContainerDebugDirectory, personKeyFormatted);
if (!Directory.Exists(checkDirectory))
continue;
displayDirectoryName = GetDisplayDirectoryName(readOnlyPersonKeyToPersonContainerCollection, readOnlyPersonKeyFormattedToPersonContainer, collection[0].PersonKey, personKeyFormatted);
if (string.IsNullOrEmpty(displayDirectoryName))
continue;
foreach (string yearDirectory in Directory.GetDirectories(checkDirectory, "*", SearchOption.TopDirectoryOnly))
{
checkDirectory = Path.Combine(yearDirectory, displayDirectoryName);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
}
checkDirectory = Path.Combine(eDistanceContentDirectory, configuration.LocationContainerDebugDirectory, personKeyFormatted, displayDirectoryName);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
}
}
private static void WriteVsCodeFiles(string eDistanceContentDirectory, string? displayDirectoryName, string directory)
{
string json;
string vsCodeDirectory = Path.Combine(directory, ".vscode");
if (!Directory.Exists(vsCodeDirectory))
_ = Directory.CreateDirectory(vsCodeDirectory);
if (displayDirectoryName is not null)
File.WriteAllText(Path.Combine(directory, $"_ {displayDirectoryName}.txt"), string.Empty);
json = "{ \"[markdown]\": { \"editor.wordWrap\": \"off\" }, \"foam.links.hover.enable\": false, \"foam.graph.style\": { \"background\": \"#202020\", \"node\": { \"note\": \"#f2cb1d\", \"distance\": \"green\", \"image\": \"orange\", \"placeholder\": \"white\", } } }";
_ = IPath.WriteAllText(Path.Combine(vsCodeDirectory, "settings.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
json = string.Concat("{ \"version\": \"2.0.0\", \"tasks\": [ { \"label\": \"MKLink\", \"type\": \"shell\", \"command\": \"New-Item\", \"args\": [ \"-ItemType\", \"Junction\", \"-Path\", \"'", directory.Replace('\\', '/'), "/()'\", \"-Target\", \"'", eDistanceContentDirectory.Replace('\\', '/'), "'\" ], \"problemMatcher\": [] } ] }");
_ = IPath.WriteAllText(Path.Combine(vsCodeDirectory, "tasks.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
}
private static ReadOnlyDictionary<string, string> MoveFiles(string locationContainerDebugDirectory, bool isCounterPersonYear, string? displayDirectoryName, List<string> linked1, List<string> linked2, List<string> linked3, List<string> linked4, List<string> linked5, List<string> linked6, List<string> linked7, List<string> linked8, List<string> linked9)
{ {
Dictionary<string, string> results = new(); Dictionary<string, string> results = new();
char c; char c;
@ -150,15 +87,15 @@ internal abstract class RelationLogic
c = Convert.ToChar(48 + keyValuePair.Value); c = Convert.ToChar(48 + keyValuePair.Value);
if (c is ':' or ';' or '<' or '=' or '>' or '?') if (c is ':' or ';' or '<' or '=' or '>' or '?')
c = '_'; c = '_';
if (maybeTicksDirectoryName == locationContainerDebugDirectory) if (maybeTicksDirectoryName == configuration.LocationContainerDebugDirectory)
checkDirectory = Path.Combine(yearDirectory, $"{keyValuePair.Value}{new string(c, 7)}"); checkDirectory = Path.Combine(yearDirectory, $"{keyValuePair.Value}{new string(c, 7)}");
else else
{ {
if (!string.IsNullOrEmpty(locationContainerDebugDirectory)) if (!string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory))
continue; continue;
checkDirectory = Path.Combine(personKeyFormattedDirectory, $"{keyValuePair.Value}{new string(c, 7)}"); checkDirectory = Path.Combine(personKeyFormattedDirectory, $"{keyValuePair.Value}{new string(c, 7)}");
} }
if (maybeTicksDirectoryName != locationContainerDebugDirectory) if (maybeTicksDirectoryName != configuration.LocationContainerDebugDirectory)
{ {
if (isCounterPersonYear || string.IsNullOrEmpty(displayDirectoryName)) if (isCounterPersonYear || string.IsNullOrEmpty(displayDirectoryName))
checkDirectory = Path.Combine(checkDirectory, personNameDirectoryName); checkDirectory = Path.Combine(checkDirectory, personNameDirectoryName);
@ -182,7 +119,7 @@ internal abstract class RelationLogic
continue; continue;
File.Move(debugFile, checkFile); File.Move(debugFile, checkFile);
} }
if (maybeTicksDirectoryName == locationContainerDebugDirectory && !string.IsNullOrEmpty(displayDirectoryName)) if (maybeTicksDirectoryName == configuration.LocationContainerDebugDirectory && !string.IsNullOrEmpty(displayDirectoryName))
{ {
checkDirectory = Path.Combine(checkDirectory, displayDirectoryName); checkDirectory = Path.Combine(checkDirectory, displayDirectoryName);
if (!Directory.Exists(checkDirectory)) if (!Directory.Exists(checkDirectory))
@ -192,7 +129,68 @@ internal abstract class RelationLogic
return new(results); return new(results);
} }
private static RelationCollection GetMappedRelationCollection(string locationContainerDebugDirectory, int take, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers) private static string? GetDisplayDirectoryName(ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, long personKey, string personKeyFormatted)
{
string? result;
PersonContainer? personContainer;
List<PersonContainer>? collection;
_ = readOnlyPersonKeyToPersonContainerCollection.TryGetValue(personKey, out collection);
if (collection is not null)
result = collection[0].DisplayDirectoryName;
else
{
if (!readOnlyPersonKeyFormattedToPersonContainer.TryGetValue(personKeyFormatted, out personContainer))
result = null;
else
result = personContainer.DisplayDirectoryName;
}
return result;
}
private static int GetTake(int locationContainerDistanceTake, int count)
{
int result = locationContainerDistanceTake;
int subtract = (int)(locationContainerDistanceTake * .05);
if (subtract < 1)
subtract = 1;
if (count > 9000)
result -= subtract;
if (count > 8000)
result -= subtract;
if (count > 7000)
result -= subtract;
if (count > 6000)
result -= subtract;
if (count > 5000)
result -= subtract;
if (count > 4000)
result -= subtract;
if (count > 3000)
result -= subtract;
if (count > 2000)
result -= subtract;
if (count > 1000)
result -= subtract;
if (result < 3)
result = 3;
return result;
}
private static void WriteVsCodeFiles(string eDistanceContentDirectory, string? displayDirectoryName, string directory)
{
string json;
string vsCodeDirectory = Path.Combine(directory, ".vscode");
if (!Directory.Exists(vsCodeDirectory))
_ = Directory.CreateDirectory(vsCodeDirectory);
if (displayDirectoryName is not null)
File.WriteAllText(Path.Combine(directory, $"_ {displayDirectoryName}.txt"), string.Empty);
json = "{ \"[markdown]\": { \"editor.wordWrap\": \"off\" }, \"foam.links.hover.enable\": false, \"foam.graph.style\": { \"background\": \"#202020\", \"node\": { \"note\": \"#f2cb1d\", \"distance\": \"green\", \"image\": \"orange\", \"placeholder\": \"white\", } } }";
_ = IPath.WriteAllText(Path.Combine(vsCodeDirectory, "settings.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
json = string.Concat("{ \"version\": \"2.0.0\", \"tasks\": [ { \"label\": \"MKLink\", \"type\": \"shell\", \"command\": \"New-Item\", \"args\": [ \"-ItemType\", \"Junction\", \"-Path\", \"'", directory.Replace('\\', '/'), "/()'\", \"-Target\", \"'", eDistanceContentDirectory.Replace('\\', '/'), "'\" ], \"problemMatcher\": [] } ] }");
_ = IPath.WriteAllText(Path.Combine(vsCodeDirectory, "tasks.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
}
private static RelationCollection GetMappedRelationCollection(Configuration configuration, int take, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers)
{ {
RelationCollection result; RelationCollection result;
List<string> linked1 = new(); List<string> linked1 = new();
@ -255,7 +253,7 @@ internal abstract class RelationLogic
} }
} }
} }
ReadOnlyDictionary<string, string> movedFiles = MoveFiles(locationContainerDebugDirectory, isCounterPersonYear, displayDirectoryName, linked1, linked2, linked3, linked4, linked5, linked6, linked7, linked8, linked9); ReadOnlyDictionary<string, string> movedFiles = MoveFiles(configuration, isCounterPersonYear, displayDirectoryName, linked1, linked2, linked3, linked4, linked5, linked6, linked7, linked8, linked9);
result = new(relationContainers, new(linked1), new(linked2), new(linked3), new(linked4), new(linked5), new(linked6), new(linked7), new(linked8), new(linked9), movedFiles); result = new(relationContainers, new(linked1), new(linked2), new(linked3), new(linked4), new(linked5), new(linked6), new(linked7), new(linked8), new(linked9), movedFiles);
return result; return result;
} }
@ -328,33 +326,37 @@ internal abstract class RelationLogic
} }
} }
private static int GetTake(int locationContainerDistanceTake, int count) private static void AddDisplayDirectoryNames(Configuration configuration, string eDistanceContentDirectory, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection, ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> collections)
{ {
int result = locationContainerDistanceTake; bool isCounterPersonYear;
int subtract = (int)(locationContainerDistanceTake * .05); string personKeyFormatted;
if (subtract < 1) string? displayDirectoryName;
subtract = 1; string? checkDirectory = Path.Combine(eDistanceContentDirectory, configuration.LocationContainerDebugDirectory);
if (count > 9000) _ = IPath.DeleteEmptyDirectories(checkDirectory);
result -= subtract; foreach (ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> collection in collections)
if (count > 8000) {
result -= subtract; if (configuration.LocationContainerDistanceTolerance is null)
if (count > 7000) break;
result -= subtract; isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(new DateTime(collection[0].PersonKey).Year);
if (count > 6000) if (isCounterPersonYear)
result -= subtract; continue;
if (count > 5000) personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, collection[0].PersonKey);
result -= subtract; checkDirectory = Path.Combine(eDistanceContentDirectory, configuration.LocationContainerDebugDirectory, personKeyFormatted);
if (count > 4000) if (!Directory.Exists(checkDirectory))
result -= subtract; continue;
if (count > 3000) displayDirectoryName = GetDisplayDirectoryName(readOnlyPersonKeyToPersonContainerCollection, readOnlyPersonKeyFormattedToPersonContainer, collection[0].PersonKey, personKeyFormatted);
result -= subtract; if (string.IsNullOrEmpty(displayDirectoryName))
if (count > 2000) continue;
result -= subtract; foreach (string yearDirectory in Directory.GetDirectories(checkDirectory, "*", SearchOption.TopDirectoryOnly))
if (count > 1000) {
result -= subtract; checkDirectory = Path.Combine(yearDirectory, displayDirectoryName);
if (result < 3) if (!Directory.Exists(checkDirectory))
result = 3; _ = Directory.CreateDirectory(checkDirectory);
return result; }
checkDirectory = Path.Combine(eDistanceContentDirectory, configuration.LocationContainerDebugDirectory, personKeyFormatted, displayDirectoryName);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
}
} }
internal static void SaveMappedRelations(Configuration configuration, Shared.Models.Methods.IDistance<MetadataExtractor.Directory> distance, string a2PeopleContentDirectory, string eDistanceContentDirectory, long ticks, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection) internal static void SaveMappedRelations(Configuration configuration, Shared.Models.Methods.IDistance<MetadataExtractor.Directory> distance, string a2PeopleContentDirectory, string eDistanceContentDirectory, long ticks, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection)
@ -370,7 +372,7 @@ internal abstract class RelationLogic
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
string message = $") Save Mapped Relations - {totalSeconds} total second(s)"; string message = $") Save Mapped Relations - {totalSeconds} total second(s)";
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> collections = GetCollections(locationContainers); ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> collections = GetCollections(configuration, locationContainers);
using ProgressBar progressBar = new(collections.Count, message, options); using ProgressBar progressBar = new(collections.Count, message, options);
foreach (ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> collection in collections) foreach (ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> collection in collections)
{ {
@ -388,7 +390,7 @@ internal abstract class RelationLogic
_ = Directory.CreateDirectory(directory); _ = Directory.CreateDirectory(directory);
WriteVsCodeFiles(eDistanceContentDirectory, displayDirectoryName, directory); WriteVsCodeFiles(eDistanceContentDirectory, displayDirectoryName, directory);
relationContainers = distance.GetRelationContainers(configuration.FaceDistancePermyriad, configuration.LocationContainerDistanceTake, configuration.LocationContainerDistanceTolerance.Value, collection); relationContainers = distance.GetRelationContainers(configuration.FaceDistancePermyriad, configuration.LocationContainerDistanceTake, configuration.LocationContainerDistanceTolerance.Value, collection);
relationCollection = GetMappedRelationCollection(configuration.LocationContainerDebugDirectory, take, isCounterPersonYear, displayDirectoryName, relationContainers); relationCollection = GetMappedRelationCollection(configuration, take, isCounterPersonYear, displayDirectoryName, relationContainers);
WriteFile(take, collection[0].PersonKey, isCounterPersonYear, personKeyFormatted, displayDirectoryName, directory, ticks, uri, relationCollection); WriteFile(take, collection[0].PersonKey, isCounterPersonYear, personKeyFormatted, displayDirectoryName, directory, ticks, uri, relationCollection);
} }
if (string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory)) if (string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory))

View File

@ -26,8 +26,6 @@ taskTemplate: '^+^_${overdue ? ''^R'' : ''''}${name}^: ${relations ? (''\n^-^/^g
## Todo ## Todo
- [verify-camera-model-still-works](tasks/verify-camera-model-still-works.md)
- [run-limiting-on-days](tasks/run-limiting-on-days.md)
- [update-drag-and-drop-to-work-with-new-resize-location](tasks/update-drag-and-drop-to-work-with-new-resize-location.md) - [update-drag-and-drop-to-work-with-new-resize-location](tasks/update-drag-and-drop-to-work-with-new-resize-location.md)
- [triangle-over-person-in-full-image-for-some](tasks/triangle-over-person-in-full-image-for-some.md) - [triangle-over-person-in-full-image-for-some](tasks/triangle-over-person-in-full-image-for-some.md)
- [use-eyes-to-find-orientation](tasks/use-eyes-to-find-orientation.md) - [use-eyes-to-find-orientation](tasks/use-eyes-to-find-orientation.md)
@ -39,7 +37,10 @@ taskTemplate: '^+^_${overdue ? ''^R'' : ''''}${name}^: ${relations ? (''\n^-^/^g
## In Progress ## In Progress
- [verify-ignore-get-set-to-dup-if-they-are-set](tasks/verify-ignore-get-set-to-dup-if-they-are-set.md)
- [name-some-from-638324064000000000-verify-manual-still-works](tasks/name-some-from-638324064000000000-verify-manual-still-works.md) - [name-some-from-638324064000000000-verify-manual-still-works](tasks/name-some-from-638324064000000000-verify-manual-still-works.md)
- [verify-camera-model-still-works](tasks/verify-camera-model-still-works.md)
- [run-limiting-on-days](tasks/run-limiting-on-days.md)
- [merge-kristy-files](tasks/merge-kristy-files.md) - [merge-kristy-files](tasks/merge-kristy-files.md)
## Done ## Done

View File

@ -1,6 +1,6 @@
--- ---
created: 2023-09-09T15:01:12.800Z created: 2023-09-09T15:01:12.800Z
updated: 2023-09-09T21:51:53.090Z updated: 2023-09-10T01:10:32.967Z
assigned: "" assigned: ""
progress: 0 progress: 0
tags: [] tags: []

View File

@ -1,6 +1,6 @@
--- ---
created: 2023-09-09T15:01:28.239Z created: 2023-09-09T15:01:28.239Z
updated: 2023-09-09T21:51:54.599Z updated: 2023-09-10T01:10:31.283Z
assigned: "" assigned: ""
progress: 0 progress: 0
tags: [] tags: []

View File

@ -0,0 +1,10 @@
---
created: 2023-09-10T02:21:51.169Z
updated: 2023-09-10T02:21:59.136Z
assigned: ""
progress: 0
tags: []
started: 2023-09-10T02:21:51.169Z
---
# Verify ignore get set to dup if they are set

View File

@ -28,14 +28,20 @@
{ {
"label": "File-Folder-Helper AOT s G File System to Genealogical Data Communication", "label": "File-Folder-Helper AOT s G File System to Genealogical Data Communication",
"type": "shell", "type": "shell",
"command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s G 'D:/1-Images-A/Images-dd514b88-Results/A2)People/dd514b88/([])/File-Folder-Helper/638280519245151237' -d 'D:/1-Images-A/Images-dd514b88-Results/A2)People/dd514b88/{2}'", "command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s G 'D:/1-Images-A/Images-dd514b88-Results/A2)People/dd514b88/([])/File-Folder-Helper/638298094252901621' -d 'D:/1-Images-A/Images-dd514b88-Results/A2)People/dd514b88/{2}'",
"problemMatcher": [] "problemMatcher": []
}, },
{ {
"label": "File-Folder-Helper AOT s VSCode Possible", "label": "File-Folder-Helper AOT s VSCode Possible - Instance",
"type": "shell", "type": "shell",
"command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s V 'L:/Git/View-by-Distance-MKLink-Console/Instance'", "command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s V 'L:/Git/View-by-Distance-MKLink-Console/Instance'",
"problemMatcher": [] "problemMatcher": []
},
{
"label": "File-Folder-Helper AOT s VSCode Possible - Map",
"type": "shell",
"command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s V L:/Git/View-by-Distance-MKLink-Console/Map/Models/Stateless",
"problemMatcher": []
} }
] ]
} }