Filter same id

RelationLogic
LookForAbandoned
This commit is contained in:
Mike Phares 2023-09-09 14:59:15 -07:00
parent 331d98793e
commit 4b8b942528
29 changed files with 709 additions and 430 deletions

View File

@ -12,13 +12,7 @@ namespace View_by_Distance.Distance.Models;
public partial class E_Distance : IDistance<MetadataExtractor.Directory>
{
internal record Mapped(string File,
double? Length,
string Link,
string Image);
internal record Record(string File,
FaceRecognitionDotNet.FaceEncoding FaceRecognitionDotNetFaceEncoding);
internal record Record(string File, FaceRecognitionDotNet.FaceEncoding FaceRecognitionDotNetFaceEncoding);
private readonly List<string> _Moved;
private readonly List<double?> _Debug;
@ -446,10 +440,10 @@ public partial class E_Distance : IDistance<MetadataExtractor.Directory>
continue;
if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.InSkipCollection is not null && faceDistanceContainer.Face.Mapping.MappingFromFilterPre.InSkipCollection.Value)
throw new NotSupportedException(nameof(PreFilterSetFaceDistances));
if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusModel is not null && faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusModel.Value)
throw new NotSupportedException(nameof(PreFilterSetFaceDistances));
if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath is not null && faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath.Value)
throw new NotSupportedException(nameof(PreFilterSetFaceDistances));
if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusModel is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusModel.Value)
continue;
if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath.Value)
continue;
if (faceDistanceContainer.Face.Mapping.MappingFromFilterPost.InSkipCollection is not null && faceDistanceContainer.Face.Mapping.MappingFromFilterPost.InSkipCollection.Value)
continue;
if (faceDistanceContainer.Face.Mapping.MappingFromFilterPost.IsFocusPerson is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilterPost.IsFocusPerson.Value)
@ -489,122 +483,27 @@ public partial class E_Distance : IDistance<MetadataExtractor.Directory>
return new(results);
}
private static void WriteVsCodeFiles(string eDistanceContentDirectory, string? displayDirectoryName, string directory)
private static ReadOnlyCollection<RelationContainer> GetRelationCollections(int faceDistancePermyriad, int locationContainerDistanceTake, float distanceTolerance, List<Record> records)
{
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\", } } }";
_ = Shared.Models.Stateless.Methods.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\": [] } ] }");
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(vsCodeDirectory, "tasks.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
}
private static void MoveFiles(string locationContainerDebugDirectory, bool isCounterPersonYear, string? displayDirectoryName, Dictionary<string, int> keyValuePairs, List<string> linkedOnce, List<string> linkedTwice, List<string> linkedThrice, List<string> linkedFour, List<string> linkedFive)
{
string checkFile;
string debugFile;
string checkDirectory;
string? yearDirectory;
string? personNameDirectory;
string? maybeTicksDirectoryName;
string? personNameDirectoryName;
string? personKeyFormattedDirectory;
foreach (string file in linkedOnce)
keyValuePairs[file] += 1;
foreach (string file in linkedTwice)
keyValuePairs[file] += 1;
foreach (string file in linkedThrice)
keyValuePairs[file] += 1;
foreach (string file in linkedFour)
keyValuePairs[file] += 1;
foreach (string file in linkedFive)
keyValuePairs[file] += 1;
foreach (KeyValuePair<string, int> keyValuePair in keyValuePairs)
{
personNameDirectory = Path.GetDirectoryName(keyValuePair.Key);
yearDirectory = Path.GetDirectoryName(personNameDirectory);
personNameDirectoryName = Path.GetFileName(personNameDirectory);
personKeyFormattedDirectory = Path.GetDirectoryName(yearDirectory);
maybeTicksDirectoryName = Path.GetFileName(personKeyFormattedDirectory);
if (string.IsNullOrEmpty(personNameDirectory) || string.IsNullOrEmpty(yearDirectory) || string.IsNullOrEmpty(personKeyFormattedDirectory) || string.IsNullOrEmpty(personNameDirectoryName))
continue;
if (maybeTicksDirectoryName == locationContainerDebugDirectory)
checkDirectory = Path.Combine(yearDirectory, $"{keyValuePair.Value}{new string(Convert.ToChar(65 + keyValuePair.Value), 7)}");
else
{
if (!string.IsNullOrEmpty(locationContainerDebugDirectory))
continue;
checkDirectory = Path.Combine(personKeyFormattedDirectory, $"{keyValuePair.Value}{new string(Convert.ToChar(65 + keyValuePair.Value), 7)}");
}
if (maybeTicksDirectoryName != locationContainerDebugDirectory)
{
if (isCounterPersonYear || string.IsNullOrEmpty(displayDirectoryName))
checkDirectory = Path.Combine(checkDirectory, personNameDirectoryName);
else
checkDirectory = Path.Combine(checkDirectory, displayDirectoryName[0].ToString());
}
if (checkDirectory == personNameDirectory)
continue;
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
checkFile = Path.Combine(checkDirectory, Path.GetFileName(keyValuePair.Key));
if (File.Exists(checkFile))
continue;
File.Move(keyValuePair.Key, checkFile);
debugFile = $"{keyValuePair.Key[..^4]}.gif";
if (File.Exists(debugFile))
{
checkFile = Path.Combine(checkDirectory, $"{Path.GetFileName(keyValuePair.Key)[..^4]}.gif");
if (File.Exists(checkFile))
continue;
File.Move(debugFile, checkFile);
}
if (maybeTicksDirectoryName == locationContainerDebugDirectory && !string.IsNullOrEmpty(displayDirectoryName))
{
checkDirectory = Path.Combine(checkDirectory, displayDirectoryName);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
}
}
}
private static void SaveMappedForOutputResolutions(string locationContainerDebugDirectory, string eDistanceContentDirectory, float distanceTolerance, long personKey, bool isCounterPersonYear, string personKeyFormatted, string? displayDirectoryName, List<Record> records, string directory)
{
int years;
string text;
List<RelationContainer> results = new();
string fileName;
FileInfo fileInfo;
FileHolder fileHolder;
int distancePermyriad;
List<string> files = new();
List<string> lines = new();
List<Mapped> results = new();
List<string> linkedFive = new();
List<string> linkedFour = new();
List<string> linkedOnce = new();
long ticks = DateTime.Now.Ticks;
string fileNameWithoutExtension;
List<string> linkedTwice = new();
List<string> linkedThrice = new();
FaceDistance? faceDistanceEncoding;
List<string> relativePaths = new();
List<Relation> mappedRelations;
List<FaceDistance> faceDistanceLengths;
Uri uri = new(eDistanceContentDirectory);
Dictionary<string, int> keyValuePairs = new();
List<FaceDistance> faceDistanceEncodings = new();
foreach (Record record in records)
{
files.Add(record.File);
relativePaths.Add(uri.MakeRelativeUri(new(record.File)).OriginalString);
faceDistanceEncodings.Add(new(record.FaceRecognitionDotNetFaceEncoding));
}
foreach (Record record in records)
{
lines.Clear();
results.Clear();
fileInfo = new(record.File);
mappedRelations = new();
fileHolder = new(record.File);
if (files.Count > 1)
{
faceDistanceEncoding = new(record.FaceRecognitionDotNetFaceEncoding);
@ -613,77 +512,25 @@ public partial class E_Distance : IDistance<MetadataExtractor.Directory>
faceDistanceLengths = FaceRecognition.FaceDistances(new(faceDistanceEncodings), faceDistanceEncoding);
for (int i = 0; i < faceDistanceLengths.Count; i++)
{
fileName = Path.GetFileName(relativePaths[i]);
if (fileName == fileInfo.Name)
fileName = Path.GetFileName(files[i]);
if (fileName == fileHolder.Name)
continue;
FaceDistance faceDistance = faceDistanceLengths[i];
if (faceDistance.Length > distanceTolerance)
if (faceDistance.Length is null || faceDistance.Length.Value > distanceTolerance)
continue;
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(fileName));
results.Add(new(files[i], faceDistance.Length, $"[[{fileNameWithoutExtension}]]", $"![{faceDistance.Length}]({relativePaths[i]})"));
distancePermyriad = (int)(faceDistance.Length.Value * faceDistancePermyriad);
mappedRelations.Add(new(distancePermyriad, files[i]));
}
}
results = (from l in results orderby l.Length select l).Take(3).ToList();
keyValuePairs.Add(record.File, results.Count);
foreach (Mapped mapped in results)
{
if (!linkedOnce.Contains(mapped.File))
{
linkedOnce.Add(mapped.File);
continue;
mappedRelations = (from l in mappedRelations orderby l.DistancePermyriad select l).Take(locationContainerDistanceTake).ToList();
results.Add(new(fileHolder, new(mappedRelations)));
}
if (!linkedTwice.Contains(mapped.File))
{
linkedTwice.Add(mapped.File);
continue;
}
if (!linkedThrice.Contains(mapped.File))
{
linkedThrice.Add(mapped.File);
continue;
}
if (!linkedFour.Contains(mapped.File))
{
linkedFour.Add(mapped.File);
continue;
}
if (!linkedFive.Contains(mapped.File))
{
linkedFive.Add(mapped.File);
continue;
}
}
if (isCounterPersonYear)
(years, _) = Shared.Models.Stateless.Methods.IAge.GetAge(ticks, fileInfo.CreationTime.Ticks);
else
(years, _) = Shared.Models.Stateless.Methods.IAge.GetAge(fileInfo.CreationTime.Ticks, personKey);
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(fileInfo.Name));
lines.Add("---");
lines.Add("type: \"distance\"");
lines.Add("---");
lines.Add(string.Empty);
if (displayDirectoryName is null)
lines.Add($"## {personKeyFormatted}");
else
lines.Add($"## {displayDirectoryName}");
lines.Add(string.Empty);
lines.Add($"![0]({uri.MakeRelativeUri(new(record.File)).OriginalString})");
lines.Add($"__{fileNameWithoutExtension}__");
if (isCounterPersonYear)
lines.Add($"#{years}yrs-ago");
else
lines.Add($"#{years}yrs-old");
lines.Add(string.Empty);
lines.AddRange(results.Select(l => $"{l.Image}{Environment.NewLine}{l.Link}{Environment.NewLine}"));
text = string.Join(Environment.NewLine, lines);
if (!Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(directory, $"{fileNameWithoutExtension}.md"), text, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null))
continue;
}
MoveFiles(locationContainerDebugDirectory, isCounterPersonYear, displayDirectoryName, keyValuePairs, linkedOnce, linkedTwice, linkedThrice, linkedFour, linkedFive);
return new(results);
}
void IDistance<MetadataExtractor.Directory>.SaveMappedForOutputResolutions(string locationContainerDebugDirectory, string a2PeopleContentDirectory, string eDistanceContentDirectory, float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers, long personKey, bool isCounterPersonYear, string personKeyFormatted, string? displayDirectoryName)
ReadOnlyCollection<RelationContainer> IDistance<MetadataExtractor.Directory>.GetRelationContainers(int faceDistancePermyriad, int locationContainerDistanceTake, float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{
ReadOnlyCollection<RelationContainer> result;
string? json;
List<Record> records = new();
Shared.Models.FaceEncoding? modelsFaceEncoding;
@ -699,15 +546,8 @@ public partial class E_Distance : IDistance<MetadataExtractor.Directory>
faceRecognitionDotNetFaceEncoding = FaceRecognition.LoadFaceEncoding(modelsFaceEncoding.RawEncoding);
records.Add(new(locationContainer.File, faceRecognitionDotNetFaceEncoding));
}
string directory = Path.Combine(a2PeopleContentDirectory, locationContainerDistanceTolerance.ToString(), personKeyFormatted);
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
if (records.Count > 0)
{
WriteVsCodeFiles(eDistanceContentDirectory, displayDirectoryName, directory);
SaveMappedForOutputResolutions(locationContainerDebugDirectory, eDistanceContentDirectory, locationContainerDistanceTolerance, personKey, isCounterPersonYear, personKeyFormatted, displayDirectoryName, records, directory);
}
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(directory);
result = GetRelationCollections(faceDistancePermyriad, locationContainerDistanceTake, locationContainerDistanceTolerance, records);
return result;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -315,7 +315,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
if (lossCount != 0 || unableToMatchCount != 0)
{ }
if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && configuration.LocationContainerDistanceTolerance is not null)
Stateless.MapLogic.SaveMappedRelations(configuration, distance, a2PeopleContentDirectory, eDistanceContentDirectory, ticks, locationContainers, readOnlyPersonKeyFormattedToPersonContainer, readOnlyPersonKeyToPersonContainerCollection);
Stateless.RelationLogic.SaveMappedRelations(configuration, distance, a2PeopleContentDirectory, eDistanceContentDirectory, ticks, locationContainers, readOnlyPersonKeyFormattedToPersonContainer, readOnlyPersonKeyToPersonContainerCollection);
if (!string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory))
throw new Exception($"{nameof(configuration.LocationContainerDebugDirectory)} is not IsNullOrEmpty!");
}
@ -681,9 +681,9 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
continue;
if (face.Mapping.MappingFromFilterPre.InSkipCollection is not null && face.Mapping.MappingFromFilterPre.InSkipCollection.Value)
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance<object>));
if (face.Mapping.MappingFromFilterPre.IsFocusModel is not null && face.Mapping.MappingFromFilterPre.IsFocusModel.Value)
if (face.Mapping.MappingFromFilterPre.IsFocusModel is not null && !face.Mapping.MappingFromFilterPre.IsFocusModel.Value)
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance<object>));
if (face.Mapping.MappingFromFilterPre.IsFocusRelativePath is not null && face.Mapping.MappingFromFilterPre.IsFocusRelativePath.Value)
if (face.Mapping.MappingFromFilterPre.IsFocusRelativePath is not null && !face.Mapping.MappingFromFilterPre.IsFocusRelativePath.Value)
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance<object>));
if (face.Mapping.MappingFromFilterPost.InSkipCollection is not null && face.Mapping.MappingFromFilterPost.InSkipCollection.Value)
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance<object>));
@ -696,6 +696,8 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
throw new NotSupportedException();
if (faceDistanceLength.Length == 0)
continue;
if (faceDistanceLength.Id == faceDistanceEncoding.Id)
continue;
if (faceDistanceLength.MappingFromFilterPost is null)
throw new NotSupportedException();
if (faceDistanceLength.MappingFromFilterPost.CanReMap is not null && !_Configuration.ReMap)
@ -890,9 +892,9 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
mappingFromFilterPost = sortingContainer.Source.MappingFromFilterPost;
if (sortingContainer.Source.MappingFromFilterPre.InSkipCollection is not null && sortingContainer.Source.MappingFromFilterPre.InSkipCollection.Value)
throw new NotSupportedException(nameof(GetSortingCollection));
if (sortingContainer.Source.MappingFromFilterPre.IsFocusModel is not null && sortingContainer.Source.MappingFromFilterPre.IsFocusModel.Value)
if (sortingContainer.Source.MappingFromFilterPre.IsFocusModel is not null && !sortingContainer.Source.MappingFromFilterPre.IsFocusModel.Value)
throw new NotSupportedException(nameof(GetSortingCollection));
if (sortingContainer.Source.MappingFromFilterPre.IsFocusRelativePath is not null && sortingContainer.Source.MappingFromFilterPre.IsFocusRelativePath.Value)
if (sortingContainer.Source.MappingFromFilterPre.IsFocusRelativePath is not null && !sortingContainer.Source.MappingFromFilterPre.IsFocusRelativePath.Value)
throw new NotSupportedException(nameof(GetSortingCollection));
if (sortingContainer.Source.MappingFromFilterPost.InSkipCollection is not null && sortingContainer.Source.MappingFromFilterPost.InSkipCollection.Value)
throw new NotSupportedException(nameof(GetSortingCollection));
@ -905,6 +907,8 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
throw new NotSupportedException();
if (!wholePercentagesToMapping.TryGetValue(sorting.WholePercentages, out keyMapping))
throw new NotSupportedException();
if (sortingContainer.Source.MappingFromItem.Id == keyMapping.MappingFromItem.Id)
throw new NotSupportedException(nameof(GetSortingCollection));
if (keyMapping.MappingFromFilterPost.CanReMap is not null && !_Configuration.ReMap)
throw new NotSupportedException(nameof(GetSortingCollection));
if (keyMapping.MappingFromFilterPost.CanReMap is not null && !keyMapping.MappingFromFilterPost.CanReMap.Value)
@ -1337,14 +1341,14 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
string? directoryName;
List<int> distinctFilteredIds = IContainer.GetFilteredDistinctIds(propertyConfiguration, containers);
LookForAbandoned(propertyConfiguration, distinctFilteredIds);
Stateless.MapLogic.LookForAbandoned(bResultsFullGroupDirectory, distinctFilteredIds);
Stateless.LookForAbandonedLogic.LookForAbandoned(bResultsFullGroupDirectory, distinctFilteredIds);
directories = Directory.GetDirectories(cResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string directory in directories)
{
directoryName = Path.GetFileName(directory);
if (string.IsNullOrEmpty(directoryName) || directoryName.Length != 2 && directoryName.Length != 4)
continue;
Stateless.MapLogic.LookForAbandoned(distinctFilteredIds, directory, directoryName);
Stateless.LookForAbandonedLogic.LookForAbandoned(distinctFilteredIds, directory, directoryName);
}
directories = Directory.GetDirectories(dResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string directory in directories)
@ -1352,7 +1356,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
directoryName = Path.GetFileName(directory);
if (string.IsNullOrEmpty(directoryName) || directoryName.Length != 2 && directoryName.Length != 4)
continue;
Stateless.MapLogic.LookForAbandoned(distinctFilteredIds, directory, directoryName);
Stateless.LookForAbandonedLogic.LookForAbandoned(distinctFilteredIds, directory, directoryName);
}
directories = Directory.GetDirectories(d2ResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string directory in directories)
@ -1360,7 +1364,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
directoryName = Path.GetFileName(directory);
if (string.IsNullOrEmpty(directoryName) || directoryName.Length != 2 && directoryName.Length != 4)
continue;
Stateless.MapLogic.LookForAbandoned(distinctFilteredIds, directory, directoryName);
Stateless.LookForAbandonedLogic.LookForAbandoned(distinctFilteredIds, directory, directoryName);
}
}

