298 lines
13 KiB
C#
298 lines
13 KiB
C#
using System.Text.Json;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
|
|
|
internal abstract class Person
|
|
{
|
|
|
|
// ...
|
|
|
|
private static List<string> ValidatePerson(Properties.IStorage storage, Models.PersonId id, Models.PersonBirthday birthday, Models.PersonName name)
|
|
{
|
|
List<string> 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<Models.PersonComment> comments, List<Models.PersonURL> urls, List<Models.PersonNumber> numbers, List<Models.PersonEmail> emails, List<Models.PersonAddress> addresses)
|
|
{
|
|
Models.Person result;
|
|
Models.PersonId id = new(birthday.Value.Ticks);
|
|
if (birthday.Value == DateTime.MinValue)
|
|
birthday = PersonBirthday.GetNextBirthDate(storage);
|
|
List<string> 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;
|
|
}
|
|
|
|
private static void SetSegments(ref string[] segments, string KeyFormat, ref DateTime incrementDate)
|
|
{
|
|
if (segments[0].Length != KeyFormat.Length || !segments[0].Contains('-') || !segments[0].Contains('_'))
|
|
{
|
|
List<string> temporarySegments;
|
|
temporarySegments = segments.ToList();
|
|
temporarySegments.Insert(0, incrementDate.ToString(KeyFormat));
|
|
segments = temporarySegments.ToArray();
|
|
incrementDate = incrementDate.AddDays(1);
|
|
}
|
|
}
|
|
|
|
internal static Dictionary<DateTime, string[]> Split(string knownPeopleFile)
|
|
{
|
|
Dictionary<DateTime, string[]> results = new();
|
|
string[] segments;
|
|
DateTime personKey;
|
|
DateTime incrementDate = new(Stateless.IPersonBirthday.FirstYear, 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;
|
|
SetSegments(ref segments, Stateless.IPerson.KeyFormat, ref incrementDate);
|
|
personKey = DateTime.ParseExact(segments[0], Stateless.IPerson.KeyFormat, cultureInfo);
|
|
if (results.ContainsKey(personKey))
|
|
continue;
|
|
results.Add(personKey, segments);
|
|
}
|
|
if (results.Any())
|
|
{
|
|
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(Stateless.IPerson.KeyFormat) });
|
|
}
|
|
}
|
|
return results.OrderBy(l => l.Key).ToDictionary(l => l.Key, l => l.Value);
|
|
}
|
|
|
|
private static void SetValues(ref string name, ref string comment, ref string mergeName, KeyValuePair<DateTime, string[]> splitLine)
|
|
{
|
|
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];
|
|
}
|
|
|
|
private static void CheckSplitLineAndSetValues(ref string name, ref string comment, ref string mergeName, KeyValuePair<DateTime, string[]> splitLine)
|
|
{
|
|
if (splitLine.Value.Length > 1)
|
|
SetValues(ref name, ref comment, ref mergeName, splitLine);
|
|
}
|
|
|
|
private static Dictionary<DateTime, PersonImport> GetPersonCollection(string knownPeopleFile)
|
|
{
|
|
Dictionary<DateTime, PersonImport> results = new();
|
|
string name;
|
|
DateTime key;
|
|
string comment;
|
|
string oldName;
|
|
string mergeName;
|
|
PersonImport person;
|
|
Dictionary<DateTime, string[]> splitLines = Split(knownPeopleFile);
|
|
foreach (KeyValuePair<DateTime, string[]> splitLine in splitLines)
|
|
{
|
|
name = string.Empty;
|
|
key = splitLine.Key;
|
|
comment = string.Empty;
|
|
oldName = string.Empty;
|
|
mergeName = string.Empty;
|
|
CheckSplitLineAndSetValues(ref name, ref comment, ref mergeName, splitLine);
|
|
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, updateDateWhenMatches: true, compareBeforeWrite: true);
|
|
}
|
|
|
|
private static string GetComment(List<Models.PersonURL> urls, List<Models.PersonComment> comments, KeyValuePair<DateTime, PersonImport> keyValuePair)
|
|
{
|
|
string result = keyValuePair.Value.Comment[2..];
|
|
if (!string.IsNullOrEmpty(result))
|
|
{
|
|
if (result.StartsWith("http://") || result.StartsWith("https://"))
|
|
urls.Add(new(new(result)));
|
|
else
|
|
comments.Add(new(new(result)));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static List<Models.Person> GetPeopleFromText(Properties.IStorage storage, string localKnownPeopleFile)
|
|
{
|
|
List<Models.Person> results = new();
|
|
string comment;
|
|
Models.Person person;
|
|
Models.PersonName name;
|
|
List<Models.PersonURL> urls;
|
|
Models.PersonBirthday birthday;
|
|
List<Models.PersonComment> comments;
|
|
List<Models.PersonEmail> emails = new();
|
|
List<Models.PersonNumber> numbers = new();
|
|
List<Models.PersonAddress> addresses = new();
|
|
Dictionary<DateTime, PersonImport> keyValuePairs = GetPersonCollection(localKnownPeopleFile);
|
|
foreach (KeyValuePair<DateTime, PersonImport> keyValuePair in keyValuePairs)
|
|
{
|
|
if (string.IsNullOrEmpty(keyValuePair.Value.Name))
|
|
continue;
|
|
urls = new();
|
|
comments = 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 = GetComment(urls, comments, keyValuePair);
|
|
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<Models.Person> results = new();
|
|
string json;
|
|
string[] files;
|
|
FileInfo fileInfo;
|
|
Models.Person? person;
|
|
string localKnownPeopleFile;
|
|
DateTime dateTime = DateTime.MinValue;
|
|
string peopleContentDirectory = Path.Combine(storage.PeopleRootDirectory, "()");
|
|
string peopleSingletonDirectory = Path.Combine(storage.PeopleRootDirectory, "{}");
|
|
if (!Directory.Exists(peopleSingletonDirectory))
|
|
_ = Directory.CreateDirectory(peopleSingletonDirectory);
|
|
if (!Directory.Exists(peopleContentDirectory))
|
|
localKnownPeopleFile = string.Empty;
|
|
else
|
|
{
|
|
files = Directory.GetFiles(peopleContentDirectory, "*People*.txt", SearchOption.TopDirectoryOnly);
|
|
if (files.Any())
|
|
localKnownPeopleFile = files[0];
|
|
else
|
|
localKnownPeopleFile = string.Empty;
|
|
}
|
|
files = Directory.GetFiles(peopleSingletonDirectory, "*.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<Models.Person>(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);
|
|
}
|
|
}
|
|
SaveToDirectory(storage, results);
|
|
return results.ToArray();
|
|
}
|
|
|
|
private static void SaveToDirectory(Properties.IStorage storage, List<Models.Person> people)
|
|
{
|
|
int years;
|
|
TimeSpan? timeSpan;
|
|
string personDirectory;
|
|
string? personFullName;
|
|
DateTime createdDateTime;
|
|
string birthdayDirectory;
|
|
string personJsonFileName;
|
|
string personDirectoryName;
|
|
string? peopleDirectory = null;
|
|
DateTime dateTime = DateTime.Now;
|
|
string? personJsonFileNameWithoutExtension;
|
|
const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]";
|
|
foreach (Models.Person person in people)
|
|
{
|
|
personJsonFileName = IPerson.GetFileFullName(storage, person);
|
|
if (string.IsNullOrEmpty(peopleDirectory))
|
|
peopleDirectory = Path.GetDirectoryName(personJsonFileName);
|
|
if (string.IsNullOrEmpty(peopleDirectory))
|
|
break;
|
|
personJsonFileNameWithoutExtension = Path.GetFileNameWithoutExtension(personJsonFileName);
|
|
if (string.IsNullOrEmpty(personJsonFileNameWithoutExtension))
|
|
break;
|
|
personFullName = Regex.Replace(person.GetFullName(), pattern, string.Empty);
|
|
timeSpan = IPersonBirthday.GetTimeSpan(dateTime, person.Birthday);
|
|
if (timeSpan is null || timeSpan.Value.Ticks < 0)
|
|
personDirectoryName = $"{personFullName}~";
|
|
else
|
|
{
|
|
createdDateTime = new FileInfo(personJsonFileName).CreationTime;
|
|
(years, timeSpan) = IPersonBirthday.GetAge(createdDateTime, person.Birthday);
|
|
personDirectoryName = $"{personFullName}^{years}-{Math.Floor(timeSpan.Value.TotalDays):000}";
|
|
}
|
|
personDirectory = Path.Combine(peopleDirectory, personDirectoryName);
|
|
if (!Directory.Exists(personDirectory))
|
|
_ = Directory.CreateDirectory(personDirectory);
|
|
birthdayDirectory = Path.Combine(personDirectory, personJsonFileNameWithoutExtension);
|
|
if (!Directory.Exists(birthdayDirectory))
|
|
{
|
|
_ = Directory.CreateDirectory(birthdayDirectory);
|
|
File.Copy(personJsonFileName, Path.Combine(birthdayDirectory, $"{personJsonFileNameWithoutExtension}.json"));
|
|
}
|
|
}
|
|
}
|
|
|
|
} |