Глобальный рефакторинг пространств имён

This commit is contained in:
2025-10-02 13:29:30 +04:00
parent d23d81fb53
commit 2fa94851cb
3176 changed files with 27146 additions and 30584 deletions
@@ -0,0 +1,341 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Pf2e.Database.Model.Base.Source;
namespace Pf2e.Scrapper.Importers.Implementations.Aonprd.Helpers;
/// <summary>
/// Класс коллекции книг, содержащих правила.
/// Реализует шаблон <c>Singleton</c>.
/// </summary>
internal class RuleTocCollection
{
/// <summary>
/// Список книг, содержащих правила.
/// </summary>
public List<RuleTocBook> Books { get; } = [];
/// <summary>
/// Поиск книги по числовому идентификатору.
/// </summary>
public RuleTocBook this[int id] =>
Books.FirstOrDefault(i => i.SourceId == id) ?? throw new($"Book with id {id} not found");
/// <summary>
/// Поиск книги по CLR-представлению источника.
/// </summary>
public RuleTocBook this[Source source]
{
get
{
RuleTocBook? result = Books.FirstOrDefault(i => i.SourceId == source.Id);
if (result is not null)
{
return result;
}
result = new(source);
Books.Add(result);
return result;
}
}
/// <summary>
/// Поиск книги по имени.
/// </summary>
public RuleTocBook? FindName(string name)
{
foreach (RuleTocBook book in Books)
{
if (book.IsNameExists(name))
{
return book;
}
}
return null;
}
/// <summary>
/// Поиск правила по идентификатору.
/// </summary>
public RuleTocItem? FindEntityId(int id)
{
foreach (RuleTocBook book in Books)
{
RuleTocItem? result = book.GetByEntityId(id);
if (result is not null)
{
return result;
}
}
return null;
}
/// <summary>
/// Возвращает строковое представление коллекции в файле YAML.
/// </summary>
public override string ToString()
{
return string.Join("\n", Books.Select(book => book.ToString()).ToList());
}
/// <summary>
/// Сохраняет коллекцию в файле YAML.
/// </summary>
public void SaveFile()
{
string fileName =
$"rules-toc.{new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds()}.debug.yaml";
using FileStream fileStream = File.Create(fileName);
using StreamWriter writer = new(fileStream);
writer.Write(ToString());
}
/// <summary>
/// Экземпляр класса <see cref="RuleTocCollection"/>.
/// </summary>
public static RuleTocCollection Instance { get; } = new();
}
/// <summary>
/// Класс представляет собой книгу, содержащую правила.
/// </summary>
internal class RuleTocBook(Source source)
{
/// <summary>
/// Идентификатор источника.
/// </summary>
public int SourceId { get; } = source.Id;
/// <summary>
/// Названия источника.
/// </summary>
public string SourceName { get; } = source.Name;
/// <summary>
/// Список дочерних правил.
/// </summary>
/// <summary>
/// Список дочерних элементов.
/// </summary>
public List<RuleTocItem> Children { get; } = [];
/// <summary>
/// Находит элемент по хлебным крошкам.
/// </summary>
/// <param name="breadcrumbs">Массив хлебных крошек, указывающих на путь в дереве.</param>
/// <returns><see cref="RuleTocItem"/> или <c>null</c> если элемент не найден.</returns>
public RuleTocItem Get(string[] breadcrumbs)
{
RuleTocItem? node = null;
while (true)
{
List<RuleTocItem> children = node?.Children ?? Children;
if (breadcrumbs.Length == 0)
{
return node!;
}
string root = breadcrumbs[0];
RuleTocItem? item = children.FirstOrDefault(i => i.Name == root);
if (item is null)
{
item = new(root, node);
children.Add(item);
}
breadcrumbs = breadcrumbs[1..];
node = item;
}
}
/// <summary>
/// Проверяет, существует ли имя в текущей книге или дочерних элементах.
/// </summary>
/// <param name="name">Имя для проверки.</param>
/// <param name="node">Начальный элемент для поиска.</param>
/// <returns>true если имя.</returns>
public bool IsNameExists(string name, RuleTocItem? node = null)
{
foreach (RuleTocItem item in node?.Children ?? Children)
{
if (item.Name == name || IsNameExists(name, item))
{
return true;
}
}
return false;
}
/// <summary>
/// Находит элемент по идентификатору сущности.
/// </summary>
/// <param name="id">Идентификатор сущности.</param>
/// <param name="node">Начальный узел для поиска.</param>
/// <returns><see cref="RuleTocItem"/> или <c>null</c> если элемент не найден.</returns>
public RuleTocItem? GetByEntityId(int id, RuleTocItem? node = null)
{
if (node?.RuleId == id)
{
return node;
}
foreach (RuleTocItem item in node?.Children ?? Children)
{
RuleTocItem? result = GetByEntityId(id, item);
if (result is not null)
{
return result;
}
}
return null;
}
/// <summary>
/// Возвращает строковое представление книги в файле YAML.
/// </summary>
/// <returns>Строковое представление книги.</returns>
public override string ToString()
{
return $"\"{SourceName}\":\n"
+ string.Join(
"\n",
Children.Select(child => RuleTocItem.Indent(child.ToString())).ToList()
);
}
}
/// <summary>
/// Класс представляет собой элемент дерева правил.
/// </summary>
internal class RuleTocItem(string name, RuleTocItem? parent)
{
public string? Id { get; set; } = null;
/// <summary>
/// Имя элемента.
/// </summary>
public string Name { get; } = name;
/// <summary>
/// Идентификатор правила.
/// </summary>
public int? RuleId { get; set; } = null;
/// <summary>
/// Указывает, что элемент обрабатывается.
/// </summary>
public bool IsHandled { get; set; } = false;
/// <summary>
/// Родительский элемент дерева.
/// </summary>
public RuleTocItem? Parent { get; } = parent;
/// <summary>
/// Порядок дочерних элементов.
/// </summary>
public List<string>? ChildrenOrder { get; set; } = null;
/// <summary>
/// Коллекция дочерних элементов.
/// </summary>
public List<RuleTocItem> Children { get; } = [];
/// <summary>
/// Предыдущий идентификатор.
/// </summary>
public string? PreviousId { get; set; }
/// <summary>
/// Следующий идентификатор.
/// </summary>
public string? NextId { get; set; }
/// <summary>
/// Идентификатор первого дочернего элемента.
/// </summary>
public string? FirstChildId { get; set; }
/// <summary>
/// Идентификатор последнего дочернего элемента.
/// </summary>
public string? LastChildId { get; set; }
/// <summary>
/// Возвращает строковое представление элемента содержания в файле YAML.
/// </summary>
/// <returns>Строковое представление элемента содержания.</returns>
public override string ToString()
{
List<string> rows =
[
$"{Name}:",
$"{Tab}aonprd: {Id ?? "null"}",
$"{Tab}entity: {RuleId?.ToString() ?? "null"}",
];
if (Children.Count == 0)
{
// rows.Add($"{TAB}children: None");
return string.Join("\n", rows);
}
rows.Add($"{Tab}children:");
foreach (RuleTocItem child in Children)
{
rows.Add(child.Indent(2));
}
return string.Join("\n", rows);
}
/// <summary>
/// Увеличение отступа строкового представления элемента содержания в файле YAML.
/// </summary>
/// <param name="amount">Количество отступов.</param>
/// <returns>Строковое представление элемента содержания с отступом.</returns>
/// <seealso cref="Tab"/>
public string Indent(int amount = 1)
{
string result = ToString();
for (int i = 0; i < amount; i++)
{
result = Indent(result);
}
return result;
}
/// <summary>
/// Увеличение отступа строки.
/// </summary>
/// <param name="str">Входная строка.</param>
/// <returns>Строка с отступом.</returns>
/// <seealso cref="Tab"/>
public static string Indent(string str)
{
return Tab + str.Replace("\n", $"\n{Tab}");
}
/// <summary>
/// Строка отступа строки.
/// </summary>
/// <seealso cref="Indent(int)"/>
/// <seealso cref="Indent(string)"/>
public const string Tab = " ";
}