View File

@ -0,0 +1,72 @@
using System.Collections.ObjectModel;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Map.Models.Stateless;
internal abstract class DecadeLogic
{
internal static string GetDecade(MappingFromItem mappingFromItem)
{
string result;
string year;
if (mappingFromItem.DateTimeOriginal is null)
{
year = mappingFromItem.MinimumDateTime.Year.ToString();
result = year[3] > '4' ? $"#{year[..3]}+" : $"#{year[..3]}-";
}
else
{
year = mappingFromItem.DateTimeOriginal.Value.Year.ToString();
result = year[3] > '4' ? $"^{year[..3]}+" : $"^{year[..3]}-";
}
return result;
}
internal static void SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{
DateTime dateTime;
FileInfo fileInfo;
string halfDecade;
string checkDirectory;
string? yearDirectory;
string yearDirectoryName;
string? personNameDirectory;
string personNameDirectoryName;
string? personKeyFormattedDirectory;
string? personKeyFormattedDirectoryName;
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
{
fileInfo = new(locationContainer.File);
if (!fileInfo.Exists)
continue;
dateTime = mappingFromItem.DateTimeOriginal is null ? mappingFromItem.MinimumDateTime : mappingFromItem.DateTimeOriginal.Value;
if (fileInfo.CreationTime != dateTime)
File.SetCreationTime(locationContainer.File, dateTime);
if (!moveToDecade)
continue;
personNameDirectory = Path.GetDirectoryName(locationContainer.File);
if (string.IsNullOrEmpty(personNameDirectory))
continue;
personNameDirectoryName = Path.GetFileName(personNameDirectory);
yearDirectory = Path.GetDirectoryName(personNameDirectory);
if (string.IsNullOrEmpty(yearDirectory))
continue;
yearDirectoryName = Path.GetFileName(yearDirectory);
personKeyFormattedDirectory = Path.GetDirectoryName(yearDirectory);
if (string.IsNullOrEmpty(personKeyFormattedDirectory))
continue;
personKeyFormattedDirectoryName = Path.GetFileName(personKeyFormattedDirectory);
if (personKeyFormattedDirectoryName.Length != propertyConfiguration.PersonBirthdayFormat.Length)
break;
halfDecade = GetDecade(mappingFromItem);
if (halfDecade == yearDirectoryName)
continue;
checkDirectory = Path.Combine(personKeyFormattedDirectory, halfDecade, personNameDirectoryName);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
File.Move(locationContainer.File, Path.Combine(checkDirectory, Path.GetFileName(locationContainer.File)));
}
}
}

