LocationContainerDistanceGroupMinimum

This commit is contained in:
Mike Phares 2023-09-21 20:43:28 -07:00
parent 5633430bfb
commit f540cac462
11 changed files with 190 additions and 104 deletions

View File

@ -307,7 +307,17 @@ public class D_Face
if (location is null) if (location is null)
continue; continue;
if (!results.Any(l => l.WholePercentages == locationContainer.WholePercentages)) if (!results.Any(l => l.WholePercentages == locationContainer.WholePercentages))
results.Add(new(locationContainer.FromDistanceContent, locationContainer.DirectoryNumber, locationContainer.File, locationContainer.PersonKey, locationContainer.DisplayDirectoryName, locationContainer.Id, locationContainer.WholePercentages, locationContainer.Directories, rectangle.Value, location)); results.Add(new(locationContainer.CreationDateOnly,
locationContainer.Directories,
locationContainer.DirectoryNumber,
locationContainer.DisplayDirectoryName,
locationContainer.File,
locationContainer.FromDistanceContent,
locationContainer.Id,
location,
locationContainer.PersonKey,
rectangle.Value,
locationContainer.WholePercentages));
} }
} }
if (results.Count > 0) if (results.Count > 0)

View File

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

View File

@ -34,6 +34,7 @@ public class Configuration
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 string? LocationContainerDirectoryPattern { get; set; }
public int? LocationContainerDistanceGroupMinimum { 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; }
@ -135,6 +136,7 @@ public class Configuration
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?.LocationContainerDirectoryPattern is null) throw new NullReferenceException(nameof(configuration.LocationContainerDirectoryPattern));
if (configuration?.LocationContainerDistanceGroupMinimum is null) throw new NullReferenceException(nameof(configuration.LocationContainerDistanceGroupMinimum));
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));
@ -223,6 +225,7 @@ public class Configuration
configuration.LoadPhotoPrismLocations.Value, configuration.LoadPhotoPrismLocations.Value,
configuration.LocationContainerDebugDirectory, configuration.LocationContainerDebugDirectory,
configuration.LocationContainerDirectoryPattern, configuration.LocationContainerDirectoryPattern,
configuration.LocationContainerDistanceGroupMinimum.Value,
configuration.LocationContainerDistanceTake.Value, configuration.LocationContainerDistanceTake.Value,
configuration.LocationContainerDistanceTolerance, configuration.LocationContainerDistanceTolerance,
configuration.LocationDigits.Value, configuration.LocationDigits.Value,

View File

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

View File

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

View File

