using System.Collections.ObjectModel; using System.Text.Json; using View_by_Distance.Shared.Models; namespace View_by_Distance.Instance.Models; /// <summary> // List<string> /// </summary> internal class F_Random { private readonly Configuration _Configuration; private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; internal F_Random(Configuration configuration) { _Configuration = configuration; _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = false }; } public override string ToString() { string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); return result; } private static ReadOnlyDictionary<string, List<string>> GetDayToRelativePaths(ReadOnlyCollection<Mapping> distinctValidImageMappingCollection, string dateFormat, string immichOwnerId, string immichRoot, Dictionary<string, ImmichAsset> immichAssets, ReadOnlyDictionary<int, List<long>> idToPersonKeys) { Dictionary<string, List<string>> results = []; string key; DateTime dateTime; List<long>? personKeys; ImmichAsset? immichAsset; List<string>? relativePaths; bool immichAssetsCountIsZero = immichAssets.Count == 0; foreach (Mapping mapping in distinctValidImageMappingCollection) { if (mapping.MappingFromItem.FilePath.DirectoryFullPath is null || mapping.MappingFromPerson is null) continue; if (!idToPersonKeys.TryGetValue(mapping.MappingFromItem.Id, out personKeys)) continue; if (Shared.Models.Stateless.Methods.IPersonBirthday.IsCounterPersonYear(mapping.MappingFromPerson.PersonKey)) continue; if (!personKeys.Contains(mapping.MappingFromPerson.PersonKey)) continue; dateTime = new(mapping.MappingFromPerson.PersonKey); key = dateTime.ToString(dateFormat); if (!results.TryGetValue(key, out relativePaths)) { results.Add(key, []); if (!results.TryGetValue(key, out relativePaths)) throw new Exception(); } if (immichAssetsCountIsZero) relativePaths.Add(mapping.MappingFromItem.RelativePath); else { if (!immichAssets.TryGetValue($"{immichRoot}{mapping.MappingFromItem.RelativePath}", out immichAsset)) continue; if (!immichAsset.Path.Contains(immichOwnerId)) continue; relativePaths.Add(immichAsset.Path.Split(immichOwnerId)[1]); } } return results.AsReadOnly(); } private static Dictionary<string, ImmichAsset> GetImmichAssets(string immichAssetsFile) { Dictionary<string, ImmichAsset> results = []; if (!string.IsNullOrEmpty(immichAssetsFile) && File.Exists(immichAssetsFile)) { string json = File.ReadAllText(immichAssetsFile); ImmichAsset[]? immichAssets = JsonSerializer.Deserialize(json, ImmichAssetCollectionSourceGenerationContext.Default.ImmichAssetArray); if (immichAssets is not null) { foreach (ImmichAsset immichAsset in immichAssets) results.Add(immichAsset.OriginalPath, immichAsset); } } return results; } internal void Random(Property.Models.Configuration configuration, string immichAssetsFile, string immichOwnerId, string immichRoot, int radomUseBirthdayMinimum, string[] validKeyWordsToIgnoreInRandom, ReadOnlyDictionary<long, List<int>> personKeyToIds, ReadOnlyDictionary<int, Identifier> splatNineIdentifiers, ReadOnlyCollection<Mapping> distinctValidImageMappingCollection) { string key; string json; string jsonFile; Random random = new(); List<string>? collection; ImmichAsset? immichAsset; string dateFormat = "MM-dd"; List<string> relativePaths = []; List<int> distinctCollection = []; DateTime dateTime = new(2024, 1, 1); //Leap year Dictionary<string, ImmichAsset> immichAssets = GetImmichAssets(immichAssetsFile); int[] splatNineIdentifiersKeys = splatNineIdentifiers.Select(l => l.Key).ToArray(); ReadOnlyDictionary<int, List<long>> idToPersonKeys = Map.Models.Stateless.Methods.IMapLogic.GetIdToPersonKeys(personKeyToIds); ReadOnlyDictionary<string, List<string>> dayToRelativePaths = GetDayToRelativePaths(distinctValidImageMappingCollection, dateFormat, immichOwnerId, immichRoot, immichAssets, idToPersonKeys); string fRandomCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(F_Random), "[]"); string[] files = Directory.GetFiles(fRandomCollectionDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string file in files) File.Delete(file); bool immichAssetsCountIsZero = immichAssets.Count == 0; foreach (Mapping mapping in distinctValidImageMappingCollection) { if (mapping.MappingFromItem.IsArchive is not null && mapping.MappingFromItem.IsArchive.Value) continue; if (distinctCollection.Contains(mapping.MappingFromItem.Id)) continue; if (mapping.MappingFromItem.FilePath.DirectoryFullPath is null) continue; if (!splatNineIdentifiersKeys.Contains(mapping.MappingFromItem.Id)) continue; if (mapping.MappingFromItem.Keywords is not null && mapping.MappingFromItem.Keywords.Any(l => validKeyWordsToIgnoreInRandom.Contains(l))) continue; if (immichAssetsCountIsZero) relativePaths.Add(mapping.MappingFromItem.RelativePath); else { if (!immichAssets.TryGetValue($"{immichRoot}{mapping.MappingFromItem.RelativePath}", out immichAsset)) continue; if (!immichAsset.Path.Contains(immichOwnerId)) continue; relativePaths.Add(immichAsset.Path.Split(immichOwnerId)[1]); } distinctCollection.Add(mapping.MappingFromItem.Id); } if (relativePaths.Count > 0) { for (int i = 0; i < 366; i++) { random = new(i); key = dateTime.AddDays(i).ToString(dateFormat); if (dayToRelativePaths.TryGetValue(key, out collection) && collection.Count > radomUseBirthdayMinimum) collection = (from l in collection orderby random.NextDouble() select l).ToList(); else collection = (from l in relativePaths orderby random.NextDouble() select l).ToList(); jsonFile = Path.Combine(fRandomCollectionDirectory, $"{key}.json"); json = JsonSerializer.Serialize(collection, _WriteIndentedJsonSerializerOptions); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: false, compareBeforeWrite: false); if (!_Configuration.SaveFullYearOfRandomFiles) break; } } } }