View File

@ -0,0 +1,51 @@
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Map.Models.Stateless;
internal abstract class LookForAbandonedLogic
{
internal static void LookForAbandoned(List<int> distinctFilteredIds, string directory, string directoryName)
{
string fileNameWithoutExtension;
bool nameWithoutExtensionIsIdFormat;
List<string> renameCollection = new();
bool nameWithoutExtensionIsPaddedIdFormat;
int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex();
string[] distinctFilteredIdsValues = distinctFilteredIds.Select(l => l.ToString()).ToArray();
string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
foreach (string file in files)
{
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(file)));
nameWithoutExtensionIsIdFormat = IProperty.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension);
nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileNameWithoutExtension, sortOrderOnlyLengthIndex);
if (!nameWithoutExtensionIsIdFormat && !nameWithoutExtensionIsPaddedIdFormat)
continue;
if (distinctFilteredIdsValues.Contains(fileNameWithoutExtension))
continue;
renameCollection.Add(file);
}
if (renameCollection.Count > 0)
{
if (directoryName.Length == 2)
IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[0]}abd{directoryName[^1]}");
else if (directoryName.Length == 4)
IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[..2]}abd{directoryName[^2..]}");
else
throw new NotSupportedException();
}
}
internal static void LookForAbandoned(string bResultsFullGroupDirectory, List<int> distinctFilteredIds)
{
string[] directories = Directory.GetDirectories(bResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string directory in directories)
{
string? directoryName = Path.GetFileName(directory);
if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4))
continue;
LookForAbandoned(distinctFilteredIds, directory, directoryName);
}
}
}