@ -6,11 +6,20 @@ namespace View_by_Distance.Map.Models.Stateless;
internal abstract class DecadeLogic internal abstract class DecadeLogic
{ {
internal static string GetDecade(MappingFromItem mappingFromItem) internal static string GetDecade(MappingFromItem? mappingFromItem, DateOnly? dateOnly)
{ {
string result; string result;
string year; string year;
if (mappingFromItem.DateTimeOriginal is null) if (mappingFromItem is null && dateOnly is null)
throw new NotSupportedException();
if (dateOnly is not null)
{
year = dateOnly.Value.Year.ToString();
result = year[3] > '4' ? $"#{year[..3]}+" : $"#{year[..3]}-";
}
else if (mappingFromItem is null)
throw new NotSupportedException();
else if (mappingFromItem.DateTimeOriginal is null)
{ {
year = mappingFromItem.MinimumDateTime.Year.ToString(); year = mappingFromItem.MinimumDateTime.Year.ToString();
result = year[3] > '4' ? $"#{year[..3]}+" : $"#{year[..3]}-"; result = year[3] > '4' ? $"#{year[..3]}+" : $"#{year[..3]}-";
@ -26,7 +35,6 @@ internal abstract class DecadeLogic
internal static void SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers) internal static void SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{ {
DateTime dateTime; DateTime dateTime;
FileInfo fileInfo;
string halfDecade; string halfDecade;
string checkDirectory; string checkDirectory;
string? yearDirectory; string? yearDirectory;
@ -37,11 +45,10 @@ internal abstract class DecadeLogic
string? personKeyFormattedDirectoryName; string? personKeyFormattedDirectoryName;
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers) foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
{ {
fileInfo = new(locationContainer.File); if (!File.Exists(locationContainer.File))
if (!fileInfo.Exists)
continue; continue;
dateTime = mappingFromItem.DateTimeOriginal is null ? mappingFromItem.MinimumDateTime : mappingFromItem.DateTimeOriginal.Value; dateTime = mappingFromItem.DateTimeOriginal is null ? mappingFromItem.MinimumDateTime : mappingFromItem.DateTimeOriginal.Value;
if (fileInfo.CreationTime != dateTime) if (locationContainer.CreationDateOnly.Year != dateTime.Year || locationContainer.CreationDateOnly.Month != dateTime.Month || locationContainer.CreationDateOnly.Day != dateTime.Day)
File.SetCreationTime(locationContainer.File, dateTime); File.SetCreationTime(locationContainer.File, dateTime);
if (!moveToDecade) if (!moveToDecade)
continue; continue;
@ -59,7 +66,7 @@ internal abstract class DecadeLogic
personKeyFormattedDirectoryName = Path.GetFileName(personKeyFormattedDirectory); personKeyFormattedDirectoryName = Path.GetFileName(personKeyFormattedDirectory);
if (personKeyFormattedDirectoryName.Length != propertyConfiguration.PersonBirthdayFormat.Length) if (personKeyFormattedDirectoryName.Length != propertyConfiguration.PersonBirthdayFormat.Length)
break; break;
halfDecade = GetDecade(mappingFromItem); halfDecade = GetDecade(mappingFromItem, null);
if (halfDecade == yearDirectoryName) if (halfDecade == yearDirectoryName)
continue; continue;
checkDirectory = Path.Combine(personKeyFormattedDirectory, halfDecade, personNameDirectoryName); checkDirectory = Path.Combine(personKeyFormattedDirectory, halfDecade, personNameDirectoryName);

View File

@ -1,4 +1,4 @@
using ShellProgressBar; using ShellProgressBar;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
@ -475,6 +475,7 @@ internal abstract class MapLogic
private static void ParallelFor(Configuration configuration, Dictionary<int, List<(string, int)>> skipCollection, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, MappedFile mappedFile) private static void ParallelFor(Configuration configuration, Dictionary<int, List<(string, int)>> skipCollection, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, MappedFile mappedFile)
{ {
string checkFile; string checkFile;
DateOnly dateOnly;
string[] fileMatches; string[] fileMatches;
const string lnk = ".lnk"; const string lnk = ".lnk";
int? id, wholePercentages; int? id, wholePercentages;
@ -502,6 +503,7 @@ internal abstract class MapLogic
continue; continue;
} }
} }
dateOnly = DateOnly.FromDateTime(new FileInfo(mappedFile.File).CreationTime);
if (mappedFile.File.EndsWith(lnk) || (!configuration.DistanceMoveUnableToMatch && !configuration.DistanceRenameToMatch) || !File.Exists(mappedFile.File)) if (mappedFile.File.EndsWith(lnk) || (!configuration.DistanceMoveUnableToMatch && !configuration.DistanceRenameToMatch) || !File.Exists(mappedFile.File))
directories = new List<MetadataExtractor.Directory>(); directories = new List<MetadataExtractor.Directory>();
else else
@ -509,7 +511,17 @@ internal abstract class MapLogic
RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value); RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value);
personDisplayDirectoryName = mappedFile.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : mappedFile.PersonDisplayDirectoryName; personDisplayDirectoryName = mappedFile.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : mappedFile.PersonDisplayDirectoryName;
lock (locationContainers) lock (locationContainers)
locationContainers.Add(new(fromDistanceContent, mappedFile.DirectoryNumber, mappedFile.File, mappedFile.PersonKey, personDisplayDirectoryName, id.Value, wholePercentages.Value, directories, rectangle, null)); locationContainers.Add(new(dateOnly,
directories,
mappedFile.DirectoryNumber,
personDisplayDirectoryName,
mappedFile.File,
fromDistanceContent,
id.Value,
null,
mappedFile.PersonKey,
rectangle,
wholePercentages.Value));
} }
private static void LookForPossibleDuplicates(Configuration configuration, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers) private static void LookForPossibleDuplicates(Configuration configuration, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers)

View File

@ -48,6 +48,6 @@ public interface IMapLogic
string TestStatic_GetDecade(Shared.Models.MappingFromItem mappingFromItem) => string TestStatic_GetDecade(Shared.Models.MappingFromItem mappingFromItem) =>
GetDecade(mappingFromItem); GetDecade(mappingFromItem);
static string GetDecade(Shared.Models.MappingFromItem mappingFromItem) => static string GetDecade(Shared.Models.MappingFromItem mappingFromItem) =>
DecadeLogic.GetDecade(mappingFromItem); DecadeLogic.GetDecade(mappingFromItem, null);
} }

