diff --git a/Pf2eDataScrapper/EnvSettings.cs b/Pf2eDataScrapper/EnvSettings.cs
index dd1b457..f5b02c1 100644
--- a/Pf2eDataScrapper/EnvSettings.cs
+++ b/Pf2eDataScrapper/EnvSettings.cs
@@ -6,7 +6,7 @@ namespace Pf2eDataScrapper;
///
/// Класс настроек.
///
-internal static class EnvSettings
+public static class EnvSettings
{
///
/// Загрузка файла настроек `.env`.
@@ -36,5 +36,8 @@ internal static class EnvSettings
///
public static string OutputDir => new(OutputDirPath);
+ ///
+ /// Строка подключения к базе данных.
+ ///
public static string DatabaseConnection => EnvReader.GetStringValue("DATABASE_CONNECTION");
}
diff --git a/Pf2eDataScrapper/Importers/AbstractImporter.cs b/Pf2eDataScrapper/Importers/AbstractImporter.cs
index e80020e..fcddf09 100644
--- a/Pf2eDataScrapper/Importers/AbstractImporter.cs
+++ b/Pf2eDataScrapper/Importers/AbstractImporter.cs
@@ -17,6 +17,9 @@ internal abstract class AbstractImporter
///
public abstract string Slug { get; }
+ ///
+ /// Репозиторий для данных, загруженных из необходимых источников.
+ ///
public abstract AbstractImporterRepository Repository { get; }
///
diff --git a/Pf2eDataScrapper/Importers/DatabaseHelper.cs b/Pf2eDataScrapper/Importers/DatabaseHelper.cs
index 718aed3..420a102 100644
--- a/Pf2eDataScrapper/Importers/DatabaseHelper.cs
+++ b/Pf2eDataScrapper/Importers/DatabaseHelper.cs
@@ -1,33 +1,60 @@
-using Microsoft.EntityFrameworkCore;
-using Pf2eModel;
+using Pf2eModel;
using Slugify;
namespace Pf2eDataScrapper.Importers;
+///
+/// Класс предоставляет методы для работы с базой данных.
+///
public class DatabaseHelper
{
- public Pf2eDbContext Context = new();
-
- public readonly SlugHelper Slugger = new();
-
+ ///
+ /// Последний найденный идентификатор сущности.
+ /// Используется для генерации новых ID сущностей.
+ ///
private int _id;
+ ///
+ /// Генерирует новый уникальный идентификатор сущности. и возвращает его.
+ ///
public int NextEntityId => ++_id;
+ ///
+ /// Сервис для работы с URL-Slug. Используется для преобразования названий в URL-friendly формат.
+ ///
+ public readonly SlugHelper Slugger = new();
+
+ ///
+ /// Context для доступа к базе данных.
+ ///
+ public readonly Pf2eDbContext Context = new();
+
private DatabaseHelper()
{
_id = Context.Entities.Any() ? Context.Entities.Max(e => e.Id) : 0;
}
+ ///
+ /// Генерирует slug из названия.
+ ///
public string GenerateSlug(string name)
{
return Slugger.GenerateSlug(name);
}
+ ///
+ /// Возвращает singleton-инстанцию класса .
+ ///
public static readonly DatabaseHelper Instance = new();
+ ///
+ /// Контекст для доступа к базе данных.
+ ///
public static Pf2eDbContext DbContext => Instance.Context;
+ ///
+ /// Обновляет контекст и сохраняет изменения в базе данных.
+ ///
public static void ResetContext()
{
Instance.Context.SaveChanges();
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdImporter.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdImporter.cs
index 7559823..b6443dc 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdImporter.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdImporter.cs
@@ -4,28 +4,42 @@ using Pf2eDataScrapper.Importers.Repositories;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
+///
+/// Класс обработки данных с сайта Архивов Нефеса.
+///
internal class AonprdImporter : AbstractImporter
{
- public override string Name => SourceName;
+ ///
+ public override string Name => TargetName;
+ ///
public override string Slug => "aonprd";
+ ///
public override AbstractImporterRepository Repository =>
new AonprdRepository(this, "https://elasticsearch.aonprd.com");
+ ///
+ /// Инструмент для работы с данными сайта Архивов Нефеса.
+ ///
public AonprdLoader Loader { get; }
+ ///
+ /// Конструктор класса .
+ ///
public AonprdImporter()
{
- Loader = new AonprdLoader(this);
+ Loader = new(this);
}
+ ///
public override void Prepare()
{
Repository.Update();
Loader.Prepare();
}
+ ///
public override void BuildSchemas()
{
AonprdSchemaBuilder builder = new(Loader);
@@ -34,6 +48,7 @@ internal class AonprdImporter : AbstractImporter
builder.Save(EnvSettings.OutputDir);
}
+ ///
public override void Import()
{
AonprdDataBuilder builder = new(Loader);
@@ -43,5 +58,8 @@ internal class AonprdImporter : AbstractImporter
builder.Build();
}
- public const string SourceName = "Archives of Nethys Pathfinder 2e";
+ ///
+ /// Название внешней ссылки.
+ ///
+ public const string TargetName = "Archives of Nethys Pathfinder 2e";
}
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdLoader.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdLoader.cs
index 6813181..d97b8ec 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdLoader.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdLoader.cs
@@ -3,23 +3,37 @@ using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
+///
+/// Класс загрузки данных с сайта Архивов Нефеса.
+///
internal class AonprdLoader(AonprdImporter importer)
{
- public AonprdImporter Importer = importer;
+ ///
+ /// Референс на импортер, используемый для загрузки данных.
+ ///
+ public AonprdImporter Importer { get; } = importer;
- public AonprdCompendium Compendium = new();
+ ///
+ /// Компендиум данных с сайта Архивов Нефеса.
+ ///
+ public AonprdCompendium Compendium { get; } = new();
+ ///
+ /// Число элементов в компендарии.
+ ///
public int ItemCount => Compendium.Count();
+ ///
+ /// Подготовка данных перед загрузкой.
+ ///
public void Prepare()
{
using StreamReader indexFile = new(Path.Combine(Importer.Dir, "index.json"));
JObject indexJson = JObject.Parse(indexFile.ReadToEnd());
- foreach (KeyValuePair kvp in indexJson)
+ foreach ((string file, JToken? value) in indexJson)
{
- string file = kvp.Key;
- JArray items = (JArray)kvp.Value!;
+ JArray items = (JArray)value!;
foreach (JToken item in items)
{
@@ -28,16 +42,30 @@ internal class AonprdLoader(AonprdImporter importer)
}
}
+ ///
+ /// Возвращает коллекцию всех доступных загружаемых элементов.
+ ///
+ /// Коллекция всех загружаемых элементов.
public IEnumerable Entries()
{
return Entries([.. Compendium.Types.Keys]);
}
+ ///
+ /// Возвращает коллекцию доступных загружаемых элементов.
+ ///
+ /// Тип, которые нужно включить в результат.
+ /// Коллекция загружаемых элементов, соответствующих предоставленному типу.
public IEnumerable Entries(string types)
{
return Entries([types]);
}
+ ///
+ /// Возвращает коллекцию доступных загружаемых элементов.
+ ///
+ /// Типы, которые нужно включить в результат.
+ /// Коллекция загружаемых элементов, соответствующих предоставленным типам.
public IEnumerable Entries(string[] types)
{
foreach (string file in Compendium.Files(types))
@@ -64,8 +92,14 @@ internal class AonprdLoader(AonprdImporter importer)
}
}
+ ///
+ /// Класс, представляющий загружаемый элемент.
+ ///
public class LoaderEntry(string id, string file, JObject itemJson) : AonprdReference(id, file)
{
+ ///
+ /// Возвращает JSON-объект, содерждающий данные о элементе.
+ ///
public JObject Json { get; } = itemJson;
}
}
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdRepository.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdRepository.cs
index 4d21dd2..ba05d9b 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdRepository.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdRepository.cs
@@ -4,13 +4,25 @@ using Pf2eDataScrapper.Importers.Repositories;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
+///
+/// Основной класс для работы с репозиторием данных Aonprd.
+///
internal class AonprdRepository(AbstractImporter importer, string searchUrl)
: AbstractImporterRepository(importer)
{
+ ///
+ /// URL для доступа к API Aonprd.
+ ///
public readonly string SearchUrl = searchUrl;
+ ///
+ /// Текущая ревизия данных. Значение обновляется при обновлении репозитория.
+ ///
public int Revision { get; private set; }
+ ///
+ /// Метод для загрузки данных из API Aonprd.
+ ///
private string Load(string url)
{
if (!url.StartsWith("http://") && !url.StartsWith("https://"))
@@ -25,6 +37,7 @@ internal class AonprdRepository(AbstractImporter importer, string searchUrl)
return reader.ReadToEnd();
}
+ ///
public override void Update()
{
if (CheckRevision())
@@ -69,9 +82,9 @@ internal class AonprdRepository(AbstractImporter importer, string searchUrl)
}
///
- /// Проверка актуальности данных
+ /// Проверка актуальности данных.
///
- /// true - актуальная ревизия, false - устаревшая/отсутсвует
+ /// true - актуальная ревизия, false - устаревшая/отсутсвует.
private bool CheckRevision()
{
JObject page = JObject.Parse(Load("/aon/_doc/feat-1"));
@@ -92,6 +105,11 @@ internal class AonprdRepository(AbstractImporter importer, string searchUrl)
return lastRevision == Revision.ToString();
}
+ ///
+ /// Запись данных в файл.
+ ///
+ /// Путь к файлу.
+ /// Содержимое, которе требуется записать в файл.
private void WriteFile(string path, string content)
{
string filePath = Path.Combine(RepositoryDirPath, path);
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdCompendium.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdCompendium.cs
index 86a4624..e7df834 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdCompendium.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdCompendium.cs
@@ -1,9 +1,20 @@
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
+///
+/// Класс хранения данных компендиума.
+///
internal class AonprdCompendium
{
+ ///
+ /// Словарь данных компендиума.
+ ///
public readonly Dictionary Types = [];
+ ///
+ /// Добавить ссылку на сущность с указанием файла, в котором она хранится.
+ ///
+ /// Идентификатор сущности.
+ /// Имя файла.
public void AddReference(string id, string file)
{
AonprdReference reference = new(id, file);
@@ -14,15 +25,29 @@ internal class AonprdCompendium
}
else
{
- Types.Add(reference.Type, new AonprdType(reference));
+ Types.Add(reference.Type, new(reference));
}
}
+ ///
+ /// Возвращает количество элементов в компендиуме.
+ ///
+ /// Количество элементов.
public int Count() => Types.Values.Sum(t => t.Count);
+ ///
+ /// Возвращает количество элементов для указанных типов данных.
+ ///
+ /// Список типов.
+ /// Количество элементов.
public int Count(IEnumerable types) =>
Types.Values.Where(t => types.Contains(t.Type)).Sum(t => t.Count);
+ ///
+ /// Возвращает список файлов для выбора сущностей указанных типов данных.
+ ///
+ /// Список типов.
+ /// Список искомых файлов.
public IEnumerable Files(IEnumerable types) =>
Types.Values.Where(t => types.Contains(t.Type)).SelectMany(t => t.Files).Distinct();
}
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdReference.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdReference.cs
index a53290f..98ebbdd 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdReference.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdReference.cs
@@ -1,16 +1,37 @@
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
+///
+/// Ссылка на сущность с указанием файла, в котором она хранится.
+///
+/// Идентификатор сущности.
+/// Имя файла.
internal class AonprdReference(string id, string file)
{
+ ///
+ /// Идентификатор сущности.
+ ///
public readonly string Id = id;
+ ///
+ /// Тип сущности.
+ ///
public readonly string Type = ResolveType(id);
+ ///
+ /// Имя файла, в котором хранится сущность.
+ ///
public readonly string File = file;
- public static string ResolveType(string id)
+ ///
+ /// Определение типа сущности как префикса идентификатора.
+ ///
+ private static string ResolveType(string id)
{
- static string? subType(string type, string cat)
+ string type = string.Join('-', id.Split('-')[..^1]);
+
+ return SubType(type, "equipment") ?? SubType(type, "weapon") ?? type;
+
+ static string? SubType(string type, string cat)
{
return type.StartsWith($"{cat}-") && type != cat
? type.EndsWith("-bonus")
@@ -18,9 +39,5 @@ internal class AonprdReference(string id, string file)
: $"{cat}-sub"
: null;
}
-
- string type = string.Join('-', id.Split('-')[0..^1]);
-
- return subType(type, "equipment") ?? subType(type, "weapon") ?? type;
}
}
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdType.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdType.cs
index 527d250..8f43ff7 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdType.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdType.cs
@@ -1,9 +1,19 @@
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
+///
+/// Класс AonprdType представляет собой уникальный тип данных, связанный с Aon (Advanced Opportunity Network).
+/// Это основной класс, который хранит информацию о различных элементах системы.
+///
internal class AonprdType(string type)
{
+ ///
+ /// Идентификатор типа данных.
+ ///
public readonly string Type = type;
+ ///
+ /// Список ссылок на сущности, связанных с этим типом.
+ ///
public readonly List Items = [];
public AonprdType(AonprdReference reference)
@@ -12,12 +22,21 @@ internal class AonprdType(string type)
Items.Add(reference);
}
+ ///
+ /// Добавляет новую ссылку в список.
+ ///
public void Add(AonprdReference reference)
{
Items.Add(reference);
}
- public List Files => [.. Items.Select(x => x.File).Distinct()];
+ ///
+ /// Возвращает уникальные файлы, использованные в ссылках.
+ ///
+ public List Files => Items.Select(x => x.File).Distinct().ToList();
+ ///
+ /// Число элементов в списке ссылок.
+ ///
public int Count => Items.Count;
}
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdDataBuilder.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdDataBuilder.cs
index 1fc0532..1f94777 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdDataBuilder.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdDataBuilder.cs
@@ -5,12 +5,19 @@ using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
+///
+/// Класс для создание схемы данных Архива Нефиса.
+///
+///
internal class AonprdDataBuilder(AonprdLoader loader)
{
+ ///
+ /// Класс работы с базой данных.
+ ///
public readonly Pf2eDatabase Database = Pf2eDatabase.Instance;
///
- /// Загрузчик данных.
+ /// Основной класс для работы с данными Архива Нефиса.
///
public readonly AonprdLoader Loader = loader;
@@ -19,8 +26,14 @@ internal class AonprdDataBuilder(AonprdLoader loader)
///
public AonprdCompendium Compendium => Loader.Compendium;
+ ///
+ /// Коллекция обработчиков данных.
+ ///
public readonly AonprdProcessorCollection Processors = new();
+ ///
+ /// Очистить таблицы в базе данных.
+ ///
public void TruncateTables()
{
Console.WriteLine("Truncating all old data...");
@@ -30,14 +43,29 @@ internal class AonprdDataBuilder(AonprdLoader loader)
Console.WriteLine("Truncation completed!");
}
+ ///
+ /// Конфигурация интерфейса вывода результатов.
+ ///
protected ConcurrentWriter Window = null!;
+ ///
+ /// Основное окно для вывода информации.
+ ///
protected Window Output = null!;
+ ///
+ /// Полоса прогресса для основного процесса обработки данных.
+ ///
protected ProgressBar ProcessProgressBar = null!;
+ ///
+ /// Полоса прогресса для под-процессов обработки данных.
+ ///
protected ProgressBar SubProcessProgressBar = null!;
+ ///
+ /// Метод для настройки интерфейса.
+ ///
protected void ConfigureWindow()
{
Window = new Window(0, 0, Console.WindowWidth, Console.WindowHeight).Concurrent();
@@ -56,6 +84,9 @@ internal class AonprdDataBuilder(AonprdLoader loader)
SubProcessProgressBar = new(bars, 1, 15);
}
+ ///
+ /// Обработка отдельного процессора данных.
+ ///
protected void RunProcessor(AonprdProcessorCollection.ProcessorItem item, JObject json)
{
AonprdProcessorInput input = new(json);
@@ -76,6 +107,9 @@ internal class AonprdDataBuilder(AonprdLoader loader)
}
}
+ ///
+ /// Полная обработка и сохранение данных.
+ ///
public void Build()
{
ConfigureWindow();
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorAttribute.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorAttribute.cs
index 05dcbc2..faac790 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorAttribute.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorAttribute.cs
@@ -1,5 +1,12 @@
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
+///
+/// Атрибут обработчика данных Архивов Нефиса.
+///
+/// Название обработчика.
+/// Тип данных, которые обработчик обрабатывает.
+/// Названия обработчиков, которые должны быть выполнены до запуска этого обработчика.
+/// Флаг, указывающий, следует ли добавить важные общие зависимости для обработчка.
[AttributeUsage(AttributeTargets.Class)]
public class AonprdProcessorAttribute(
string name,
@@ -8,23 +15,51 @@ public class AonprdProcessorAttribute(
bool includeDefaults = true
) : Attribute
{
+ ///
+ /// Важные общие зависимости для обработчка.
+ ///
private static readonly string[] DefaultDependencies = ["trait", "source"];
+
+ ///
+ /// Название обработчика.
+ ///
public readonly string Name = name;
+ ///
+ /// Тип данных, которые обработчик обрабатывает.
+ ///
public readonly string? Type = type;
+ ///
+ /// Названия обработчиков, которые должны быть выполнены до запуска этого обработчика.
+ ///
public readonly IEnumerable Dependencies =
[
.. includeDefaults ? DefaultDependencies : [],
.. dependencies,
];
+ ///
+ /// Конструктор класса со стандартными общими зависимости для обработчка.
+ ///
+ /// Тип данных, которые обработчик обрабатывает. Также будет использоваться в качестве названия.
public AonprdProcessorAttribute(string type)
: this(type, type, DefaultDependencies) { }
+ ///
+ /// Конструктор класса .
+ ///
+ /// Тип данных, которые обработчик обрабатывает. Также будет использоваться в качестве названия.
+ /// Названия обработчиков, которые должны быть выполнены до запуска этого обработчика.
+ /// Флаг, указывающий, следует ли добавить важные общие зависимости для обработчка.
public AonprdProcessorAttribute(string type, string[] dependencies, bool includeDefaults = true)
: this(type, type, dependencies, includeDefaults) { }
+ ///
+ /// Конструктор класса со стандартными общими зависимости для обработчка.
+ ///
+ /// Название обработчика.
+ /// Тип данных, которые обработчик обрабатывает.
public AonprdProcessorAttribute(string name, string type)
: this(name, type, DefaultDependencies) { }
}
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorCollection.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorCollection.cs
index 7f3d24a..9d66d8a 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorCollection.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorCollection.cs
@@ -3,21 +3,47 @@ using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
+///
+/// Класс отвечает за управление обработчиками, отмеченных атрибутом .
+///
internal class AonprdProcessorCollection
{
+ ///
+ /// Элемент коллекции обработчика.
+ ///
+ /// Атрибут, связанный с обаботчиком.
+ /// Конструктор обработчика.
public class ProcessorItem(AonprdProcessorAttribute attribute, ConstructorInfo constructor)
{
+ ///
+ /// Атрибут, связанный с обаботчиком.
+ ///
public readonly AonprdProcessorAttribute Attribute = attribute;
+ ///
+ /// Конструктор обработчика.
+ ///
public readonly ConstructorInfo Constructor = constructor;
+ ///
+ /// Приоритет выполнения обработчика.
+ ///
public int Priority = -1;
}
+ ///
+ /// Список всех объявленных обработчиков.
+ ///
private readonly List _allItems;
+ ///
+ /// Список используемых обработчиков.
+ ///
public List Items { get; private set; } = [];
+ ///
+ /// Конструктор класса , загружающий все обработчики.
+ ///
public AonprdProcessorCollection()
{
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
@@ -29,7 +55,7 @@ internal class AonprdProcessorCollection
if (!type.IsSubclassOf(typeof(AbstractProcessor)))
{
- throw new Exception(
+ throw new(
$"'AonprdProcessor' attribute should only be applied to children of 'AbstractProcessor' class. '{type.FullName}' is not."
);
}
@@ -56,6 +82,9 @@ internal class AonprdProcessorCollection
_allItems = Items.ToList();
}
+ ///
+ /// Проверка, что все зависимости всех обработчиков могут быть удовлетворены.
+ ///
private void CheckDependencies()
{
foreach (ProcessorItem item in Items)
@@ -72,6 +101,9 @@ internal class AonprdProcessorCollection
}
}
+ ///
+ /// Сортировать обработчики в соответсвии со всеми зависимостями.
+ ///
private void SortItems()
{
CheckDependencies();
@@ -104,6 +136,10 @@ internal class AonprdProcessorCollection
Items.Sort((a, b) => a.Priority - b.Priority);
}
+ ///
+ /// Итерация через все используемые обработчики.
+ ///
+ /// Итератор.
public IEnumerable Iterate()
{
SortItems();
@@ -114,9 +150,14 @@ internal class AonprdProcessorCollection
}
}
- public void UseOnlyNames(string[] processorNames)
+ ///
+ /// Ограничить список используемых обработчиков по названию.
+ /// Автоматически включает все обработчики, от которых зависят указанные в аргументе обработчики.
+ ///
+ /// Коллекция названиий требуемых обработчиков.
+ public void UseOnlyNames(ICollection processorNames)
{
- if (processorNames.Length == 0)
+ if (processorNames.Count == 0)
{
Items = _allItems;
return;
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorInput.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorInput.cs
index 6f9aa5f..d369fec 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorInput.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorInput.cs
@@ -3,8 +3,13 @@ using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
+///
+/// Класс для работы с JSON-объектом при обработки данных с Архивов Нефиса.
+///
+/// JSON-объект, который будет использоваться для доступа к данным.
internal class AonprdProcessorInput(JObject input) : ProcessorInput(input)
{
+ ///
public override T Enum(string value)
{
try
@@ -17,6 +22,11 @@ internal class AonprdProcessorInput(JObject input) : ProcessorInput(input)
}
}
+ ///
+ /// Обработать строку, содержащую информацию о количестве действий.
+ ///
+ /// Входная строка с данными.
+ /// Структура, хранящая информацию о количетсве действий.
public ActionStruct ResolveActionString(string input)
{
ActionStruct result = new();
@@ -89,13 +99,39 @@ internal class AonprdProcessorInput(JObject input) : ProcessorInput(input)
return result;
}
+ ///
+ /// Класс структуры, хранящей информацию о количетсве действий.
+ ///
public class ActionStruct
{
- public int Actions;
- public int MaxActions;
- public bool IsPassive;
- public bool IsReaction;
- public bool IsFreeAction;
- public bool TwoRounds;
+ ///
+ /// Количество действий
+ ///
+ public int Actions { get; set; }
+
+ ///
+ /// Максимальное количество действий
+ ///
+ public int MaxActions { get; set; }
+
+ ///
+ /// Флаг, указывающий, что действия не требуются.
+ ///
+ public bool IsPassive { get; set; }
+
+ ///
+ /// Флаг, указывающий, что действие может быть использовано как реакция.
+ ///
+ public bool IsReaction { get; set; }
+
+ ///
+ /// Флаг, указывающий, что можно использовать свободное действие.
+ ///
+ public bool IsFreeAction { get; set; }
+
+ ///
+ /// Флаг, указывающий, что действие может быть продлено до 2 раундов.
+ ///
+ public bool TwoRounds { get; set; }
}
}
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdBuilderGlobals.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdBuilderGlobals.cs
index 048c6be..def6837 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdBuilderGlobals.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdBuilderGlobals.cs
@@ -2,11 +2,24 @@
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
+///
+/// Класс-помощник, хранящий необходимые глобальные данные.
+/// Реализует шаблон Singleton.
+///
internal class AonprdBuilderGlobals
{
+ ///
+ /// Цель внешних ссылок Архивов Нефисов.
+ ///
public ExternalTarget AonprdTarget = null!;
+ ///
+ /// Конструктор класса .
+ ///
private AonprdBuilderGlobals() { }
+ ///
+ /// Экземпляр класса .
+ ///
public static readonly AonprdBuilderGlobals Instance = new();
}
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdEnumResolver.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdEnumResolver.cs
index 809ead1..e4f395c 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdEnumResolver.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdEnumResolver.cs
@@ -2,8 +2,14 @@
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
+///
+/// Класс, помогающий разрешить строковые значения с Архивов Нефиса в перечисления.
+///
public static class AonprdEnumResolver
{
+ ///
+ /// Коллекция классов, разрешающих строковые значения в перечисления.
+ ///
private static readonly ICollection Solvers =
[
new Solver(
@@ -62,6 +68,18 @@ public static class AonprdEnumResolver
),
];
+ ///
+ /// Разрешить строковое значение с Архивов Нефиса в перечисление.
+ ///
+ /// Тип искомого перечисления.
+ /// Обрабатываемое строковоее значение.
+ /// Значение искомого перечисления.
+ ///
+ /// Исключение, если для указанного типа перечисления не указан класс, разрешающий строковые значения.
+ ///
+ ///
+ /// Исключение, если указанное значение не получилось преобразовать искомое значение.
+ ///
public static T Resolve(string value)
where T : Enum
{
@@ -81,11 +99,17 @@ public static class AonprdEnumResolver
: throw new EnumResolverValueUnknownException(type, value);
}
+ ///
+ /// Класс, разрешающий строковые значения в перечисления.
+ ///
private abstract class Solver
{
public abstract Type Type { get; }
}
+ ///
+ /// Абстрактный общий класс, разрешающий строковые значения в перечисления.
+ ///
private class Solver(Dictionary data) : Solver
where T : Enum
{
@@ -93,9 +117,18 @@ public static class AonprdEnumResolver
public Dictionary Data { get; } = data;
}
+ ///
+ /// Исключение, указывающее, что для указанного типа перечисления не указан класс, разрешающий строковые значения.
+ ///
+ /// Тип искомого перечисления.
public class EnumResolverEnumUnknownException(Type t)
: Exception($"Can't resolve type '{t.FullName}': Solver not defined");
+ ///
+ /// Исключение, указывающее, что указанное значение не получилось преобразовать искомое значение.
+ ///
+ /// Тип искомого перечисления.
+ /// Искомое значение.
public class EnumResolverValueUnknownException(Type t, string value)
: Exception($"Can't resolve type '{t.FullName}': Value '{value}' is not matched");
}
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/StringHelper.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/StringHelper.cs
index 384ea5f..7682c74 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/StringHelper.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/StringHelper.cs
@@ -2,10 +2,22 @@
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
+///
+/// Класс-помощник, для обработки строкового ввода с Архивов Нефиса.
+/// Реализует шаблон Singleton.
+///
internal partial class StringHelper
{
+ ///
+ /// Конструктор класса
+ ///
private StringHelper() { }
+ ///
+ /// Разбиение строки по нестабильным строковым разделителям (например, ", ", " or " и т.д.).
+ ///
+ /// Исходная строка.
+ /// Коллекция строк.
public List RowSplit(string value)
{
return value
@@ -17,6 +29,11 @@ internal partial class StringHelper
.ToList();
}
+ ///
+ /// Разбор списка ссылок в исходной строке.
+ ///
+ /// Исходная строка.
+ /// Структура, содеражащая информацию разбиении строки по ссылкам.
public MarkdownLinkSplit ParseMarkdownLinks(string input)
{
MarkdownLinkSplit result = new();
@@ -39,31 +56,70 @@ internal partial class StringHelper
return result;
}
+ ///
+ /// Извлечение информации о названии источника.
+ ///
+ /// Исходная строка.
+ /// Название источника.
public string ResolveSource(string input)
{
Match match = SourceSuffixRegex().Match(input);
return match.Captures.Count > 0 ? match.Captures[0].Value : "";
}
+ ///
+ /// Экземпляр класса .
+ ///
public static StringHelper Instance { get; } = new();
+ ///
+ /// Регулярное выражение для извлечения источника из строки с Markdown-ссылкой.
+ ///
+ /// Регулярное выражение.
[GeneratedRegex(@"^\[.*?\]\(.*?\)\s+(.*)$")]
public static partial Regex SourceSuffixRegex();
+ ///
+ /// Регулярное выражение для выявления Markdown-ссылок в строке.
+ ///
+ /// Регулярное выражение.
[GeneratedRegex(@"(.*?)\[(.*?)\]\((.*?)\)")]
public static partial Regex LinkRegex();
}
+///
+/// Класс структуры, содеражащая информацию разбиении строки по ссылкам.
+///
internal class MarkdownLinkSplit
{
- public List Links = [];
+ ///
+ /// Список содержащихся ссылок.
+ ///
+ public List Links { get; } = [];
- public string Suffix = "";
+ ///
+ /// Завершающая часть ссылки.
+ ///
+ public string Suffix { get; set; } = "";
}
+///
+/// Информация о ссылке в строке.
+///
internal class MarkdownLink
{
- public string Prefix { get; set; } = "";
- public string Text { get; set; } = "";
- public string Url { get; set; } = "";
+ ///
+ /// Данные, содержащиеся до ссылки.
+ ///
+ public string Prefix { get; init; } = "";
+
+ ///
+ /// Текст ссылки.
+ ///
+ public string Text { get; init; } = "";
+
+ ///
+ /// URL ссылки.
+ ///
+ public string Url { get; init; } = "";
}
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/LegacyEntityHandler.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/LegacyEntityHandler.cs
index e6f00d7..d5cfc57 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/LegacyEntityHandler.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/LegacyEntityHandler.cs
@@ -1,29 +1,55 @@
-using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
-using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
+using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
using Pf2eModel.Model.Base;
using Pf2eModel.Model.Base.Source;
using Pf2eModel.Model.Common.I18n;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
+///
+/// Обработчик сущностей, помеченных как устаревшие.
+///
internal class LegacyEntityHandler
{
+ ///
+ /// Идентификатор устаревшей сущности.
+ ///
public string LegacyId { get; private set; }
+ ///
+ /// Название устаревшей сущности.
+ ///
public string LegacyName { get; private set; } = "";
+ ///
+ /// Коллекция источников устревшей сущности.
+ ///
public List LegacySources { get; private set; } = [];
+ ///
+ /// Флаг, указывающий, что сведения об устаревшей сущности готовы к добавлению в обновлённые.
+ ///
public bool LegacyPrepared { get; private set; } = false;
- public List RemasterEntities = [];
+ ///
+ /// Список обновлённых сущностей, что отметели устаревшую сущность как предшественника.
+ ///
+ public List RemasterEntities { get; } = [];
+ ///
+ /// Конструктор класса , если сущность сама отмечена как устаревшая.
+ ///
+ /// Обработчик устаревшей сущности.
public LegacyEntityHandler(AbstractEntityProcessor processor)
{
LegacyId = processor.Input.GetRequired("id");
Prepare(processor);
}
+ ///
+ /// Конструктор класса , если обновлённая сущность указывает на ещё недобавленную устаревшую сущность.
+ ///
+ /// Идентификатор устаревшей сущности.
+ /// Обновлённая сущность.
public LegacyEntityHandler(string legacyId, Entity remasterEntity)
{
LegacyId = legacyId;
@@ -31,6 +57,10 @@ internal class LegacyEntityHandler
RemasterEntities.Add(remasterEntity);
}
+ ///
+ /// Подготовить данные об устравшей сущности.
+ ///
+ /// Обработчик устаревшей сущности.
public void Prepare(AbstractEntityProcessor processor)
{
if (LegacyPrepared)
@@ -48,6 +78,10 @@ internal class LegacyEntityHandler
}
}
+ ///
+ /// Применить данные устаревшей сущности к обновлённой.
+ ///
+ /// Обновлённая сущность.
public void Apply(Entity remasterEntity)
{
if (!remasterEntity.Name.Contains(LegacyName))
diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractEntityProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractEntityProcessor.cs
index 828cd3a..7876221 100644
--- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractEntityProcessor.cs
+++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractEntityProcessor.cs
@@ -14,17 +14,37 @@ using Pf2eModel.Model.Structure;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
+///
+/// Абстрактный класс-обработчик сущностей, полученных из Архивов Нефиса.
+/// Класс предназначен для обработки данных с помощью различных обработчиков,
+/// для которых указан атрибут .
+///
+/// Объект обработки вводимого JSON.
+///
internal abstract class AbstractEntityProcessor(AonprdProcessorInput input)
: AbstractProcessor(input)
{
+ ///
+ /// Корневая сущность.
+ ///
public Entity Entity { get; } = new();
+ ///
+ /// Тип сущности.
+ ///
public abstract EntityType Type { get; }
+ ///
+ /// Основная сущность.
+ ///
public abstract IEntity Object { get; }
+ ///
+ /// Добавление основной сущности в контекст базы данных.
+ ///
public abstract void Add();
+ ///
public override void Process()
{
if (Input.GetOptional("remaster_id") is not null)
@@ -42,27 +62,54 @@ internal abstract class AbstractEntityProcessor(AonprdProcessorInput input)
ProcessLegacy();
}
+ ///
public override void Save()
{
Add();
Context.SaveChanges();
}
- // Description generation
+ #region "Генерация описания"
- protected virtual string[] AddedDescriptionPaths() => [];
+ ///
+ /// Получение списка полей, которые должны быть добавлены в описание.
+ ///
+ ///
+ // [Obsolete("Данный метод будет отключён на финальных этапах разработки.")]
+ protected virtual ICollection AddedDescriptionPaths() => [];
+ ///
+ /// Создание строкового представления объекта по указанному пути для добавления к описанию сущности.
+ ///
+ /// Путь к добавляемому объекту.
+ /// Строковое представление для добавления к описанию сущности.
+ // [Obsolete("Данный метод будет отключён на финальных этапах разработки.")]
protected string AddedDescription(string path) =>
- $"\r\n\r\n========== [{path}] ==========\r\n\r\n{Input.GetOptional(path) ?? ""}";
+ $"\r\n\r\n========== [{path}] ==========\r\n\r\n{Input.GetOptional