using System.Text.Json; namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class Person { // ... private static List ValidatePerson(Properties.IStorage storage, Models.PersonId id, Models.PersonBirthday birthday, Models.PersonName name) { List results = new(); if (birthday is null) throw new Exception("Birthday must be supplied!"); if (birthday.Value > DateTime.Now) results.Add("Birthday must be in the past!"); if (id is null) throw new Exception("Birthday must be supplied!"); if (id.Value != birthday.Value.Ticks) results.Add("Id must be Birthday ticks!"); if (name.First is null || string.IsNullOrEmpty(name.First.Value)) results.Add("Fist Name must be supplied!"); if (PersonBirthday.DoesBirthDateExits(storage, birthday)) results.Add("BirthDate already exits!"); return results; } internal static Models.Person CreatePerson(Properties.IStorage storage, Models.PersonBirthday birthday, Models.PersonName name, List comments, List urls, List numbers, List emails, List addresses) { Models.Person result; Models.PersonId id = new(birthday.Value.Ticks); if (birthday.Value == DateTime.MinValue) birthday = PersonBirthday.GetNextBirthDate(storage); List results = ValidatePerson(storage, id, birthday, name); if (results.Any()) throw new Exception(string.Join(Environment.NewLine, results)); if (comments is null) comments = new(); if (urls is null) urls = new(); if (numbers is null) numbers = new(); if (emails is null) emails = new(); if (addresses is null) addresses = new(); result = new(id, birthday, name, comments, urls, numbers, emails, addresses); return result; } internal static Dictionary Split(string knownPeopleFile) { Dictionary results = new(); string[] segments; DateTime personKey; List temporarySegments; const string KeyFormat = "yyyy-MM-dd_HH"; DateTime incrementDate = new(1500, 1, 1); string[] lines = File.ReadAllLines(knownPeopleFile); _ = incrementDate.AddDays(lines.Length); System.Globalization.CultureInfo cultureInfo = System.Globalization.CultureInfo.InvariantCulture; foreach (string line in lines) { if (string.IsNullOrEmpty(line)) continue; segments = line.Replace(" //", "\t//").Split('\t'); if (segments.Length < 1) continue; if (segments[0].Length != KeyFormat.Length || !segments[0].Contains('-') || !segments[0].Contains('_')) { temporarySegments = segments.ToList(); temporarySegments.Insert(0, incrementDate.ToString(KeyFormat)); segments = temporarySegments.ToArray(); incrementDate = incrementDate.AddDays(1); } personKey = DateTime.ParseExact(segments[0], KeyFormat, cultureInfo); if (results.ContainsKey(personKey)) continue; results.Add(personKey, segments); } int countBefore = results.Count; DateTime minimumDateTime = results.Keys.Min(); for (int i = 1; i < (1000 - countBefore); i++) { personKey = minimumDateTime.AddDays(i * -1); results.Add(personKey, new string[] { personKey.ToString(KeyFormat) }); } return results.OrderBy(l => l.Key).ToDictionary(l => l.Key, l => l.Value); } internal static Dictionary GetPersonCollection(string knownPeopleFile) { Dictionary results = new(); string name; DateTime key; string comment; string oldName; string mergeName; PersonImport person; Dictionary splitLines = Split(knownPeopleFile); foreach (KeyValuePair splitLine in splitLines) { name = string.Empty; key = splitLine.Key; comment = string.Empty; oldName = string.Empty; mergeName = string.Empty; if (splitLine.Value.Length > 1) { foreach (string segment in splitLine.Value) { if (!segment.Contains('*')) continue; mergeName = segment.Split('*')[1].Split('\t')[0]; } if (splitLine.Value[1].StartsWith("//")) comment = splitLine.Value[1]; else name = splitLine.Value[1].Split('\t')[0]; if (splitLine.Value.Length > 2) comment = splitLine.Value[2]; } person = new(key, name, mergeName, oldName, comment); results.Add(splitLine.Key, person); } return results; } internal static void SavePerson(Properties.IStorage storage, Models.Person person) { string fileName = IPerson.GetFileFullName(storage, person); string json = JsonSerializer.Serialize(person, new JsonSerializerOptions { WriteIndented = true }); _ = IStorage.WriteAllText(fileName, json, compareBeforeWrite: true); } private static List GetPeopleFromText(Properties.IStorage storage, string localKnownPeopleFile) { List results = new(); string comment; Models.Person person; Models.PersonName name; List urls; Models.PersonBirthday birthday; List emails = new(); List numbers = new(); List comments = new(); List addresses = new(); Dictionary keyValuePairs = GetPersonCollection(localKnownPeopleFile); foreach (KeyValuePair keyValuePair in keyValuePairs) { if (string.IsNullOrEmpty(keyValuePair.Value.Name)) continue; urls = new(); birthday = new(keyValuePair.Key); name = PersonName.Create(keyValuePair.Value.Name); if (name.First is null || string.IsNullOrEmpty(name.First.Value)) continue; if (!string.IsNullOrEmpty(keyValuePair.Value.Comment)) { comment = keyValuePair.Value.Comment[2..]; if (!string.IsNullOrEmpty(comment)) { if (comment.StartsWith("http://") || comment.StartsWith("https://")) urls.Add(new(new(comment))); else comments.Add(new(new(comment))); } } if (!string.IsNullOrEmpty(keyValuePair.Value.OldName)) comments.Add(new(new(keyValuePair.Value.OldName))); person = IPerson.CreatePerson(storage, birthday, name, comments, urls, numbers, emails, addresses); SavePerson(storage, person); results.Add(person); } return results; } internal static Models.Person[] GetPeople(Properties.IStorage storage) { List results = new(); string json; string[] files; FileInfo fileInfo; Models.Person? person; string localKnownPeopleFile; DateTime dateTime = DateTime.MinValue; string directory = Path.Combine(storage.PeopleRootDirectory, "{}"); if (!Directory.Exists(directory)) _ = Directory.CreateDirectory(directory); string? rootDirectoryParent = Path.GetDirectoryName(storage.RootDirectory); if (string.IsNullOrEmpty(rootDirectoryParent)) throw new Exception($"{nameof(rootDirectoryParent)} is null!"); if (!Directory.Exists(rootDirectoryParent)) localKnownPeopleFile = string.Empty; else { files = Directory.GetFiles(rootDirectoryParent, "*People*.txt", SearchOption.TopDirectoryOnly); if (files.Any()) localKnownPeopleFile = files[0]; else localKnownPeopleFile = string.Empty; } files = Directory.GetFiles(directory, "*.json", SearchOption.TopDirectoryOnly); if (!files.Any() && string.IsNullOrEmpty(localKnownPeopleFile)) throw new Exception("Copy \"KnownPeople.txt\" file from server!"); foreach (string file in files) { fileInfo = new(file); if (dateTime < fileInfo.LastWriteTime) dateTime = fileInfo.LastWriteTime; json = File.ReadAllText(file); person = JsonSerializer.Deserialize(json); if (person is null) continue; results.Add(person); } if (!results.Any()) results = GetPeopleFromText(storage, localKnownPeopleFile); else if (!string.IsNullOrEmpty(localKnownPeopleFile)) { fileInfo = new FileInfo(localKnownPeopleFile); if (fileInfo.LastWriteTime > dateTime) { foreach (string file in files) File.Delete(file); results = GetPeopleFromText(storage, localKnownPeopleFile); } } return results.ToArray(); } }