View File

@ -8,46 +8,86 @@ namespace View_by_Distance.Map.Models.Stateless;
internal abstract class RelationLogic internal abstract class RelationLogic
{ {
internal record RelationCollection(ReadOnlyCollection<RelationContainer> RelationContainers, internal record Group(string Key, long PersonKey, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> RelationContainersCollection);
ReadOnlyCollection<string> Linked1,
ReadOnlyCollection<string> Linked2,
ReadOnlyCollection<string> Linked3,
ReadOnlyCollection<string> Linked4,
ReadOnlyCollection<string> Linked5,
ReadOnlyCollection<string> Linked6,
ReadOnlyCollection<string> Linked7,
ReadOnlyCollection<string> Linked8,
ReadOnlyCollection<string> Linked9,
ReadOnlyDictionary<string, string> MovedFiles);
private static ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> GetCollections(Configuration configuration, List<LocationContainer<MetadataExtractor.Directory>> locationContainers) private static Dictionary<long, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>>> GetPersonKeyTo(Configuration configuration, List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{ {
List<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> results = new();
List<LocationContainer<MetadataExtractor.Directory>>? collection; List<LocationContainer<MetadataExtractor.Directory>>? collection;
Dictionary<long, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePairs = new(); Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>>? yearTo;
Dictionary<long, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>>> personKeyTo = new();
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers) foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
{ {
if (!locationContainer.FromDistanceContent) if (!locationContainer.FromDistanceContent)
continue; continue;
if (!locationContainer.File.Contains(configuration.LocationContainerDirectoryPattern)) if (!locationContainer.File.Contains(configuration.LocationContainerDirectoryPattern))
continue; continue;
if (!keyValuePairs.TryGetValue(locationContainer.PersonKey, out collection)) if (!personKeyTo.TryGetValue(locationContainer.PersonKey, out yearTo))
{ {
keyValuePairs.Add(locationContainer.PersonKey, new()); personKeyTo.Add(locationContainer.PersonKey, new());
if (!keyValuePairs.TryGetValue(locationContainer.PersonKey, out collection)) if (!personKeyTo.TryGetValue(locationContainer.PersonKey, out yearTo))
throw new Exception();
}
if (!yearTo.TryGetValue(locationContainer.CreationDateOnly.Year, out collection))
{
yearTo.Add(locationContainer.CreationDateOnly.Year, new());
if (!yearTo.TryGetValue(locationContainer.CreationDateOnly.Year, out collection))
throw new Exception(); throw new Exception();
} }
collection.Add(locationContainer); collection.Add(locationContainer);
} }
foreach (KeyValuePair<long, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePair in keyValuePairs) return personKeyTo;
results.Add(new(keyValuePair.Value)); }
private static ReadOnlyCollection<Group> GetGroups(Configuration configuration, List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{
List<Group> results = new();
string key;
int lastIndex;
List<int> years = new();
List<int> indices = new();
List<(int Index, int Year)> sort = new();
List<LocationContainer<MetadataExtractor.Directory>> collection = new();
KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> keyValue;
Dictionary<long, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>>> personKeyTo = GetPersonKeyTo(configuration, locationContainers);
foreach (KeyValuePair<long, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>>> keyValuePair in personKeyTo)
{
sort.Clear();
years.Clear();
indices.Clear();
for (int i = 0; i < keyValuePair.Value.Count; i++)
sort.Add(new(i, keyValuePair.Value.ElementAt(i).Key));
if (sort.Count == 0)
continue;
foreach ((int index, int _) in sort.OrderBy(l => l.Year))
indices.Add(index);
lastIndex = indices[^1];
foreach (int index in indices)
{
keyValue = keyValuePair.Value.ElementAt(index);
if (keyValue.Value.Count == 0)
continue;
years.Add(keyValue.Key);
collection.AddRange(keyValue.Value);
if (index != lastIndex && years.Count < 6 && years.Sum() > configuration.LocationContainerDistanceGroupMinimum)
continue;
if (years.Count == 1)
key = keyValue.Key.ToString();
else
key = $"{years.Min()}-{keyValue.Key}";
if (collection.Count == 0)
continue;
results.Add(new(key, collection[0].PersonKey, new(collection)));
collection = new();
years.Clear();
}
}
return new(results); return new(results);
} }
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) private static ReadOnlyDictionary<string, string> MoveFiles(Configuration configuration, string key, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers, 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; string value;
string checkFile; string checkFile;
string debugFile; string debugFile;
string checkDirectory; string checkDirectory;
@ -56,44 +96,42 @@ internal abstract class RelationLogic
string? maybeTicksDirectoryName; string? maybeTicksDirectoryName;
string? personNameDirectoryName; string? personNameDirectoryName;
string? personKeyFormattedDirectory; string? personKeyFormattedDirectory;
Dictionary<string, int> fullNameToCount = new(); foreach ((FileHolder fileHolder, _) in relationContainers)
foreach (string file in linked1)
fullNameToCount.Add(file, 1);
foreach (string file in linked2)
fullNameToCount[file] += 1;
foreach (string file in linked3)
fullNameToCount[file] += 1;
foreach (string file in linked4)
fullNameToCount[file] += 1;
foreach (string file in linked5)
fullNameToCount[file] += 1;
foreach (string file in linked6)
fullNameToCount[file] += 1;
foreach (string file in linked7)
fullNameToCount[file] += 1;
foreach (string file in linked8)
fullNameToCount[file] += 1;
foreach (string file in linked9)
fullNameToCount[file] += 1;
foreach (KeyValuePair<string, int> keyValuePair in fullNameToCount)
{ {
personNameDirectory = Path.GetDirectoryName(keyValuePair.Key); personNameDirectory = fileHolder.DirectoryName;
yearDirectory = Path.GetDirectoryName(personNameDirectory); yearDirectory = Path.GetDirectoryName(personNameDirectory);
personNameDirectoryName = Path.GetFileName(personNameDirectory); personNameDirectoryName = Path.GetFileName(personNameDirectory);
personKeyFormattedDirectory = Path.GetDirectoryName(yearDirectory); personKeyFormattedDirectory = Path.GetDirectoryName(yearDirectory);
maybeTicksDirectoryName = Path.GetFileName(personKeyFormattedDirectory); maybeTicksDirectoryName = Path.GetFileName(personKeyFormattedDirectory);
if (string.IsNullOrEmpty(personNameDirectory) || string.IsNullOrEmpty(yearDirectory) || string.IsNullOrEmpty(personKeyFormattedDirectory) || string.IsNullOrEmpty(personNameDirectoryName)) if (string.IsNullOrEmpty(personNameDirectory) || string.IsNullOrEmpty(yearDirectory) || string.IsNullOrEmpty(personKeyFormattedDirectory) || string.IsNullOrEmpty(personNameDirectoryName))
continue; continue;
c = Convert.ToChar(48 + keyValuePair.Value); if (linked9.Contains(fileHolder.FullName))
if (c is ':' or ';' or '<' or '=' or '>' or '?') value = "JJJ";
c = '_'; else if (linked8.Contains(fileHolder.FullName))
value = "III";
else if (linked7.Contains(fileHolder.FullName))
value = "HHH";
else if (linked6.Contains(fileHolder.FullName))
value = "GGG";
else if (linked5.Contains(fileHolder.FullName))
value = "FFF";
else if (linked4.Contains(fileHolder.FullName))
value = "EEE";
else if (linked3.Contains(fileHolder.FullName))
value = "DDD";
else if (linked2.Contains(fileHolder.FullName))
value = "CCC";
else if (linked1.Contains(fileHolder.FullName))
value = "BBB";
else
value = "AAA";
if (maybeTicksDirectoryName == configuration.LocationContainerDebugDirectory) if (maybeTicksDirectoryName == configuration.LocationContainerDebugDirectory)
checkDirectory = Path.Combine(yearDirectory, $"{keyValuePair.Value}{new string(c, 7)}"); checkDirectory = Path.Combine(yearDirectory, $"{key}-{value}");
else else
{ {
if (!string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory)) if (!string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory))
continue; continue;
checkDirectory = Path.Combine(personKeyFormattedDirectory, $"{keyValuePair.Value}{new string(c, 7)}"); checkDirectory = Path.Combine(personKeyFormattedDirectory, $"{key}-{value}");
} }
if (maybeTicksDirectoryName != configuration.LocationContainerDebugDirectory) if (maybeTicksDirectoryName != configuration.LocationContainerDebugDirectory)
{ {
@ -106,15 +144,15 @@ internal abstract class RelationLogic
continue; continue;
if (!Directory.Exists(checkDirectory)) if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory); _ = Directory.CreateDirectory(checkDirectory);
checkFile = Path.Combine(checkDirectory, Path.GetFileName(keyValuePair.Key)); checkFile = Path.Combine(checkDirectory, fileHolder.Name);
if (File.Exists(checkFile)) if (File.Exists(checkFile))
continue; continue;
results.Add(keyValuePair.Key, checkFile); results.Add(fileHolder.FullName, checkFile);
File.Move(keyValuePair.Key, checkFile); File.Move(fileHolder.FullName, checkFile);
debugFile = $"{keyValuePair.Key[..^4]}.gif"; debugFile = $"{fileHolder.FullName[..^4]}.gif";
if (File.Exists(debugFile)) if (File.Exists(debugFile))
{ {
checkFile = Path.Combine(checkDirectory, $"{Path.GetFileName(keyValuePair.Key)[..^4]}.gif"); checkFile = Path.Combine(checkDirectory, $"{Path.GetFileName(fileHolder.FullName)[..^4]}.gif");
if (File.Exists(checkFile)) if (File.Exists(checkFile))
continue; continue;
File.Move(debugFile, checkFile); File.Move(debugFile, checkFile);
@ -190,9 +228,9 @@ internal abstract class RelationLogic
_ = IPath.WriteAllText(Path.Combine(vsCodeDirectory, "tasks.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); _ = 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) private static ReadOnlyDictionary<string, string> GetMoveFiles(Configuration configuration, string key, int take, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers)
{ {
RelationCollection result; ReadOnlyDictionary<string, string> results;
List<string> linked1 = new(); List<string> linked1 = new();
List<string> linked2 = new(); List<string> linked2 = new();
List<string> linked3 = new(); List<string> linked3 = new();
@ -253,12 +291,11 @@ internal abstract class RelationLogic
} }
} }
} }
ReadOnlyDictionary<string, string> movedFiles = MoveFiles(configuration, isCounterPersonYear, displayDirectoryName, linked1, linked2, linked3, linked4, linked5, linked6, linked7, linked8, linked9); results = MoveFiles(configuration, key, isCounterPersonYear, displayDirectoryName, relationContainers, 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); return results;
return result;
} }
private static void WriteFile(int take, long personKey, bool isCounterPersonYear, string personKeyFormatted, string? displayDirectoryName, string directory, long ticks, Uri uri, RelationCollection relationCollection) private static void WriteFile(int take, long personKey, bool isCounterPersonYear, string personKeyFormatted, string? displayDirectoryName, string directory, long ticks, Uri uri, ReadOnlyCollection<RelationContainer> relationContainers, ReadOnlyDictionary<string, string> movedFiles)
{ {
string a; string a;
string b; string b;
@ -271,10 +308,10 @@ internal abstract class RelationLogic
string originalString; string originalString;
List<string> lines = new(); List<string> lines = new();
string fileNameWithoutExtension; string fileNameWithoutExtension;
foreach ((FileHolder relationFileHolder, ReadOnlyCollection<Relation> relations) in relationCollection.RelationContainers) foreach ((FileHolder relationFileHolder, ReadOnlyCollection<Relation> relations) in relationContainers)
{ {
lines.Clear(); lines.Clear();
if (relationCollection.MovedFiles.TryGetValue(relationFileHolder.FullName, out file)) if (movedFiles.TryGetValue(relationFileHolder.FullName, out file))
fileHolder = new(file); fileHolder = new(file);
else else
fileHolder = new(relationFileHolder.FullName); fileHolder = new(relationFileHolder.FullName);
@ -295,18 +332,18 @@ internal abstract class RelationLogic
else else
lines.Add($"## {displayDirectoryName}"); lines.Add($"## {displayDirectoryName}");
lines.Add(string.Empty); lines.Add(string.Empty);
lines.Add($"![0]({uri.MakeRelativeUri(new(relationFileHolder.FullName)).OriginalString})"); lines.Add($"![0]({uri.MakeRelativeUri(new(fileHolder.FullName)).OriginalString})");
lines.Add($"__{fileNameWithoutExtension}__"); lines.Add($"- __{fileNameWithoutExtension}__");
if (isCounterPersonYear) if (isCounterPersonYear)
lines.Add($"#{years}yrs-ago"); lines.Add($"- #{years}yrs-ago");
else else
lines.Add($"#{years}yrs-old"); lines.Add($"- #{years}yrs-old");
lines.Add($"~~{relations.Count}~~"); lines.Add($"- ~~{relations.Count}~~");
lines.Add(string.Empty); lines.Add(string.Empty);
for (int i = 0; i < relations.Count; i++) for (int i = 0; i < relations.Count; i++)
{ {
relation = relations[i]; relation = relations[i];
if (relationCollection.MovedFiles.TryGetValue(relation.File, out file)) if (movedFiles.TryGetValue(relation.File, out file))
fileHolder = new(file); fileHolder = new(file);
else else
fileHolder = new(relation.File); fileHolder = new(relation.File);
@ -321,30 +358,37 @@ internal abstract class RelationLogic
lines.Add($"![{relation.DistancePermyriad}]({originalString}){Environment.NewLine}{a}{fileNameWithoutExtension}{b}"); lines.Add($"![{relation.DistancePermyriad}]({originalString}){Environment.NewLine}{a}{fileNameWithoutExtension}{b}");
lines.Add(string.Empty); lines.Add(string.Empty);
} }
lines.Add("<style>");
lines.Add("img {");
lines.Add("min-width: 75px;");
lines.Add("max-width: 75px;");
lines.Add("display: block;");
lines.Add("}");
lines.Add("</style>");
text = string.Join(Environment.NewLine, lines); text = string.Join(Environment.NewLine, lines);
File.WriteAllText(Path.Combine(directory, markDownFile), text); File.WriteAllText(Path.Combine(directory, markDownFile), text);
} }
} }
private static void AddDisplayDirectoryNames(Configuration configuration, string eDistanceContentDirectory, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection, ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> collections) private static void AddDisplayDirectoryNames(Configuration configuration, string eDistanceContentDirectory, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection, ReadOnlyCollection<Group> groups)
{ {
bool isCounterPersonYear; bool isCounterPersonYear;
string personKeyFormatted; string personKeyFormatted;
string? displayDirectoryName; string? displayDirectoryName;
string? checkDirectory = Path.Combine(eDistanceContentDirectory, configuration.LocationContainerDebugDirectory); string? checkDirectory = Path.Combine(eDistanceContentDirectory, configuration.LocationContainerDebugDirectory);
_ = IPath.DeleteEmptyDirectories(checkDirectory); _ = IPath.DeleteEmptyDirectories(checkDirectory);
foreach (ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> collection in collections) foreach (Group group in groups)
{ {
if (configuration.LocationContainerDistanceTolerance is null) if (configuration.LocationContainerDistanceTolerance is null)
break; break;
isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(new DateTime(collection[0].PersonKey).Year); isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(new DateTime(group.PersonKey).Year);
if (isCounterPersonYear) if (isCounterPersonYear)
continue; continue;
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, collection[0].PersonKey); personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, group.PersonKey);
checkDirectory = Path.Combine(eDistanceContentDirectory, configuration.LocationContainerDebugDirectory, personKeyFormatted); checkDirectory = Path.Combine(eDistanceContentDirectory, configuration.LocationContainerDebugDirectory, personKeyFormatted);
if (!Directory.Exists(checkDirectory)) if (!Directory.Exists(checkDirectory))
continue; continue;
displayDirectoryName = GetDisplayDirectoryName(readOnlyPersonKeyToPersonContainerCollection, readOnlyPersonKeyFormattedToPersonContainer, collection[0].PersonKey, personKeyFormatted); displayDirectoryName = GetDisplayDirectoryName(readOnlyPersonKeyToPersonContainerCollection, readOnlyPersonKeyFormattedToPersonContainer, group.PersonKey, personKeyFormatted);
if (string.IsNullOrEmpty(displayDirectoryName)) if (string.IsNullOrEmpty(displayDirectoryName))
continue; continue;
foreach (string yearDirectory in Directory.GetDirectories(checkDirectory, "*", SearchOption.TopDirectoryOnly)) foreach (string yearDirectory in Directory.GetDirectories(checkDirectory, "*", SearchOption.TopDirectoryOnly))
@ -367,36 +411,36 @@ internal abstract class RelationLogic
string personKeyFormatted; string personKeyFormatted;
string? displayDirectoryName; string? displayDirectoryName;
Uri uri = new(eDistanceContentDirectory); Uri uri = new(eDistanceContentDirectory);
RelationCollection relationCollection; ReadOnlyDictionary<string, string> movedFiles;
ReadOnlyCollection<RelationContainer> relationContainers; ReadOnlyCollection<RelationContainer> relationContainers;
ReadOnlyCollection<Group> groups = GetGroups(configuration, locationContainers);
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(configuration, locationContainers); using ProgressBar progressBar = new(groups.Count, message, options);
using ProgressBar progressBar = new(collections.Count, message, options); foreach (Group group in groups)
foreach (ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> collection in collections)
{ {
if (configuration.LocationContainerDistanceTolerance is null) if (configuration.LocationContainerDistanceTolerance is null)
break; break;
progressBar.Tick(); progressBar.Tick();
if (collection.Count == 0) if (group.RelationContainersCollection.Count == 0)
continue; continue;
take = GetTake(configuration.LocationContainerDistanceTake, collection.Count); take = GetTake(configuration.LocationContainerDistanceTake, group.RelationContainersCollection.Count);
isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(new DateTime(collection[0].PersonKey).Year); isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(new DateTime(group.PersonKey).Year);
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, collection[0].PersonKey); personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, group.PersonKey);
displayDirectoryName = GetDisplayDirectoryName(readOnlyPersonKeyToPersonContainerCollection, readOnlyPersonKeyFormattedToPersonContainer, collection[0].PersonKey, personKeyFormatted); displayDirectoryName = GetDisplayDirectoryName(readOnlyPersonKeyToPersonContainerCollection, readOnlyPersonKeyFormattedToPersonContainer, group.PersonKey, personKeyFormatted);
directory = Path.Combine(a2PeopleContentDirectory, $"{ticks}-{configuration.LocationContainerDistanceTolerance.Value}", personKeyFormatted); directory = Path.Combine(a2PeopleContentDirectory, $"{ticks}-{configuration.LocationContainerDistanceTolerance.Value}", personKeyFormatted, group.Key);
if (!Directory.Exists(directory)) if (!Directory.Exists(directory))
_ = 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, group.RelationContainersCollection);
relationCollection = GetMappedRelationCollection(configuration, take, isCounterPersonYear, displayDirectoryName, relationContainers); movedFiles = GetMoveFiles(configuration, group.Key, take, isCounterPersonYear, displayDirectoryName, relationContainers);
WriteFile(take, collection[0].PersonKey, isCounterPersonYear, personKeyFormatted, displayDirectoryName, directory, ticks, uri, relationCollection); WriteFile(take, group.PersonKey, isCounterPersonYear, personKeyFormatted, displayDirectoryName, directory, ticks, uri, relationContainers, movedFiles);
} }
if (string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory)) if (string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory))
_ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory); _ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
else else
AddDisplayDirectoryNames(configuration, eDistanceContentDirectory, readOnlyPersonKeyFormattedToPersonContainer, readOnlyPersonKeyToPersonContainerCollection, collections); AddDisplayDirectoryNames(configuration, eDistanceContentDirectory, readOnlyPersonKeyFormattedToPersonContainer, readOnlyPersonKeyToPersonContainerCollection, groups);
} }
} }

View File

@ -42,6 +42,12 @@
"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/Map/Models/Stateless", "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": [] "problemMatcher": []
},
{
"label": "File-Folder-Helper AOT s Ticks",
"type": "shell",
"command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s T 'D:/1-Images-A/Images-dd514b88-Results/E)Distance/dd514b88/('",
"problemMatcher": []
} }
] ]
} }

View File

@ -2,13 +2,14 @@ using System.Drawing;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public record LocationContainer<T>(bool FromDistanceContent, public record LocationContainer<T>(DateOnly CreationDateOnly,
int? DirectoryNumber,
string File,
long PersonKey,
string DisplayDirectoryName,
int Id,
int WholePercentages,
IReadOnlyList<T> Directories, IReadOnlyList<T> Directories,
int? DirectoryNumber,
string DisplayDirectoryName,
string File,
bool FromDistanceContent,
int Id,
Location? Location,
long PersonKey,
RectangleF? Rectangle, RectangleF? Rectangle,
Location? Location); int WholePercentages);