using System.Text; using System.Text.Json; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Stateless.Methods; namespace View_by_Distance.PhotoPrism.Models; public class F_PhotoPrism { private static JsonProperty[] GetJsonProperty(string fileName) { JsonProperty[] results; if (!File.Exists(fileName)) results = Array.Empty(); else { string json = File.ReadAllText(fileName); JsonElement? jsonElement = JsonSerializer.Deserialize(json); results = jsonElement.Value.EnumerateObject().ToArray(); } return results; } private static Marker[]? GetMarkers(string fPhotoPrismSingletonDirectory) { Marker[]? results; string file = Path.Combine(fPhotoPrismSingletonDirectory, "markers.json"); JsonProperty[] jsonProperties = GetJsonProperty(file); if (!jsonProperties.Any()) results = null; else results = JsonSerializer.Deserialize(jsonProperties[1].Value); return results; } private static Dictionary> GetFileUIdToMarkers(string fPhotoPrismSingletonDirectory) { Dictionary> results = new(); Marker[]? markers = GetMarkers(fPhotoPrismSingletonDirectory); if (markers is null) throw new NullReferenceException(nameof(markers)); foreach (Marker marker in markers) { if (!results.ContainsKey(marker.FileUid)) results.Add(marker.FileUid, new()); results[marker.FileUid].Add(marker); } return results; } private static DatabaseFile[]? GetDatabaseFiles(string fPhotoPrismSingletonDirectory) { DatabaseFile[]? results; string file = Path.Combine(fPhotoPrismSingletonDirectory, "files.json"); JsonProperty[] jsonProperties = GetJsonProperty(file); if (!jsonProperties.Any()) results = null; else results = JsonSerializer.Deserialize(jsonProperties[1].Value); return results; } public static Dictionary> GetFileNameToCollection(string fPhotoPrismSingletonDirectory) { Dictionary> results = new(); List? makers; MappingFromPhotoPrism mappingFromPhotoPrism; List? mappingFromPhotoPrismCollection; DatabaseFile[]? databaseFiles = GetDatabaseFiles(fPhotoPrismSingletonDirectory); if (databaseFiles is null) throw new NullReferenceException(nameof(databaseFiles)); Dictionary> fileUIdToMarkers = GetFileUIdToMarkers(fPhotoPrismSingletonDirectory); foreach (DatabaseFile databaseFile in databaseFiles) { if (!results.TryGetValue(databaseFile.FileName, out mappingFromPhotoPrismCollection)) { results.Add(databaseFile.FileName, new()); if (!results.TryGetValue(databaseFile.FileName, out mappingFromPhotoPrismCollection)) throw new Exception(); } if (!fileUIdToMarkers.TryGetValue(databaseFile.FileUid, out makers)) mappingFromPhotoPrism = new(databaseFile, new()); else mappingFromPhotoPrism = new(databaseFile, makers); mappingFromPhotoPrismCollection.Add(mappingFromPhotoPrism); } return results; } public static void WriteMatches(string fPhotoPrismContentDirectory, string personBirthdayFormat, long ticks, List distinctFilteredFaces, Shared.Models.Methods.IMapLogic mapLogic) { long? personKey; const int zero = 0; int? normalizedRectangle; string personKeyFormatted; List subjects = new(); PersonBirthday personBirthday; string personDisplayDirectoryName; StringBuilder stringBuilder = new(); PersonContainer[]? personContainers; System.Drawing.Rectangle dlibRectangle; System.Drawing.Rectangle? prismRectangle; System.Drawing.Rectangle intersectRectangle; Dictionary? normalizedRectangleToPersonContainers; (MappingFromPhotoPrism MappingFromPhotoPrism, Marker Marker, double Percent)[] sortedCollection; List<(MappingFromPhotoPrism MappingFromPhotoPrism, Marker Marker, double Percent)> collection = new(); foreach (Face face in distinctFilteredFaces) { collection.Clear(); normalizedRectangle = face.Mapping?.MappingFromLocation.NormalizedRectangle; if (normalizedRectangle is null) continue; if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null || face.Mapping is null) continue; if (face.Mapping.MappingFromPhotoPrismCollection is null) continue; (_, normalizedRectangleToPersonContainers) = mapLogic.GetNormalizedRectangleToPersonContainers(face.Mapping.MappingFromItem.Id); if (normalizedRectangleToPersonContainers is null || !normalizedRectangleToPersonContainers.TryGetValue(normalizedRectangle.Value, out personContainers)) continue; dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top); foreach (MappingFromPhotoPrism mappingFromPhotoPrism in face.Mapping.MappingFromPhotoPrismCollection) { foreach (Marker marker in mappingFromPhotoPrism.Markers) { prismRectangle = ILocation.GetRectangle(face.OutputResolution, mappingFromPhotoPrism.DatabaseFile, marker); if (prismRectangle is null) continue; intersectRectangle = System.Drawing.Rectangle.Intersect(dlibRectangle, prismRectangle.Value); if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0) continue; double percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height); if (percent < 0.000001) continue; collection.Add(new(mappingFromPhotoPrism, marker, percent)); } } if (!collection.Any()) continue; sortedCollection = collection.OrderByDescending(l => l.Percent).ToArray(); foreach ((MappingFromPhotoPrism mappingFromPhotoPrism, Marker marker, double percent) in sortedCollection) { foreach (PersonContainer personContainer in personContainers) { if (personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) continue; personBirthday = personContainer.Birthdays[zero]; personKey = personBirthday.Value.Ticks; personDisplayDirectoryName = personContainer.DisplayDirectoryName; personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday); subjects.Add($"update `subjects` set subj_alias = '{personKeyFormatted}' where subj_name = '{personDisplayDirectoryName}';"); _ = stringBuilder. Append("update `markers` set subj_src = 'manual', marker_name = '"). Append(personDisplayDirectoryName). Append("' where marker_uid = '"). Append(marker.MarkerUid). AppendLine("';"); } } } File.WriteAllLines(Path.Combine(fPhotoPrismContentDirectory, $"{ticks}-subject_alias_update.sql"), subjects.Distinct()); File.WriteAllText(Path.Combine(fPhotoPrismContentDirectory, $"{ticks}-marker_name_update.sql"), stringBuilder.ToString()); } }