View File

@ -841,37 +841,6 @@ internal abstract class MapLogic
return results;
}
internal static void LookForAbandoned(List<int> distinctFilteredIds, string directory, string directoryName)
{
string fileNameWithoutExtension;
bool nameWithoutExtensionIsIdFormat;
List<string> renameCollection = new();
bool nameWithoutExtensionIsPaddedIdFormat;
int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex();
string[] distinctFilteredIdsValues = distinctFilteredIds.Select(l => l.ToString()).ToArray();
string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
foreach (string file in files)
{
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(file)));
nameWithoutExtensionIsIdFormat = IProperty.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension);
nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileNameWithoutExtension, sortOrderOnlyLengthIndex);
if (!nameWithoutExtensionIsIdFormat && !nameWithoutExtensionIsPaddedIdFormat)
continue;
if (distinctFilteredIdsValues.Contains(fileNameWithoutExtension))
continue;
renameCollection.Add(file);
}
if (renameCollection.Count > 0)
{
if (directoryName.Length == 2)
IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[0]}abd{directoryName[^1]}");
else if (directoryName.Length == 4)
IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[..2]}abd{directoryName[^2..]}");
else
throw new NotSupportedException();
}
}
private static List<Record> GetRecords(Configuration configuration, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, List<string> distinct, string? personDisplayDirectoryName)
{
List<Record> results = new();
@ -1652,18 +1621,6 @@ internal abstract class MapLogic
}
}
internal static void LookForAbandoned(string bResultsFullGroupDirectory, List<int> distinctFilteredIds)
{
string[] directories = Directory.GetDirectories(bResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string directory in directories)
{
string? directoryName = Path.GetFileName(directory);
if (string.IsNullOrEmpty(directoryName) || (directoryName.Length != 2 && directoryName.Length != 4))
continue;
LookForAbandoned(distinctFilteredIds, directory, directoryName);
}
}
internal static ReadOnlyDictionary<int, List<int>> ConvertSkip(Dictionary<int, List<(string, int)>> skipCollection)
{
Dictionary<int, List<int>> results = new();
@ -1712,168 +1669,6 @@ internal abstract class MapLogic
return new(results);
}
internal static string GetDecade(MappingFromItem mappingFromItem)
{
string result;
string year;
if (mappingFromItem.DateTimeOriginal is null)
{
year = mappingFromItem.MinimumDateTime.Year.ToString();
result = year[3] > '4' ? $"#{year[..3]}+" : $"#{year[..3]}-";
}
else
{
year = mappingFromItem.DateTimeOriginal.Value.Year.ToString();
result = year[3] > '4' ? $"^{year[..3]}+" : $"^{year[..3]}-";
}
return result;
}
internal static void SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{
DateTime dateTime;
FileInfo fileInfo;
string halfDecade;
string checkDirectory;
string? yearDirectory;
string yearDirectoryName;
string? personNameDirectory;
string personNameDirectoryName;
string? personKeyFormattedDirectory;
string? personKeyFormattedDirectoryName;
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
{
fileInfo = new(locationContainer.File);
if (!fileInfo.Exists)
continue;
dateTime = mappingFromItem.DateTimeOriginal is null ? mappingFromItem.MinimumDateTime : mappingFromItem.DateTimeOriginal.Value;
if (fileInfo.CreationTime != dateTime)
File.SetCreationTime(locationContainer.File, dateTime);
if (!moveToDecade)
continue;
personNameDirectory = Path.GetDirectoryName(locationContainer.File);
if (string.IsNullOrEmpty(personNameDirectory))
continue;
personNameDirectoryName = Path.GetFileName(personNameDirectory);
yearDirectory = Path.GetDirectoryName(personNameDirectory);
if (string.IsNullOrEmpty(yearDirectory))
continue;
yearDirectoryName = Path.GetFileName(yearDirectory);
personKeyFormattedDirectory = Path.GetDirectoryName(yearDirectory);
if (string.IsNullOrEmpty(personKeyFormattedDirectory))
continue;
personKeyFormattedDirectoryName = Path.GetFileName(personKeyFormattedDirectory);
if (personKeyFormattedDirectoryName.Length != propertyConfiguration.PersonBirthdayFormat.Length)
break;
halfDecade = GetDecade(mappingFromItem);
if (halfDecade == yearDirectoryName)
continue;
checkDirectory = Path.Combine(personKeyFormattedDirectory, halfDecade, personNameDirectoryName);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
File.Move(locationContainer.File, Path.Combine(checkDirectory, Path.GetFileName(locationContainer.File)));
}
}
private static ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> GetCollections(List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{
List<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> results = new();
List<LocationContainer<MetadataExtractor.Directory>>? collection;
Dictionary<long, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePairs = new();
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
{
if (!locationContainer.FromDistanceContent)
continue;
if (!keyValuePairs.TryGetValue(locationContainer.PersonKey, out collection))
{
keyValuePairs.Add(locationContainer.PersonKey, new());
if (!keyValuePairs.TryGetValue(locationContainer.PersonKey, out collection))
throw new Exception();
}
collection.Add(locationContainer);
}
foreach (KeyValuePair<long, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePair in keyValuePairs)
results.Add(new(keyValuePair.Value));
return new(results);
}
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 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);
}
}
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)
{
bool isCounterPersonYear;
string personKeyFormatted;
string? displayDirectoryName;
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
string message = $") Save Mapped Relations - {totalSeconds} total second(s)";
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> collections = GetCollections(locationContainers);
using ProgressBar progressBar = new(collections.Count, message, options);
foreach (ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> collection in collections)
{
if (configuration.LocationContainerDistanceTolerance is null)
break;
progressBar.Tick();
if (collection.Count == 0)
continue;
isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(new DateTime(collection[0].PersonKey).Year);
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, collection[0].PersonKey);
displayDirectoryName = GetDisplayDirectoryName(readOnlyPersonKeyToPersonContainerCollection, readOnlyPersonKeyFormattedToPersonContainer, collection[0].PersonKey, personKeyFormatted);
distance.SaveMappedForOutputResolutions(configuration.LocationContainerDebugDirectory, a2PeopleContentDirectory, eDistanceContentDirectory, configuration.LocationContainerDistanceTolerance.Value, collection, collection[0].PersonKey, isCounterPersonYear, personKeyFormatted, displayDirectoryName);
}
if (!string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory))
AddDisplayDirectoryNames(configuration, eDistanceContentDirectory, readOnlyPersonKeyFormattedToPersonContainer, readOnlyPersonKeyToPersonContainerCollection, collections);
}
internal static bool? CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers, MappingFromLocation mappingFromLocation)
{
bool? result;

View File

@ -38,7 +38,7 @@ public interface IMapLogic
void TestStatic_SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, Shared.Models.MappingFromItem mappingFromItem, ReadOnlyCollection<Shared.Models.LocationContainer<MetadataExtractor.Directory>> locationContainers) =>
SetCreationTimeMaybeMoveToDecade(propertyConfiguration, moveToDecade, mappingFromItem, locationContainers);
static void SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, Shared.Models.MappingFromItem mappingFromItem, ReadOnlyCollection<Shared.Models.LocationContainer<MetadataExtractor.Directory>> locationContainers) =>
MapLogic.SetCreationTimeMaybeMoveToDecade(propertyConfiguration, moveToDecade, mappingFromItem, locationContainers);
DecadeLogic.SetCreationTimeMaybeMoveToDecade(propertyConfiguration, moveToDecade, mappingFromItem, locationContainers);
bool? TestStatic_CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<Shared.Models.PersonContainer>>? wholePercentagesToPersonContainers, Shared.Models.MappingFromLocation mappingFromLocation) =>
CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);
@ -48,6 +48,6 @@ public interface IMapLogic
string TestStatic_GetDecade(Shared.Models.MappingFromItem mappingFromItem) =>
GetDecade(mappingFromItem);
static string GetDecade(Shared.Models.MappingFromItem mappingFromItem) =>
MapLogic.GetDecade(mappingFromItem);
DecadeLogic.GetDecade(mappingFromItem);
}

View File

@ -0,0 +1,400 @@
using ShellProgressBar;
using System.Collections.ObjectModel;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Map.Models.Stateless;
internal abstract class RelationLogic
{
internal record RelationCollection(ReadOnlyCollection<RelationContainer> RelationContainers,
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(List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
{
List<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> results = new();
List<LocationContainer<MetadataExtractor.Directory>>? collection;
Dictionary<long, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePairs = new();
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
{
if (!locationContainer.FromDistanceContent)
continue;
if (!keyValuePairs.TryGetValue(locationContainer.PersonKey, out collection))
{
keyValuePairs.Add(locationContainer.PersonKey, new());
if (!keyValuePairs.TryGetValue(locationContainer.PersonKey, out collection))
throw new Exception();
}
collection.Add(locationContainer);
}
foreach (KeyValuePair<long, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePair in keyValuePairs)
results.Add(new(keyValuePair.Value));
return new(results);
}
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 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();
char c;
string checkFile;
string debugFile;
string checkDirectory;
string? yearDirectory;
string? personNameDirectory;
string? maybeTicksDirectoryName;
string? personNameDirectoryName;
string? personKeyFormattedDirectory;
Dictionary<string, int> fullNameToCount = new();
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);
yearDirectory = Path.GetDirectoryName(personNameDirectory);
personNameDirectoryName = Path.GetFileName(personNameDirectory);
personKeyFormattedDirectory = Path.GetDirectoryName(yearDirectory);
maybeTicksDirectoryName = Path.GetFileName(personKeyFormattedDirectory);
if (string.IsNullOrEmpty(personNameDirectory) || string.IsNullOrEmpty(yearDirectory) || string.IsNullOrEmpty(personKeyFormattedDirectory) || string.IsNullOrEmpty(personNameDirectoryName))
continue;
c = Convert.ToChar(48 + keyValuePair.Value);
if (c is ':' or ';' or '<' or '=' or '>' or '?')
c = '_';
if (maybeTicksDirectoryName == locationContainerDebugDirectory)
checkDirectory = Path.Combine(yearDirectory, $"{keyValuePair.Value}{new string(c, 7)}");
else
{
if (!string.IsNullOrEmpty(locationContainerDebugDirectory))
continue;
checkDirectory = Path.Combine(personKeyFormattedDirectory, $"{keyValuePair.Value}{new string(c, 7)}");
}
if (maybeTicksDirectoryName != locationContainerDebugDirectory)
{
if (isCounterPersonYear || string.IsNullOrEmpty(displayDirectoryName))
checkDirectory = Path.Combine(checkDirectory, personNameDirectoryName);
else
checkDirectory = Path.Combine(checkDirectory, displayDirectoryName[0].ToString());
}
if (checkDirectory == personNameDirectory)
continue;
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
checkFile = Path.Combine(checkDirectory, Path.GetFileName(keyValuePair.Key));
if (File.Exists(checkFile))
continue;
results.Add(keyValuePair.Key, checkFile);
File.Move(keyValuePair.Key, checkFile);
debugFile = $"{keyValuePair.Key[..^4]}.gif";
if (File.Exists(debugFile))
{
checkFile = Path.Combine(checkDirectory, $"{Path.GetFileName(keyValuePair.Key)[..^4]}.gif");
if (File.Exists(checkFile))
continue;
File.Move(debugFile, checkFile);
}
if (maybeTicksDirectoryName == locationContainerDebugDirectory && !string.IsNullOrEmpty(displayDirectoryName))
{
checkDirectory = Path.Combine(checkDirectory, displayDirectoryName);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
}
}
return new(results);
}
private static RelationCollection GetMappedRelationCollection(string locationContainerDebugDirectory, int take, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers)
{
RelationCollection result;
List<string> linked1 = new();
List<string> linked2 = new();
List<string> linked3 = new();
List<string> linked4 = new();
List<string> linked5 = new();
List<string> linked6 = new();
List<string> linked7 = new();
List<string> linked8 = new();
List<string> linked9 = new();
foreach ((FileHolder fileHolder, ReadOnlyCollection<Relation> relations) in relationContainers)
{
foreach (Relation relation in relations.Take(take))
{
if (!linked1.Contains(relation.File))
{
linked1.Add(relation.File);
continue;
}
if (!linked2.Contains(relation.File))
{
linked2.Add(relation.File);
continue;
}
if (!linked3.Contains(relation.File))
{
linked3.Add(relation.File);
continue;
}
if (!linked4.Contains(relation.File))
{
linked4.Add(relation.File);
continue;
}
if (!linked5.Contains(relation.File))
{
linked5.Add(relation.File);
continue;
}
if (!linked6.Contains(relation.File))
{
linked6.Add(relation.File);
continue;
}
if (!linked7.Contains(relation.File))
{
linked7.Add(relation.File);
continue;
}
if (!linked8.Contains(relation.File))
{
linked8.Add(relation.File);
continue;
}
if (!linked9.Contains(relation.File))
{
linked9.Add(relation.File);
continue;
}
}
}
ReadOnlyDictionary<string, string> movedFiles = MoveFiles(locationContainerDebugDirectory, 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);
return result;
}
private static void WriteFile(int take, long personKey, bool isCounterPersonYear, string personKeyFormatted, string? displayDirectoryName, string directory, long ticks, Uri uri, RelationCollection relationCollection)
{
string a;
string b;
int years;
string text;
string? file;
Relation relation;
string markDownFile;
FileHolder fileHolder;
string originalString;
List<string> lines = new();
string fileNameWithoutExtension;
foreach ((FileHolder relationFileHolder, ReadOnlyCollection<Relation> relations) in relationCollection.RelationContainers)
{
lines.Clear();
if (relationCollection.MovedFiles.TryGetValue(relationFileHolder.FullName, out file))
fileHolder = new(file);
else
fileHolder = new(relationFileHolder.FullName);
if (!relationFileHolder.Exists || relationFileHolder.CreationTime is null)
continue;
if (isCounterPersonYear)
(years, _) = IAge.GetAge(ticks, relationFileHolder.CreationTime.Value.Ticks);
else
(years, _) = IAge.GetAge(relationFileHolder.CreationTime.Value.Ticks, personKey);
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileHolder.NameWithoutExtension);
markDownFile = $"{fileNameWithoutExtension}.md";
lines.Add("---");
lines.Add("type: \"distance\"");
lines.Add("---");
lines.Add(string.Empty);
if (displayDirectoryName is null)
lines.Add($"## {personKeyFormatted}");
else
lines.Add($"## {displayDirectoryName}");
lines.Add(string.Empty);
lines.Add($"![0]({uri.MakeRelativeUri(new(relationFileHolder.FullName)).OriginalString})");
lines.Add($"__{fileNameWithoutExtension}__");
if (isCounterPersonYear)
lines.Add($"#{years}yrs-ago");
else
lines.Add($"#{years}yrs-old");
lines.Add($"~~{relations.Count}~~");
lines.Add(string.Empty);
for (int i = 0; i < relations.Count; i++)
{
relation = relations[i];
if (relationCollection.MovedFiles.TryGetValue(relation.File, out file))
fileHolder = new(file);
else
fileHolder = new(relation.File);
if (!fileHolder.Exists || fileHolder.CreationTime is null)
continue;
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileHolder.NameWithoutExtension);
originalString = uri.MakeRelativeUri(new(fileHolder.FullName)).OriginalString;
if (i < take)
(a, b) = ("[[", "]]");
else
(a, b) = ("~~", "~~");
lines.Add($"![{relation.DistancePermyriad}]({originalString}){Environment.NewLine}{a}{fileNameWithoutExtension}{b}");
lines.Add(string.Empty);
}
text = string.Join(Environment.NewLine, lines);
File.WriteAllText(Path.Combine(directory, markDownFile), text);
}
}
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;
}
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)
{
int take;
string directory;
bool isCounterPersonYear;
string personKeyFormatted;
string? displayDirectoryName;
Uri uri = new(eDistanceContentDirectory);
RelationCollection relationCollection;
ReadOnlyCollection<RelationContainer> relationContainers;
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
string message = $") Save Mapped Relations - {totalSeconds} total second(s)";
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
ReadOnlyCollection<ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>> collections = GetCollections(locationContainers);
using ProgressBar progressBar = new(collections.Count, message, options);
foreach (ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> collection in collections)
{
if (configuration.LocationContainerDistanceTolerance is null)
break;
progressBar.Tick();
if (collection.Count == 0)
continue;
take = GetTake(configuration.LocationContainerDistanceTake, collection.Count);
isCounterPersonYear = IPersonBirthday.IsCounterPersonYear(new DateTime(collection[0].PersonKey).Year);
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, collection[0].PersonKey);
displayDirectoryName = GetDisplayDirectoryName(readOnlyPersonKeyToPersonContainerCollection, readOnlyPersonKeyFormattedToPersonContainer, collection[0].PersonKey, personKeyFormatted);
directory = Path.Combine(a2PeopleContentDirectory, $"{ticks}-{configuration.LocationContainerDistanceTolerance.Value}", personKeyFormatted);
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
WriteVsCodeFiles(eDistanceContentDirectory, displayDirectoryName, directory);
relationContainers = distance.GetRelationContainers(configuration.FaceDistancePermyriad, configuration.LocationContainerDistanceTake, configuration.LocationContainerDistanceTolerance.Value, collection);
relationCollection = GetMappedRelationCollection(configuration.LocationContainerDebugDirectory, take, isCounterPersonYear, displayDirectoryName, relationContainers);
WriteFile(take, collection[0].PersonKey, isCounterPersonYear, personKeyFormatted, displayDirectoryName, directory, ticks, uri, relationCollection);
}
if (string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory))
_ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
else
AddDisplayDirectoryNames(configuration, eDistanceContentDirectory, readOnlyPersonKeyFormattedToPersonContainer, readOnlyPersonKeyToPersonContainerCollection, collections);
}
}

View File

@ -15,39 +15,46 @@ taskTemplate: '^+^_${overdue ? ''^R'' : ''''}${name}^: ${relations ? (''\n^-^/^g
## Backlog
- [use-photo-prism-to-map](tasks/use-photo-prism-to-map.md)
- [google-timeline-for-geo](tasks/google-timeline-for-geo.md)
- [import-face-region-metadata](tasks/import-face-region-metadata.md)
- [setup-syncthing-server](tasks/setup-syncthing-server.md)
- [cluster-questioning](tasks/cluster-questioning.md)
- [photoview-in-docker-for-a-viewer-only](tasks/photoview-in-docker-for-a-viewer-only.md)
- [image-size-distribution-per-exif-model-directory-when-no-model](tasks/image-size-distribution-per-exif-model-directory-when-no-model.md)
- [import-know-faces-into-db](tasks/import-know-faces-into-db.md)
- [skip-metadata-load-after-first-each-day](tasks/skip-metadata-load-after-first-each-day.md)
- [determine-if-location-container-collection-is-needed-in-get-faces](tasks/determine-if-location-container-collection-is-needed-in-get-faces.md)
- [cluster-questioning](tasks/cluster-questioning.md)
## 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)
- [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)
- [find-incorrectly-mapped-faces](tasks/find-incorrectly-mapped-faces.md)
- [nef-support](tasks/nef-support.md)
- [set-date-taken-when-missing](tasks/set-date-taken-when-missing.md)
- [triangle-over-person-in-full-image-for-some](tasks/triangle-over-person-in-full-image-for-some.md)
- [find-incorrectly-mapped-faces](tasks/find-incorrectly-mapped-faces.md)
- [google-timeline-for-geo](tasks/google-timeline-for-geo.md)
- [neo4j-db-import](tasks/neo4j-db-import.md)
## In Progress
- [name-some-from-638324064000000000-verify-manual-still-works](tasks/name-some-from-638324064000000000-verify-manual-still-works.md)
- [merge-kristy-files](tasks/merge-kristy-files.md)
- [review-location-container-distance-tolerance](tasks/review-location-container-distance-tolerance.md)
- [can-re-map](tasks/can-re-map.md)
## Done
- [eof-error](tasks/eof-error.md)
- [shrink-percent](tasks/shrink-percent.md)
- [setup-photo-prism-again-in-wsl-docker](tasks/setup-photo-prism-again-in-wsl-docker.md)
- [linked-to-9](tasks/linked-to-9.md)
- [fix-random-logic](tasks/fix-random-logic.md)
- [filter-same-id](tasks/filter-same-id.md)
- [can-re-map](tasks/can-re-map.md)
- [move-copy-manual-files-to-get-display-directory-all-files](tasks/move-copy-manual-files-to-get-display-directory-all-files.md)
- [rename-files-to-padded-number-string](tasks/rename-files-to-padded-number-string.md)
- [reload-slideshow](tasks/reload-slideshow.md)
- [review-location-container-distance-tolerance-needs-to-be-unique](tasks/review-location-container-distance-tolerance-needs-to-be-unique.md)
- [genealogical-data-communication-as-golden](tasks/genealogical-data-communication-as-golden.md)
- [look-for-family-from-jlink-in-x-mapped](tasks/look-for-family-from-jlink-in-x-mapped.md)
- [move-over-2023-california-pictures](tasks/move-over-2023-california-pictures.md)

View File

@ -1,10 +1,11 @@
---
created: 2023-09-06T01:48:53.593Z
updated: 2023-09-06T01:48:53.588Z
updated: 2023-09-09T15:16:04.076Z
assigned: ""
progress: 0
tags: []
started: 2023-09-06T01:48:53.593Z
completed: 2023-09-09T15:16:04.076Z
---
# CanReMap

View File

@ -1,9 +1,10 @@
---
created: "2023-07-17T06:39:53.148Z"
updated: "2023-07-21T21:36:44.190Z"
created: 2023-07-17T06:39:53.148Z
updated: 2023-09-09T06:30:37.280Z
assigned: ""
progress: 0
type: "kanbn"
type: kanbn
started: 2023-09-09T06:30:28.358Z
---
# Cluster Questioning

View File

@ -0,0 +1,11 @@
---
created: 2023-09-09T15:00:50.872Z
updated: 2023-09-09T15:37:00.549Z
assigned: ""
progress: 0
tags: []
started: 2023-09-09T15:00:50.872Z
completed: 2023-09-09T15:37:00.549Z
---
# Filter same id

View File

@ -1,11 +1,11 @@
---
created: "2023-07-21T18:26:38.901Z"
updated: "2023-07-21T18:26:38.902Z"
created: 2023-07-21T18:26:38.901Z
updated: 2023-09-09T06:30:12.385Z
assigned: ""
progress: 0
tags: []
status: '3-In Progress'
type: "kanbn"
type: kanbn
---
# Find Incorrectly Mapped Faces

View File

@ -1,10 +1,10 @@
---
created: "2023-07-21T18:26:38.903Z"
updated: "2023-07-21T18:26:38.903Z"
created: 2023-07-21T18:26:38.903Z
updated: 2023-09-09T06:31:23.591Z
assigned: ""
progress: 0
status: "1-Backlog"
type: "kanbn"
status: 1-Backlog
type: kanbn
---
# Google Timeline for Geo

View File

@ -0,0 +1,13 @@
---
created: 2023-09-09T15:36:54.752Z
updated: 2023-09-09T21:51:25.431Z
assigned: ""
progress: 0
tags: []
started: 2023-09-09T15:36:54.752Z
completed: 2023-09-09T21:51:25.432Z
---
# Linked to 9
Convert.ToChar(48 + keyValuePair.Value)

View File

@ -0,0 +1,10 @@
---
created: 2023-09-09T06:28:12.578Z
updated: 2023-09-09T21:51:56.736Z
assigned: ""
progress: 0
tags: []
started: 2023-09-08T00:00:00.000Z
---
# Name some from 638324064000000000 verify Manual still works

View File

@ -0,0 +1,9 @@
---
created: 2023-09-09T06:33:28.795Z
updated: 2023-09-09T06:33:28.790Z
assigned: ""
progress: 0
tags: []
---
# Neo4j DB import

View File

@ -0,0 +1,11 @@
---
created: 2023-08-07T00:19:34.160Z
updated: 2023-09-09T15:12:01.657Z
assigned: ""
progress: 1
tags: []
started: 2023-08-05T00:00:00.000Z
completed: 2023-09-08T00:00:00.000Z
---
# ReviewLocationContainerDistanceTolerance needs to be unique

View File

@ -1,10 +0,0 @@
---
created: 2023-08-07T00:19:34.160Z
updated: 2023-08-07T05:46:42.946Z
assigned: ""
progress: 0
tags: []
started: 2023-08-06T00:00:00.000Z
---
# ReviewLocationContainerDistanceTolerance

View File

@ -0,0 +1,10 @@
---
created: 2023-09-09T15:01:12.800Z
updated: 2023-09-09T21:51:53.090Z
assigned: ""
progress: 0
tags: []
started: 2023-09-09T15:01:12.800Z
---
# Run limiting on days

View File

@ -1,6 +1,6 @@
---
created: 2023-08-08T23:48:54.260Z
updated: 2023-08-08T23:48:54.257Z
updated: 2023-09-09T06:31:43.028Z
assigned: ""
progress: 0
tags: []

View File

@ -0,0 +1,9 @@
---
created: 2023-09-09T06:29:03.734Z
updated: 2023-09-09T06:31:45.781Z
assigned: ""
progress: 0
tags: []
---
# Update drag and drop to work with new resize location

View File

@ -0,0 +1,10 @@
---
created: 2023-09-09T15:01:28.239Z
updated: 2023-09-09T21:51:54.599Z
assigned: ""
progress: 0
tags: []
started: 2023-09-09T15:01:28.239Z
---
# Verify camera model still works

View File

@ -5,6 +5,6 @@ namespace View_by_Distance.Shared.Models.Methods;
public interface IDistance<T>
{
void SaveMappedForOutputResolutions(string locationContainerDebugDirectory, string a2PeopleContentDirectory, string eDistanceContentDirectory, float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer<T>> locationContainers, long personKey, bool isCounterPersonYear, string personKeyFormatted, string? displayDirectoryName);
ReadOnlyCollection<RelationContainer> GetRelationContainers(int faceDistancePermyriad, int locationContainerDistanceTake, float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer<T>> locationContainers);
}

14
Shared/Models/Relation.cs Normal file
View File

@ -0,0 +1,14 @@
using System.Text.Json;
namespace View_by_Distance.Shared.Models;
public record Relation(int DistancePermyriad, string File)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,15 @@
using System.Collections.ObjectModel;
using System.Text.Json;
namespace View_by_Distance.Shared.Models;
public record RelationContainer(FileHolder FileHolder, ReadOnlyCollection<Relation> RelationCollections)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}