Продолжение работы над фундаментальным обновлением проекта (всё ещё без сборки)
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
namespace Pf2eDataScrapper.App;
|
||||
|
||||
/// <summary>
|
||||
/// Общий аттрибут обработчика.
|
||||
/// </summary>
|
||||
/// <param name="name">Название обработчика.</param>
|
||||
/// <param name="dependencies">Названия обработчиков, которые должны быть выполнены до запуска этого обработчика.</param>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class ProcessAttribute(string name, ICollection<string> dependencies) : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Название обработчика.
|
||||
/// </summary>
|
||||
public string Name { get; init; } = name;
|
||||
|
||||
/// <summary>
|
||||
/// Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика.
|
||||
/// </summary>
|
||||
public ICollection<string> Dependencies { get; init; } = dependencies;
|
||||
|
||||
public ProcessAttribute(string name)
|
||||
: this(name, []) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Аттрибут обработчика для уточнения группы.
|
||||
/// </summary>
|
||||
/// <param group="group">Группа обработчиков, к которому относится обработчик.</param>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
internal class ProcessorGroupAttribute(ProcessorGroupEnum group) : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Название обработчика, к которому относится обработчик.
|
||||
/// </summary>
|
||||
public ProcessorGroupEnum Group { get; init; } = group;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Аттрибут обработчика для уточнения списка зависимостей.
|
||||
/// </summary>
|
||||
/// <param name="dependencies">Список названий зависимостей.</param>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
internal class ProcessorDependenciesAttribute(ICollection<string> dependencies) : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика.
|
||||
/// </summary>
|
||||
public ICollection<string> Dependencies { get; init; } = dependencies;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Аттрибут обработчика для внутреннего типа элемента.
|
||||
/// </summary>
|
||||
/// <param name="innerType">Внутренний типа элемента.</param>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
internal class ProcessorInnerTypeAttribute(string innerType) : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика.
|
||||
/// </summary>
|
||||
public string InnerType { get; init; } = innerType;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
namespace Pf2eDataScrapper.App;
|
||||
|
||||
/// <summary>
|
||||
/// Общий аттрибут обработчика.
|
||||
/// </summary>
|
||||
/// <param name="name">Название обработчика.</param>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class ProcessorAttribute(string name) : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Название обработчика.
|
||||
/// </summary>
|
||||
public string Name { get; init; } = name;
|
||||
|
||||
/// <summary>
|
||||
/// Описание обработчика.
|
||||
/// </summary>
|
||||
public string Description { get; init; } = name;
|
||||
|
||||
/// <summary>
|
||||
/// Группа обработчиков, к которому относится обработчик.
|
||||
/// </summary>
|
||||
public ProcessorGroupEnum Group { get; init; } = ProcessorGroupEnum.General;
|
||||
|
||||
/// <summary>
|
||||
/// Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика.
|
||||
/// </summary>
|
||||
public string? InnerType { get; init; } = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Аттрибут зависимостей обработчика.
|
||||
/// </summary>
|
||||
/// <param name="dependencies">Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика.</param>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class ProcessorDependenciesAttribute(string[] dependencies) : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика.
|
||||
/// </summary>
|
||||
public ICollection<string> Dependencies { get; } = dependencies;
|
||||
}
|
||||
@@ -29,7 +29,7 @@ internal class ProcessorCollection
|
||||
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
if (type.GetCustomAttributes(typeof(ProcessAttribute), true).Length <= 0)
|
||||
if (type.GetCustomAttributes(typeof(ProcessorAttribute), true).Length <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -51,21 +51,15 @@ internal class ProcessorCollection
|
||||
if (!type.IsSubclassOf(typeof(IProcessor)))
|
||||
{
|
||||
throw new(
|
||||
$"'ProcessAttribute' attribute should only be applied to children of 'IProcessor' class. '{type.FullName}' is not."
|
||||
$"'ProcessorAttribute' attribute should only be applied to children of 'IProcessor' class. '{type.FullName}' is not."
|
||||
);
|
||||
}
|
||||
|
||||
ProcessAttribute processAttribute = type.GetCustomAttribute<ProcessAttribute>()!;
|
||||
DescriptionAttribute? descriptionAttribute =
|
||||
type.GetCustomAttribute<DescriptionAttribute>();
|
||||
ProcessorGroupAttribute? groupAttribute =
|
||||
type.GetCustomAttribute<ProcessorGroupAttribute>();
|
||||
ProcessorAttribute processorAttribute = type.GetCustomAttribute<ProcessorAttribute>()!;
|
||||
ProcessorDependenciesAttribute? dependenciesAttribute =
|
||||
type.GetCustomAttribute<ProcessorDependenciesAttribute>();
|
||||
ProcessorInnerTypeAttribute? innerTypeAttribute =
|
||||
type.GetCustomAttribute<ProcessorInnerTypeAttribute>();
|
||||
|
||||
bool isCollection = innerTypeAttribute is not null;
|
||||
bool isCollection = processorAttribute.InnerType is not null;
|
||||
|
||||
ConstructorInfo? constructor = isCollection
|
||||
? type.GetConstructor([])
|
||||
@@ -78,13 +72,13 @@ internal class ProcessorCollection
|
||||
|
||||
return new()
|
||||
{
|
||||
Name = processAttribute.Name,
|
||||
Name = processorAttribute.Name,
|
||||
Type = type,
|
||||
Description = descriptionAttribute?.Description ?? processAttribute.Name,
|
||||
Group = groupAttribute?.Group ?? ProcessorGroupEnum.General,
|
||||
Description = processorAttribute.Description,
|
||||
Group = processorAttribute.Group,
|
||||
Dependencies = dependenciesAttribute?.Dependencies ?? [],
|
||||
IsCollectionProcessor = isCollection,
|
||||
InnerType = innerTypeAttribute?.InnerType,
|
||||
InnerType = processorAttribute.InnerType,
|
||||
Constructor = constructor,
|
||||
};
|
||||
}
|
||||
|
||||
+33
-32
@@ -31,11 +31,11 @@ partial class StartForm
|
||||
MainSplitContainer = new SplitContainer();
|
||||
PropertiesGroupBox = new GroupBox();
|
||||
SettingsPropertyGrid = new PropertyGrid();
|
||||
StartButton = new Button();
|
||||
ProcessorsGroupBox = new GroupBox();
|
||||
DeselectAllButton = new Button();
|
||||
SelectAllButton = new Button();
|
||||
ProcessorsListView = new ListView();
|
||||
SelectAllButton = new Button();
|
||||
DeselectAllButton = new Button();
|
||||
StartButton = new Button();
|
||||
((System.ComponentModel.ISupportInitialize)MainSplitContainer).BeginInit();
|
||||
MainSplitContainer.Panel1.SuspendLayout();
|
||||
MainSplitContainer.Panel2.SuspendLayout();
|
||||
@@ -84,17 +84,6 @@ partial class StartForm
|
||||
SettingsPropertyGrid.Size = new Size(288, 649);
|
||||
SettingsPropertyGrid.TabIndex = 0;
|
||||
//
|
||||
// StartButton
|
||||
//
|
||||
StartButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
StartButton.Font = new Font("Segoe UI", 18F, FontStyle.Bold);
|
||||
StartButton.Location = new Point(3, 611);
|
||||
StartButton.Name = "StartButton";
|
||||
StartButton.Size = new Size(621, 63);
|
||||
StartButton.TabIndex = 0;
|
||||
StartButton.Text = "Запуск";
|
||||
StartButton.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ProcessorsGroupBox
|
||||
//
|
||||
ProcessorsGroupBox.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
@@ -108,24 +97,6 @@ partial class StartForm
|
||||
ProcessorsGroupBox.TabStop = false;
|
||||
ProcessorsGroupBox.Text = "Обработчики";
|
||||
//
|
||||
// DeselectAllButton
|
||||
//
|
||||
DeselectAllButton.Location = new Point(6, 19);
|
||||
DeselectAllButton.Name = "DeselectAllButton";
|
||||
DeselectAllButton.Size = new Size(137, 23);
|
||||
DeselectAllButton.TabIndex = 0;
|
||||
DeselectAllButton.Text = "Снять выделение всех";
|
||||
DeselectAllButton.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// SelectAllButton
|
||||
//
|
||||
SelectAllButton.Location = new Point(149, 19);
|
||||
SelectAllButton.Name = "SelectAllButton";
|
||||
SelectAllButton.Size = new Size(137, 23);
|
||||
SelectAllButton.TabIndex = 1;
|
||||
SelectAllButton.Text = "Выделить все";
|
||||
SelectAllButton.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ProcessorsListView
|
||||
//
|
||||
ProcessorsListView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
@@ -136,6 +107,35 @@ partial class StartForm
|
||||
ProcessorsListView.TabIndex = 2;
|
||||
ProcessorsListView.UseCompatibleStateImageBehavior = false;
|
||||
//
|
||||
// SelectAllButton
|
||||
//
|
||||
SelectAllButton.Location = new Point(149, 19);
|
||||
SelectAllButton.Name = "SelectAllButton";
|
||||
SelectAllButton.Size = new Size(137, 23);
|
||||
SelectAllButton.TabIndex = 1;
|
||||
SelectAllButton.Text = "Выделить все";
|
||||
SelectAllButton.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// DeselectAllButton
|
||||
//
|
||||
DeselectAllButton.Location = new Point(6, 19);
|
||||
DeselectAllButton.Name = "DeselectAllButton";
|
||||
DeselectAllButton.Size = new Size(137, 23);
|
||||
DeselectAllButton.TabIndex = 0;
|
||||
DeselectAllButton.Text = "Снять выделение всех";
|
||||
DeselectAllButton.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// StartButton
|
||||
//
|
||||
StartButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
StartButton.Font = new Font("Segoe UI", 18F, FontStyle.Bold);
|
||||
StartButton.Location = new Point(3, 611);
|
||||
StartButton.Name = "StartButton";
|
||||
StartButton.Size = new Size(621, 63);
|
||||
StartButton.TabIndex = 0;
|
||||
StartButton.Text = "Запуск";
|
||||
StartButton.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// StartForm
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
@@ -144,6 +144,7 @@ partial class StartForm
|
||||
Controls.Add(MainSplitContainer);
|
||||
Name = "StartForm";
|
||||
Text = "Настройки импорта данных";
|
||||
Load += StartForm_Load;
|
||||
MainSplitContainer.Panel1.ResumeLayout(false);
|
||||
MainSplitContainer.Panel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)MainSplitContainer).EndInit();
|
||||
|
||||
@@ -1,9 +1,64 @@
|
||||
namespace Pf2eDataScrapper.Forms;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using Pf2eDataScrapper.App;
|
||||
|
||||
public partial class StartForm : Form
|
||||
namespace Pf2eDataScrapper.Forms;
|
||||
|
||||
internal partial class StartForm : Form
|
||||
{
|
||||
public StartForm()
|
||||
private readonly ProcessorCollection _processorCollection;
|
||||
|
||||
public StartForm(ProcessorCollection processorCollection)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_processorCollection = processorCollection;
|
||||
}
|
||||
|
||||
private void StartForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
PopulateListView();
|
||||
}
|
||||
|
||||
private void PopulateListView()
|
||||
{
|
||||
Dictionary<ProcessorGroupEnum, List<ProcessorCollectionItem>> items = [];
|
||||
|
||||
foreach (ProcessorCollectionItem item in _processorCollection.AllItems)
|
||||
{
|
||||
items.TryAdd(item.Group, []);
|
||||
items[item.Group].Add(item);
|
||||
}
|
||||
|
||||
ProcessorsListView.Groups.Clear();
|
||||
|
||||
foreach (FieldInfo field in typeof(ProcessorGroupEnum).GetFields())
|
||||
{
|
||||
ProcessorGroupEnum groupEnum = (ProcessorGroupEnum)field.GetValue(null)!;
|
||||
|
||||
if (!items.TryGetValue(groupEnum, out List<ProcessorCollectionItem>? list))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DescriptionAttribute? attribute = (DescriptionAttribute?)
|
||||
Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute));
|
||||
|
||||
string name = attribute?.Description ?? field.Name;
|
||||
|
||||
ListViewGroup listViewGroup = new(name);
|
||||
ProcessorsListView.Groups.Add(listViewGroup);
|
||||
|
||||
foreach (ProcessorCollectionItem item in list)
|
||||
{
|
||||
ListViewItem listViewItem = new()
|
||||
{
|
||||
Group = listViewGroup,
|
||||
Text = item.Description,
|
||||
Selected = true,
|
||||
};
|
||||
ProcessorsListView.Items.Add(listViewItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using Pf2eModel;
|
||||
using Slugify;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers;
|
||||
namespace Pf2eDataScrapper.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Класс предоставляет методы для работы с базой данных.
|
||||
@@ -1,6 +1,10 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Forms;
|
||||
using Pf2eDataScrapper.Importers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eModel;
|
||||
|
||||
namespace Pf2eDataScrapper;
|
||||
@@ -15,23 +19,27 @@ internal sealed class ImportApplication : ApplicationContext
|
||||
|
||||
#region "Внедрение зависимостей (DI)"
|
||||
|
||||
public IServiceCollection Services = new ServiceCollection();
|
||||
public readonly IServiceCollection Services = new ServiceCollection();
|
||||
|
||||
public IServiceProvider ServiceProvider { get; private set; } = null!;
|
||||
|
||||
private void InitializeServices()
|
||||
{
|
||||
Services.AddSingleton(this);
|
||||
Services.AddSingleton(Settings);
|
||||
|
||||
Services.AddSingleton<ProcessorCollection>();
|
||||
Services.AddSingleton(Processors);
|
||||
|
||||
Services.AddDbContext<Pf2eDbContext>();
|
||||
|
||||
ServiceProvider = Services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region "Настройки"
|
||||
|
||||
public ApplicationSettings Settings = new();
|
||||
public readonly ApplicationSettings Settings = new();
|
||||
public readonly ProcessorCollection Processors = new();
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -45,13 +53,73 @@ internal sealed class ImportApplication : ApplicationContext
|
||||
|
||||
private void CreateStartForm()
|
||||
{
|
||||
_startForm = new() { StartPosition = FormStartPosition.CenterParent };
|
||||
_startForm = ActivatorUtilities.CreateInstance<StartForm>(ServiceProvider);
|
||||
_startForm.StartPosition = FormStartPosition.CenterParent;
|
||||
_startForm.Show();
|
||||
}
|
||||
|
||||
private void StartProcess()
|
||||
{
|
||||
_startForm!.Close();
|
||||
|
||||
Processors.SortItems();
|
||||
|
||||
ProcessProgress progress = new ProcessProgress();
|
||||
|
||||
foreach (ProcessorCollectionItem item in Processors.Items)
|
||||
{
|
||||
if (item.IsCollectionProcessor)
|
||||
{
|
||||
RunCollection(item, progress);
|
||||
}
|
||||
else
|
||||
{
|
||||
RunSingle(item, progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RunSingle(ProcessorCollectionItem item, ProcessProgress progress)
|
||||
{
|
||||
progress.Local.Reset(1);
|
||||
progress.Local.Start("");
|
||||
|
||||
IProcessor processor = (IProcessor)
|
||||
ActivatorUtilities.CreateInstance(ServiceProvider, item.Type);
|
||||
|
||||
processor.Process();
|
||||
processor.Save();
|
||||
|
||||
progress.Local.Complete();
|
||||
}
|
||||
|
||||
private void RunCollection(ProcessorCollectionItem item, ProcessProgress progress)
|
||||
{
|
||||
AbstractImporter importer = item.Group switch
|
||||
{
|
||||
ProcessorGroupEnum.AonprdPreparation
|
||||
or ProcessorGroupEnum.AonprdEntities
|
||||
or ProcessorGroupEnum.AonprdSubclasses => new AonprdImporter(),
|
||||
ProcessorGroupEnum.FoundryEnPreparation => new Pf2EFoundryImporter(),
|
||||
_ => throw new("Can't recognize importer"),
|
||||
};
|
||||
|
||||
progress.Local.Reset(importer.CountInputs(item.InnerType!));
|
||||
|
||||
foreach (ProcessorInput input in importer.ResolveInputs(item.InnerType!))
|
||||
{
|
||||
progress.Local.Start(input.Name);
|
||||
|
||||
IProcessor processor = (IProcessor)
|
||||
ActivatorUtilities.CreateInstance(ServiceProvider, item.Type);
|
||||
|
||||
processor.Process();
|
||||
processor.Save();
|
||||
|
||||
progress.Local.End();
|
||||
}
|
||||
|
||||
progress.Local.Complete();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Pf2eDataScrapper.Importers.Repositories;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers;
|
||||
|
||||
@@ -36,15 +37,32 @@ internal abstract class AbstractImporter
|
||||
/// <summary>
|
||||
/// Метод подготовки данных для импорта.
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public abstract void Prepare();
|
||||
|
||||
/// <summary>
|
||||
/// Импорт данных
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public abstract void Import();
|
||||
|
||||
/// <summary>
|
||||
/// Построение схем данных.
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public abstract void BuildSchemas();
|
||||
|
||||
/// <summary>
|
||||
/// Получение количества записей, принаделажащих типу <paramref name="type"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">Тип записей.</param>
|
||||
/// <returns>Количество записей.</returns>
|
||||
public abstract int CountInputs(string type);
|
||||
|
||||
/// <summary>
|
||||
/// Итератор ввода для записей, принаделажащих типу <paramref name="type"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">Тип записей.</param>
|
||||
/// <returns>Итератор.</returns>
|
||||
public abstract IEnumerable<ProcessorInput> ResolveInputs(string type);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.SchemaBuilder;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||
using Pf2eDataScrapper.Importers.Repositories;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
||||
|
||||
@@ -9,6 +11,11 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
||||
/// </summary>
|
||||
internal class AonprdImporter : AbstractImporter
|
||||
{
|
||||
/// <summary>
|
||||
/// Название внешней ссылки.
|
||||
/// </summary>
|
||||
public const string TargetName = "Archives of Nethys Pathfinder 2e";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Name => TargetName;
|
||||
|
||||
@@ -16,8 +23,7 @@ internal class AonprdImporter : AbstractImporter
|
||||
public override string Slug => "aonprd";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override AbstractImporterRepository Repository =>
|
||||
new AonprdRepository(this, "https://elasticsearch.aonprd.com");
|
||||
public override AbstractImporterRepository Repository { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Инструмент для работы с данными сайта Архивов Нефеса.
|
||||
@@ -29,37 +35,47 @@ internal class AonprdImporter : AbstractImporter
|
||||
/// </summary>
|
||||
public AonprdImporter()
|
||||
{
|
||||
Repository = new AonprdRepository(this, "https://elasticsearch.aonprd.com");
|
||||
Loader = new(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Prepare()
|
||||
public override void Prepare() { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void BuildSchemas() { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Import() { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int CountInputs(string type)
|
||||
{
|
||||
Repository.Update();
|
||||
Loader.Prepare();
|
||||
return Loader.Compendium.Count(type);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void BuildSchemas()
|
||||
public override IEnumerable<ProcessorInput> ResolveInputs(string type)
|
||||
{
|
||||
AonprdSchemaBuilder builder = new(Loader);
|
||||
foreach (string file in Loader.Compendium.Files(type))
|
||||
{
|
||||
using StreamReader fileReader = new(Path.Combine(Dir, $"{file}.json"));
|
||||
JArray array = JArray.Parse(fileReader.ReadToEnd());
|
||||
|
||||
builder.BuildSchemas();
|
||||
builder.Save(EnvSettings.OutputDir);
|
||||
foreach (JToken item in array)
|
||||
{
|
||||
string? id = item.SelectToken("id")?.ToString();
|
||||
|
||||
if (id is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AonprdReference.ResolveType(id) == type)
|
||||
{
|
||||
yield return new AonprdProcessorInput(id, (JObject)item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Import()
|
||||
{
|
||||
AonprdDataBuilder builder = new(Loader);
|
||||
builder.Processors.UseOnlyNames(ProcessorNames);
|
||||
|
||||
builder.TruncateTables();
|
||||
builder.Build();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Название внешней ссылки.
|
||||
/// </summary>
|
||||
public const string TargetName = "Archives of Nethys Pathfinder 2e";
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,14 +1,14 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
||||
|
||||
/// <summary>
|
||||
/// Класс для работы с JSON-объектом при обработки данных с Архивов Нефиса.
|
||||
/// </summary>
|
||||
/// <param name="input">JSON-объект, который будет использоваться для доступа к данным.</param>
|
||||
internal class AonprdProcessorInput(JObject input) : ProcessorInput(input)
|
||||
internal class AonprdProcessorInput(string name, JObject input) : ProcessorInput(name, input)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override T Enum<T>(string value)
|
||||
@@ -1,6 +1,7 @@
|
||||
using Konsole;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.Importers.Repositories;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
||||
|
||||
@@ -38,18 +39,21 @@ internal class AonprdRepository(AbstractImporter importer, string searchUrl)
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Update()
|
||||
public override void Update(ProcessProgress progress)
|
||||
{
|
||||
if (CheckRevision())
|
||||
{
|
||||
Console.WriteLine($"Данные Aonprd актуальны, текущая ревизия {Revision}.");
|
||||
progress.Local.Complete();
|
||||
progress.Message($"Данные Aonprd актуальны, текущая ревизия {Revision}.");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine(
|
||||
progress.Message(
|
||||
$"Данные Aonprd устарели, обновляем {RepositoryDirPath} до ревизии {Revision}..."
|
||||
);
|
||||
|
||||
progress.Local.Reset(1);
|
||||
|
||||
if (Directory.Exists(RepositoryDirPath))
|
||||
{
|
||||
Directory.Delete(RepositoryDirPath, true);
|
||||
@@ -58,27 +62,28 @@ internal class AonprdRepository(AbstractImporter importer, string searchUrl)
|
||||
|
||||
WriteFile("revision.txt", Revision.ToString());
|
||||
|
||||
Console.WriteLine("Загрузка индекса...");
|
||||
progress.Local.Start("Загрузка индекса...");
|
||||
|
||||
string indexContent = Load($"/json-data/aon{Revision}-index.json");
|
||||
WriteFile("index.json", indexContent);
|
||||
|
||||
JObject indexJson = JObject.Parse(indexContent);
|
||||
|
||||
Console.WriteLine("Загрузка индексных файлов...");
|
||||
|
||||
ProgressBar bar = new(indexJson.Count);
|
||||
int i = 0;
|
||||
progress.Local.Reset(indexJson.Count + 1);
|
||||
progress.Local.End();
|
||||
|
||||
foreach (KeyValuePair<string, JToken?> kvp in indexJson)
|
||||
{
|
||||
string fileName = kvp.Key;
|
||||
bar.Refresh(i++, fileName);
|
||||
progress.Local.Start(fileName);
|
||||
|
||||
string fileContent = Load($"/json-data/{fileName}.json");
|
||||
WriteFile($"{fileName}.json", fileContent);
|
||||
|
||||
progress.Local.End();
|
||||
}
|
||||
|
||||
bar.Refresh(indexJson.Count, "Готово!");
|
||||
progress.Local.Complete();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -35,18 +35,32 @@ internal class AonprdCompendium
|
||||
/// <returns>Количество элементов.</returns>
|
||||
public int Count() => Types.Values.Sum(t => t.Count);
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает количество элементов для указанного типа данных.
|
||||
/// </summary>
|
||||
/// <param name="type">Тип данных.</param>
|
||||
/// <returns>Количество элементов.</returns>
|
||||
public int Count(string type) => Types.Values.First(t => t.Type == type).Count;
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает количество элементов для указанных типов данных.
|
||||
/// </summary>
|
||||
/// <param name="types">Список типов.</param>
|
||||
/// <param name="types">Список типов данных.</param>
|
||||
/// <returns>Количество элементов.</returns>
|
||||
public int Count(IEnumerable<string> types) =>
|
||||
Types.Values.Where(t => types.Contains(t.Type)).Sum(t => t.Count);
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает список файлов для выбора сущностей указанного типа данных.
|
||||
/// </summary>
|
||||
/// <param name="type">Тип данных.</param>
|
||||
/// <returns>Список искомых файлов.</returns>
|
||||
public IEnumerable<string> Files(string type) => Types.Values.First(t => t.Type == type).Files;
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает список файлов для выбора сущностей указанных типов данных.
|
||||
/// </summary>
|
||||
/// <param name="types">Список типов.</param>
|
||||
/// <param name="types">Список типов данных.</param>
|
||||
/// <returns>Список искомых файлов.</returns>
|
||||
public IEnumerable<string> Files(IEnumerable<string> types) =>
|
||||
Types.Values.Where(t => types.Contains(t.Type)).SelectMany(t => t.Files).Distinct();
|
||||
|
||||
@@ -25,7 +25,7 @@ internal class AonprdReference(string id, string file)
|
||||
/// <summary>
|
||||
/// Определение типа сущности как префикса идентификатора.
|
||||
/// </summary>
|
||||
private static string ResolveType(string id)
|
||||
public static string ResolveType(string id)
|
||||
{
|
||||
string type = string.Join('-', id.Split('-')[..^1]);
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
||||
|
||||
/// <summary>
|
||||
/// Класс AonprdType представляет собой уникальный тип данных, связанный с Aon (Advanced Opportunity Network).
|
||||
/// Это основной класс, который хранит информацию о различных элементах системы.
|
||||
/// Класс типа элементов с Архива Нефиса.
|
||||
/// </summary>
|
||||
internal class AonprdType(string type)
|
||||
{
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
using Konsole;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eModel;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||
|
||||
/// <summary>
|
||||
/// Класс для создание схемы данных Архива Нефиса.
|
||||
/// </summary>
|
||||
/// <param name="loader"></param>
|
||||
internal class AonprdDataBuilder(AonprdLoader loader)
|
||||
{
|
||||
/// <summary>
|
||||
/// Основной класс для работы с данными Архива Нефиса.
|
||||
/// </summary>
|
||||
public readonly AonprdLoader Loader = loader;
|
||||
|
||||
/// <summary>
|
||||
/// Коллекция папок компендиума.
|
||||
/// </summary>
|
||||
public AonprdCompendium Compendium => Loader.Compendium;
|
||||
|
||||
/// <summary>
|
||||
/// Коллекция обработчиков данных.
|
||||
/// </summary>
|
||||
public readonly AonprdProcessorCollection Processors = new();
|
||||
|
||||
/// <summary>
|
||||
/// Очистить таблицы в базе данных.
|
||||
/// </summary>
|
||||
public void TruncateTables()
|
||||
{
|
||||
Console.WriteLine("Truncating all old data...");
|
||||
|
||||
using Pf2eDbContext context = new();
|
||||
string cmd = context.Entities.Truncate() + "\n" + context.TruncateAll();
|
||||
|
||||
Console.WriteLine(cmd);
|
||||
|
||||
Console.WriteLine("Truncation completed!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конфигурация интерфейса вывода результатов.
|
||||
/// </summary>
|
||||
protected ConcurrentWriter Window = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Основное окно для вывода информации.
|
||||
/// </summary>
|
||||
protected Window Output = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Полоса прогресса для основного процесса обработки данных.
|
||||
/// </summary>
|
||||
protected ProgressBar ProcessProgressBar = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Полоса прогресса для под-процессов обработки данных.
|
||||
/// </summary>
|
||||
protected ProgressBar SubProcessProgressBar = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Метод для настройки интерфейса.
|
||||
/// </summary>
|
||||
protected void ConfigureWindow()
|
||||
{
|
||||
Window = new Window(0, 0, Console.WindowWidth, Console.WindowHeight).Concurrent();
|
||||
|
||||
IConsole bars = Window.OpenBox(
|
||||
"Progress",
|
||||
Console.WindowWidth,
|
||||
4,
|
||||
new() { Body = Colors.WhiteOnBlack }
|
||||
);
|
||||
|
||||
Output = new(0, 4, Console.WindowWidth, Console.WindowHeight - 4, Window);
|
||||
|
||||
ProcessProgressBar = new(bars, Processors.Items.Count, 15);
|
||||
|
||||
SubProcessProgressBar = new(bars, 1, 15);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обработка отдельного процессора данных.
|
||||
/// </summary>
|
||||
protected void RunProcessor(AonprdProcessorCollection.ProcessorItem item, JObject json)
|
||||
{
|
||||
AonprdProcessorInput input = new(json);
|
||||
AbstractProcessor processor = (AbstractProcessor)item.Constructor.Invoke([input]);
|
||||
|
||||
try
|
||||
{
|
||||
processor.Process();
|
||||
processor.Save();
|
||||
}
|
||||
catch (LegacyItemException ex)
|
||||
{
|
||||
Output.WriteLine(ex.Message);
|
||||
}
|
||||
catch (SkipItemException ex)
|
||||
{
|
||||
Output.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Полная обработка и сохранение данных.
|
||||
/// </summary>
|
||||
public void Build()
|
||||
{
|
||||
ConfigureWindow();
|
||||
|
||||
ProcessProgressBar.Refresh(-1, "");
|
||||
|
||||
foreach (AonprdProcessorCollection.ProcessorItem item in Processors.Iterate())
|
||||
{
|
||||
ProcessProgressBar.Next(item.Attribute.Name);
|
||||
|
||||
SubProcessProgressBar.Refresh(-1, "Starting...");
|
||||
|
||||
if (item.Attribute.Type is null)
|
||||
{
|
||||
RunProcessor(item, []);
|
||||
continue;
|
||||
}
|
||||
|
||||
SubProcessProgressBar.Max = Compendium.Count([item.Attribute.Type]);
|
||||
|
||||
foreach (AonprdLoader.LoaderEntry entry in Loader.Entries(item.Attribute.Type))
|
||||
{
|
||||
SubProcessProgressBar.Next($"{entry.Id}");
|
||||
RunProcessor(item, entry.Json);
|
||||
}
|
||||
|
||||
SubProcessProgressBar.Next("Ready");
|
||||
|
||||
DatabaseHelper.ResetContext();
|
||||
}
|
||||
|
||||
ProcessProgressBar.Next("Done!");
|
||||
|
||||
Window.Clear();
|
||||
}
|
||||
}
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
using Pf2eDataScrapper.App.Attributes;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||
|
||||
/// <summary>
|
||||
/// Атрибут обработчика данных Архивов Нефиса.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class AonprdProcessorAttribute : Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Важные общие зависимости для обработчка.
|
||||
/// </summary>
|
||||
private static readonly string[] DefaultDependencies = ["aonprd:trait", "aonprd:source"];
|
||||
|
||||
/// <summary>
|
||||
/// Тип данных, которые обработчик обрабатывает.
|
||||
/// </summary>
|
||||
public string Type { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор класса <see cref="AonprdProcessorAttribute"/> со стандартными общими зависимости для обработчка.
|
||||
/// </summary>
|
||||
/// <param name="type">Тип данных, которые обработчик обрабатывает. Также будет использоваться в качестве названия.</param>
|
||||
public AonprdProcessorAttribute(string type)
|
||||
: this(type, type, DefaultDependencies) { }
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор класса <see cref="AonprdProcessorAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">Тип данных, которые обработчик обрабатывает. Также будет использоваться в качестве названия.</param>
|
||||
/// <param name="dependencies">Названия обработчиков, которые должны быть выполнены до запуска этого обработчика.</param>
|
||||
/// <param name="includeDefaults">Флаг, указывающий, следует ли добавить важные общие зависимости для обработчка.</param>
|
||||
public AonprdProcessorAttribute(string type, string[] dependencies, bool includeDefaults = true)
|
||||
: this(type, type, dependencies, includeDefaults) { }
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор класса <see cref="AonprdProcessorAttribute"/> со стандартными общими зависимости для обработчка.
|
||||
/// </summary>
|
||||
/// <param name="name">Название обработчика.</param>
|
||||
/// <param name="type">Тип данных, которые обработчик обрабатывает.</param>
|
||||
public AonprdProcessorAttribute(string name, string type)
|
||||
: this(name, type, DefaultDependencies) { }
|
||||
|
||||
/// <summary>
|
||||
/// Основной конструктор класса <see cref="AonprdProcessorAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">Название обработчика.</param>
|
||||
/// <param name="type">Тип данных, которые обработчик обрабатывает.</param>
|
||||
/// <param name="dependencies">Названия обработчиков, которые должны быть выполнены до запуска этого обработчика.</param>
|
||||
/// <param name="includeDefaults">Флаг, указывающий, следует ли добавить важные общие зависимости для обработчка.</param>
|
||||
public AonprdProcessorAttribute(
|
||||
string name,
|
||||
string? type,
|
||||
ICollection<string> dependencies,
|
||||
bool includeDefaults = true
|
||||
)
|
||||
: base($"aonprd:{name}", [.. includeDefaults ? DefaultDependencies : [], .. dependencies])
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
-187
@@ -1,187 +0,0 @@
|
||||
using System.Reflection;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||
|
||||
/// <summary>
|
||||
/// Класс отвечает за управление обработчиками, отмеченных атрибутом <see cref="AonprdProcessorAttribute"/>.
|
||||
/// </summary>
|
||||
internal class AonprdProcessorCollection
|
||||
{
|
||||
/// <summary>
|
||||
/// Элемент коллекции обработчика.
|
||||
/// </summary>
|
||||
/// <param name="attribute">Атрибут, связанный с обаботчиком.</param>
|
||||
/// <param name="constructor">Конструктор обработчика.</param>
|
||||
public class ProcessorItem(AonprdProcessorAttribute attribute, ConstructorInfo constructor)
|
||||
{
|
||||
/// <summary>
|
||||
/// Атрибут, связанный с обаботчиком.
|
||||
/// </summary>
|
||||
public readonly AonprdProcessorAttribute Attribute = attribute;
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор обработчика.
|
||||
/// </summary>
|
||||
public readonly ConstructorInfo Constructor = constructor;
|
||||
|
||||
/// <summary>
|
||||
/// Приоритет выполнения обработчика.
|
||||
/// </summary>
|
||||
public int Priority = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Список всех объявленных обработчиков.
|
||||
/// </summary>
|
||||
private readonly List<ProcessorItem> _allItems;
|
||||
|
||||
/// <summary>
|
||||
/// Список используемых обработчиков.
|
||||
/// </summary>
|
||||
public List<ProcessorItem> Items { get; private set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор класса <see cref="AonprdProcessorCollection"/>, загружающий все обработчики.
|
||||
/// </summary>
|
||||
public AonprdProcessorCollection()
|
||||
{
|
||||
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
|
||||
{
|
||||
if (type.GetCustomAttributes(typeof(AonprdProcessorAttribute), true).Length <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!type.IsSubclassOf(typeof(AbstractProcessor)))
|
||||
{
|
||||
throw new(
|
||||
$"'AonprdProcessor' attribute should only be applied to children of 'AbstractProcessor' class. '{type.FullName}' is not."
|
||||
);
|
||||
}
|
||||
|
||||
AonprdProcessorAttribute attribute =
|
||||
type.GetCustomAttribute<AonprdProcessorAttribute>()!;
|
||||
|
||||
ConstructorInfo constructor = type.GetConstructor([typeof(AonprdProcessorInput)])!;
|
||||
|
||||
ProcessorItem? collision = Items.FirstOrDefault(i =>
|
||||
i.Attribute.Name == attribute.Name
|
||||
);
|
||||
if (collision is not null)
|
||||
{
|
||||
throw new(
|
||||
$"Multiply attributes 'AonprdProcessor' have same name '{attribute.Name}'."
|
||||
+ $" They are added to classes: '{type.FullName}' and '{collision.Constructor.DeclaringType!.FullName}'"
|
||||
);
|
||||
}
|
||||
|
||||
Items.Add(new(attribute, constructor));
|
||||
}
|
||||
|
||||
_allItems = Items.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверка, что все зависимости всех обработчиков могут быть удовлетворены.
|
||||
/// </summary>
|
||||
private void CheckDependencies()
|
||||
{
|
||||
foreach (ProcessorItem item in Items)
|
||||
{
|
||||
foreach (string dependency in item.Attribute.Dependencies)
|
||||
{
|
||||
if (Items.All(i => i.Attribute.Name != dependency))
|
||||
{
|
||||
throw new(
|
||||
$"Dependency '{dependency}' for processor '{item.Attribute.Name}' not found."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сортировать обработчики в соответсвии со всеми зависимостями.
|
||||
/// </summary>
|
||||
private void SortItems()
|
||||
{
|
||||
CheckDependencies();
|
||||
|
||||
Dictionary<string, int> priorities = [];
|
||||
|
||||
while (priorities.Count < Items.Count)
|
||||
{
|
||||
foreach (ProcessorItem item in Items)
|
||||
{
|
||||
if (item.Priority > 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IEnumerable<int> dependencyPriorities = item.Attribute.Dependencies.Select(d =>
|
||||
priorities.GetValueOrDefault(d, -1)
|
||||
);
|
||||
|
||||
if (dependencyPriorities.Any(p => p == -1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
item.Priority = dependencyPriorities.Any() ? dependencyPriorities.Max() + 1 : 1;
|
||||
priorities.Add(item.Attribute.Name, item.Priority);
|
||||
}
|
||||
}
|
||||
|
||||
Items.Sort((a, b) => a.Priority - b.Priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Итерация через все используемые обработчики.
|
||||
/// </summary>
|
||||
/// <returns>Итератор.</returns>
|
||||
public IEnumerable<ProcessorItem> Iterate()
|
||||
{
|
||||
SortItems();
|
||||
|
||||
foreach (ProcessorItem item in Items)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ограничить список используемых обработчиков по названию.
|
||||
/// Автоматически включает все обработчики, от которых зависят указанные в аргументе обработчики.
|
||||
/// </summary>
|
||||
/// <param name="processorNames">Коллекция названиий требуемых обработчиков.</param>
|
||||
public void UseOnlyNames(ICollection<string> processorNames)
|
||||
{
|
||||
if (processorNames.Count == 0)
|
||||
{
|
||||
Items = _allItems;
|
||||
return;
|
||||
}
|
||||
|
||||
Dictionary<string, bool> nameFlags = processorNames.ToDictionary(name => name, _ => false);
|
||||
|
||||
while (nameFlags.Values.Any(v => !v))
|
||||
{
|
||||
foreach (
|
||||
KeyValuePair<string, bool> pair in nameFlags.Where(pair => !pair.Value).ToList()
|
||||
)
|
||||
{
|
||||
ProcessorItem item = _allItems.First(item => item.Attribute.Name == pair.Key);
|
||||
|
||||
foreach (string dependency in item.Attribute.Dependencies)
|
||||
{
|
||||
nameFlags.TryAdd(dependency, false);
|
||||
}
|
||||
|
||||
nameFlags[pair.Key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
Items = _allItems.Where(item => nameFlags.ContainsKey(item.Attribute.Name)).ToList();
|
||||
}
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eModel.Model.Base.Targets;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common;
|
||||
|
||||
[AonprdProcessor("external", null, [], false)]
|
||||
internal class ExternalProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
||||
{
|
||||
public ExternalTarget AonprdTarget = null!;
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
AonprdTarget = new()
|
||||
{
|
||||
Name = AonprdImporter.TargetName,
|
||||
Icon = "http://www.google.com/s2/favicons?domain=2e.aonprd.com",
|
||||
Prefix = "https://2e.aonprd.com",
|
||||
};
|
||||
}
|
||||
|
||||
public override void Save()
|
||||
{
|
||||
Context.ExternalTargets.Add(AonprdTarget);
|
||||
|
||||
Globals.AonprdTarget = AonprdTarget;
|
||||
}
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||
|
||||
[AonprdProcessor("archetype")]
|
||||
internal class ArchetypeProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Archetype;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Archetype Object { get; } = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Add() => Context.Archetypes.Add(Object);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Process()
|
||||
{
|
||||
base.Process();
|
||||
|
||||
Object.Level = Input.GetOptional<int>("level");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string[] AddedDescriptionPaths() =>
|
||||
["prerequisite_markdown", "requirement_markdown", "summary_markdown"];
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||
|
||||
[AonprdProcessor("language")]
|
||||
internal class LanguageProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Language;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Language Object { get; } = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Add() => Context.Languages.Add(Object);
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||
|
||||
[AonprdProcessor("trait", ["external"], false)]
|
||||
internal class TraitProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Trait;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Trait Object { get; } = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Add() => Context.Traits.Add(Object);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Process()
|
||||
{
|
||||
base.Process();
|
||||
|
||||
Object.Type = TraitType.Regular;
|
||||
|
||||
Context.Traits.Add(Object);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void AddTraits()
|
||||
{
|
||||
// Необходимо пропускать
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetDescription() =>
|
||||
base.GetDescription() + AddedDescription(["summary_markdown", "search_markdown"]);
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using Pf2eModel.Model.Base.Targets;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Класс-помощник, хранящий необходимые глобальные данные.
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using Pf2eModel.Model.Enum;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Класс, помогающий разрешить строковые значения с Архивов Нефиса в перечисления.
|
||||
+2
-1
@@ -1,9 +1,10 @@
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors;
|
||||
using Pf2eModel.Model.Base;
|
||||
using Pf2eModel.Model.Base.Source;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Обработчик сущностей, помеченных как устаревшие.
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using Pf2eModel.Model.Base.Source;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types.Rules;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Класс коллекции книг, содержащих правила.
|
||||
+19
-5
@@ -3,6 +3,10 @@ using System.Text;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model;
|
||||
@@ -13,18 +17,28 @@ using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// Абстрактный класс-обработчик сущностей, полученных из Архивов Нефиса.
|
||||
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
||||
/// для которых указан атрибут <see cref="AonprdProcessorAttribute"/>.
|
||||
/// для которых указан атрибут <see cref="ProcessorAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="input">Объект обработки вводимого JSON.</param>
|
||||
/// <seealso cref="AonprdProcessorAttribute"/>
|
||||
internal abstract class AbstractEntityProcessor(AonprdProcessorInput input)
|
||||
: AbstractProcessor(input)
|
||||
/// <seealso cref="ProcessorAttribute"/>
|
||||
internal abstract class AbstractEntityProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractInputProcessor(input)
|
||||
{
|
||||
public Pf2eDbContext Context { get; } = context;
|
||||
public StringHelper StringHelper { get; } = stringHelper;
|
||||
public DatabaseHelper Helper { get; } = helper;
|
||||
public AonprdBuilderGlobals Globals { get; } = globals;
|
||||
|
||||
/// <summary>
|
||||
/// Корневая сущность.
|
||||
/// </summary>
|
||||
+14
-7
@@ -1,20 +1,27 @@
|
||||
using Pf2eModel;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Base;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// Абстрактный класс-обработчик сущностей подклассов, полученных из Архивов Нефиса.
|
||||
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
||||
/// для которых указан атрибут <see cref="AonprdProcessorAttribute"/>.
|
||||
/// для которых указан атрибут <see cref="ProcessorAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="input">Объект обработки вводимого JSON.</param>
|
||||
/// <seealso cref="AonprdProcessorAttribute"/>
|
||||
internal abstract class AbstractSubclassProcessor(AonprdProcessorInput input)
|
||||
: AbstractEntityProcessor(input)
|
||||
internal abstract class AbstractSubclassProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Subclass;
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
|
||||
|
||||
[Processor(
|
||||
"aonprd:repository",
|
||||
Description = "Обновление репозитория",
|
||||
Group = ProcessorGroupEnum.AonprdPreparation
|
||||
)]
|
||||
internal class AonprdRepositoryUpdateProcessor(AonprdImporter importer, ProcessProgress progress)
|
||||
: IProcessor
|
||||
{
|
||||
private AonprdImporter Importer { get; } = importer;
|
||||
public ProcessProgress Progress { get; } = progress;
|
||||
|
||||
public void Process()
|
||||
{
|
||||
Importer.Repository.Update(Progress);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
Importer.Loader.Prepare();
|
||||
}
|
||||
}
|
||||
+57
-58
@@ -1,24 +1,29 @@
|
||||
using Konsole;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eDataScrapper.SchemaBuilder;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.SchemaBuilder;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Класс создания схемы данных с сайта Архивов Нефеса.
|
||||
/// </summary>
|
||||
/// <param name="loader">Загузчик данных с сайта Архивов Нефеса.</param>
|
||||
internal class AonprdSchemaBuilder(AonprdLoader loader)
|
||||
[Processor(
|
||||
"aonprd:schema",
|
||||
Description = "Построение схемы данных",
|
||||
Group = ProcessorGroupEnum.AonprdPreparation
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:repository"])]
|
||||
internal class AonprdSchemaBuildProcessor(
|
||||
AonprdImporter importer,
|
||||
ProcessProgress progress,
|
||||
ApplicationSettings settings
|
||||
) : IProcessor
|
||||
{
|
||||
public AonprdImporter Importer { get; } = importer;
|
||||
public ProcessProgress Progress { get; } = progress;
|
||||
public ApplicationSettings Settings { get; } = settings;
|
||||
|
||||
/// <summary>
|
||||
/// Загузчик данных с сайта Архивов Нефеса.
|
||||
/// </summary>
|
||||
public readonly AonprdLoader Loader = loader;
|
||||
|
||||
/// <inheritdoc cref="AonprdLoader.Compendium"/>
|
||||
public readonly AonprdCompendium Compendium = loader.Compendium;
|
||||
|
||||
// public readonly AonprdSchemaTypeResolver Resolver = new();
|
||||
public AonprdLoader Loader => Importer.Loader;
|
||||
|
||||
/// <summary>
|
||||
/// Дополнительные схемы данных.
|
||||
@@ -28,6 +33,44 @@ internal class AonprdSchemaBuilder(AonprdLoader loader)
|
||||
["_subclass"] = new() { Path = "_subclass" },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Построение схемы данных.
|
||||
/// </summary>
|
||||
public void Process()
|
||||
{
|
||||
Progress.Local.Reset(Loader.ItemCount);
|
||||
|
||||
foreach (AonprdLoader.LoaderEntry entry in Loader.Entries())
|
||||
{
|
||||
Progress.Local.Start(entry.Type);
|
||||
GetSchema(entry).AddValue(entry.Json);
|
||||
|
||||
if (_subclassSchemaTypes.Contains(entry.Type))
|
||||
{
|
||||
Schemas["_subclass"].AddValue(entry.Json);
|
||||
}
|
||||
|
||||
Progress.Local.End();
|
||||
}
|
||||
|
||||
Progress.Local.Complete();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сохранение постренных схем данных.
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
string targetDir = Settings.OutputDir;
|
||||
|
||||
targetDir = Path.Combine(targetDir, Loader.Importer.Slug);
|
||||
|
||||
foreach (KeyValuePair<string, SchemaNode> kvp in Schemas)
|
||||
{
|
||||
SaveSchema(targetDir, kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Список типов, являющихся подклассами.
|
||||
/// </summary>
|
||||
@@ -87,50 +130,6 @@ internal class AonprdSchemaBuilder(AonprdLoader loader)
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Построение схемы данных.
|
||||
/// </summary>
|
||||
public void BuildSchemas()
|
||||
{
|
||||
Console.WriteLine("Building schemas...");
|
||||
|
||||
ProgressBar bar = new(Loader.ItemCount);
|
||||
int i = 0;
|
||||
|
||||
foreach (AonprdLoader.LoaderEntry entry in Loader.Entries())
|
||||
{
|
||||
bar.Refresh(i++, entry.Type);
|
||||
GetSchema(entry).AddValue(entry.Json);
|
||||
|
||||
if (_subclassSchemaTypes.Contains(entry.Type))
|
||||
{
|
||||
Schemas["_subclass"].AddValue(entry.Json);
|
||||
}
|
||||
}
|
||||
|
||||
bar.Refresh(Loader.ItemCount, "Done!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сохранение постренных схем данных.
|
||||
/// </summary>
|
||||
/// <param name="targetDir">Целевой каталог.</param>
|
||||
public void Save(string targetDir)
|
||||
{
|
||||
Console.WriteLine("Dumping schemas...");
|
||||
|
||||
targetDir = Path.Combine(targetDir, Loader.Importer.Slug);
|
||||
|
||||
ProgressBar bar = new(Schemas.Count);
|
||||
int i = 0;
|
||||
|
||||
foreach (KeyValuePair<string, SchemaNode> kvp in Schemas)
|
||||
{
|
||||
bar.Refresh(i++, kvp.Key);
|
||||
SaveSchema(targetDir, kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сохранение отдельной схемы данных.
|
||||
/// </summary>
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Base.Targets;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
|
||||
|
||||
[Processor(
|
||||
"aonprd:external",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdPreparation
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:repository"])]
|
||||
internal class ExternalProcessor(Pf2eDbContext context) : AbstractProcessor
|
||||
{
|
||||
public Pf2eDbContext Context { get; } = context;
|
||||
|
||||
public ExternalTarget AonprdTarget = null!;
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
AonprdTarget = new()
|
||||
{
|
||||
Name = AonprdImporter.TargetName,
|
||||
Icon = "http://www.google.com/s2/favicons?domain=2e.aonprd.com",
|
||||
Prefix = "https://2e.aonprd.com",
|
||||
};
|
||||
}
|
||||
|
||||
public override void Save()
|
||||
{
|
||||
Context.ExternalTargets.Add(AonprdTarget);
|
||||
|
||||
// TODO
|
||||
// Globals.AonprdTarget = AonprdTarget;
|
||||
}
|
||||
}
|
||||
+14
-4
@@ -1,13 +1,23 @@
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Common;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
|
||||
|
||||
[AonprdProcessor("skill", [], false)]
|
||||
internal class SkillProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
||||
[Processor(
|
||||
"aonprd:skill",
|
||||
InnerType = "skill",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdPreparation
|
||||
)]
|
||||
internal class SkillProcessor(AonprdProcessorInput input, Pf2eDbContext context)
|
||||
: AbstractInputProcessor(input)
|
||||
{
|
||||
public Pf2eDbContext Context { get; } = context;
|
||||
|
||||
/// <summary>
|
||||
/// Обучаемый объект.
|
||||
/// </summary>
|
||||
+15
-4
@@ -1,12 +1,23 @@
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Base.Source;
|
||||
using Pf2eModel.Model.Enum;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
|
||||
|
||||
[AonprdProcessor("source", [], false)]
|
||||
internal class SourceProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
||||
[Processor(
|
||||
"aonprd:source",
|
||||
InnerType = "source",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdPreparation
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:repository"])]
|
||||
internal class SourceProcessor(AonprdProcessorInput input, Pf2eDbContext context)
|
||||
: AbstractInputProcessor(input)
|
||||
{
|
||||
public Pf2eDbContext Context { get; } = context;
|
||||
|
||||
/// <summary>
|
||||
/// Источник сущности.
|
||||
/// </summary>
|
||||
+22
-4
@@ -1,14 +1,32 @@
|
||||
using Pf2eModel;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Base;
|
||||
using Pf2eModel.Model.Common;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Subclasses;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Subclasses;
|
||||
|
||||
[AonprdProcessor("apparition", ["class", "spell", "skill"])]
|
||||
internal class ApparitionProcessor(AonprdProcessorInput input) : AbstractSubclassProcessor(input)
|
||||
[Processor(
|
||||
"aonprd:apparition",
|
||||
InnerType = "apparition",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdSubclasses
|
||||
)]
|
||||
[ProcessorDependencies(
|
||||
["aonprd:trait", "aonprd:source", "aonprd:class", "aonprd:spell", "aonprd:skill"]
|
||||
)]
|
||||
internal class ApparitionProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractSubclassProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override Subclass Object { get; } = new();
|
||||
+21
-4
@@ -1,9 +1,26 @@
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Enum;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||
|
||||
[AonprdProcessor("action")]
|
||||
internal class ActionProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
[Processor(
|
||||
"aonprd:action",
|
||||
InnerType = "action",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdEntities
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:trait", "aonprd:source"])]
|
||||
internal class ActionProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Action;
|
||||
+20
-3
@@ -1,11 +1,28 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||
|
||||
[AonprdProcessor("ancestry", ["trait", "source", "language"])]
|
||||
internal class AncestryProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
[Processor(
|
||||
"aonprd:ancestry",
|
||||
InnerType = "ancestry",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdEntities
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:language"])]
|
||||
internal class AncestryProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Ancestry;
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||
|
||||
[Processor(
|
||||
"aonprd:archetype",
|
||||
InnerType = "archetype",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdEntities
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:trait", "aonprd:source"])]
|
||||
internal class ArchetypeProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Archetype;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Archetype Object { get; } = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Add() => Context.Archetypes.Add(Object);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Process()
|
||||
{
|
||||
base.Process();
|
||||
|
||||
Object.Level = Input.GetOptional<int>("level");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string[] AddedDescriptionPaths() =>
|
||||
["prerequisite_markdown", "requirement_markdown", "summary_markdown"];
|
||||
}
|
||||
+20
-3
@@ -1,12 +1,29 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
using Pf2eModel.Model.Structure.BackgroundRelation;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||
|
||||
[AonprdProcessor("background")]
|
||||
internal class BackgroundProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
[Processor(
|
||||
"aonprd:background",
|
||||
InnerType = "background",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdEntities
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:trait", "aonprd:source"])]
|
||||
internal class BackgroundProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Background;
|
||||
+19
-3
@@ -1,5 +1,9 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Common;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
@@ -8,10 +12,22 @@ using Pf2eModel.Model.Structure;
|
||||
using Pf2eModel.Model.Structure.ClassRelation;
|
||||
using static System.Text.RegularExpressions.Regex;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||
|
||||
[AonprdProcessor("class", ["trait", "source", "skill"])]
|
||||
internal partial class ClassProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
[Processor(
|
||||
"aonprd:class",
|
||||
InnerType = "class",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdEntities
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:skill"])]
|
||||
internal partial class ClassProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Class;
|
||||
+19
-3
@@ -1,12 +1,28 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||
|
||||
[AonprdProcessor("feat", ["trait", "source", "archetype"])]
|
||||
internal class FeatProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
[Processor(
|
||||
"aonprd:feat",
|
||||
InnerType = "feat",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdEntities
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:archetype"])]
|
||||
internal class FeatProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Feat;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||
|
||||
[Processor(
|
||||
"aonprd:language",
|
||||
InnerType = "language",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdEntities
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:trait", "aonprd:source"])]
|
||||
internal class LanguageProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Language;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Language Object { get; } = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Add() => Context.Languages.Add(Object);
|
||||
}
|
||||
+18
-3
@@ -1,16 +1,31 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
using Pf2eModel.Model.Structure.RitualRelation;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||
|
||||
[AonprdProcessor("ritual", ["trait", "source", "skill"])]
|
||||
internal partial class RitualProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
[Processor(
|
||||
"aonprd:ritual",
|
||||
InnerType = "ritual",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdEntities
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:skill"])]
|
||||
internal partial class RitualProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Ritual;
|
||||
+20
-3
@@ -1,14 +1,31 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Base.Source;
|
||||
using Pf2eModel.Model.Base.Targets;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Rule = Pf2eModel.Model.Structure.Rule;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types.Rules;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types.Rules;
|
||||
|
||||
[AonprdProcessor("rules", ["rules-toc"])]
|
||||
internal class RuleProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
[Processor(
|
||||
"aonprd:rules",
|
||||
InnerType = "rules",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdEntities
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:rules-toc"])]
|
||||
internal class RuleProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Rule;
|
||||
+1
@@ -6,6 +6,7 @@
|
||||
// Ну а пока просто расставляем родительские и дочерние элементы.
|
||||
|
||||
using System.Data;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eModel.Model.Structure;
|
||||
using Rule = Pf2eModel.Model.Structure.Rule;
|
||||
+1
@@ -2,6 +2,7 @@
|
||||
using System.Web;
|
||||
using AngleSharp;
|
||||
using AngleSharp.Dom;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eModel.Model.Base.Source;
|
||||
|
||||
+20
-3
@@ -1,13 +1,30 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
using Pf2eModel.Model.Structure.SpellRelation;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||
|
||||
[AonprdProcessor("spell")]
|
||||
internal class SpellProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
[Processor(
|
||||
"aonprd:spell",
|
||||
InnerType = "spell",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdEntities
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:trait", "aonprd:source"])]
|
||||
internal class SpellProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Spell;
|
||||
@@ -0,0 +1,54 @@
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||
|
||||
[Processor(
|
||||
"aonprd:trait",
|
||||
InnerType = "trait",
|
||||
Description = "Создание цели внешних ссылок",
|
||||
Group = ProcessorGroupEnum.AonprdEntities
|
||||
)]
|
||||
[ProcessorDependencies(["aonprd:external"])]
|
||||
internal class TraitProcessor(
|
||||
AonprdProcessorInput input,
|
||||
Pf2eDbContext context,
|
||||
StringHelper stringHelper,
|
||||
DatabaseHelper helper,
|
||||
AonprdBuilderGlobals globals
|
||||
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override EntityType Type => EntityType.Trait;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Trait Object { get; } = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Add() => Context.Traits.Add(Object);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Process()
|
||||
{
|
||||
base.Process();
|
||||
|
||||
Object.Type = TraitType.Regular;
|
||||
|
||||
Context.Traits.Add(Object);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void AddTraits()
|
||||
{
|
||||
// Необходимо пропускать
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetDescription() =>
|
||||
base.GetDescription() + AddedDescription(["summary_markdown", "search_markdown"]);
|
||||
}
|
||||
+1
@@ -2,6 +2,7 @@
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.Helpers;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Pf2eDataScrapper.Importers.Repositories;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Класс абстрактного репозитория.
|
||||
@@ -22,5 +24,5 @@ internal abstract class AbstractImporterRepository(AbstractImporter importer)
|
||||
/// <summary>
|
||||
/// Обновление данных в репозитории.
|
||||
/// </summary>
|
||||
public abstract void Update();
|
||||
public abstract void Update(ProcessProgress progress);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using Pf2eDataScrapper.Processors;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Repositories;
|
||||
|
||||
@@ -16,11 +17,14 @@ internal class GitRepository(AbstractImporter importer, string url)
|
||||
public string Url { get; } = url;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Update()
|
||||
public override void Update(ProcessProgress progress)
|
||||
{
|
||||
progress.Local.Reset(1);
|
||||
|
||||
if (Directory.Exists(RepositoryDirPath))
|
||||
{
|
||||
// git pull
|
||||
progress.Local.Start("git pull");
|
||||
|
||||
Process process = new()
|
||||
{
|
||||
StartInfo = new()
|
||||
@@ -34,7 +38,8 @@ internal class GitRepository(AbstractImporter importer, string url)
|
||||
}
|
||||
else
|
||||
{
|
||||
// git clone
|
||||
progress.Local.Start("git clone");
|
||||
|
||||
Process process = new()
|
||||
{
|
||||
StartInfo = new()
|
||||
@@ -46,5 +51,7 @@ internal class GitRepository(AbstractImporter importer, string url)
|
||||
};
|
||||
process.Start();
|
||||
}
|
||||
|
||||
progress.Local.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,18 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eModel;
|
||||
using Pf2eDataScrapper.App;
|
||||
|
||||
namespace Pf2eDataScrapper.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса.
|
||||
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
||||
/// для которых указан атрибут <see cref="ProcessAttribute"/>.
|
||||
/// для которых указан атрибут <see cref="ProcessorAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">Провайдер сервисов.</param>
|
||||
/// <param name="input">Провайдер сервисов.</param>
|
||||
/// <seealso cref="ProcessAttribute"/>
|
||||
internal abstract class AbstractInputProcessor(
|
||||
IServiceProvider serviceProvider,
|
||||
ProcessorInput input
|
||||
) : IProcessor
|
||||
/// <param name="input">Входные данные обработчика.</param>
|
||||
/// <seealso cref="ProcessorAttribute"/>
|
||||
internal abstract class AbstractInputProcessor(ProcessorInput input) : IProcessor
|
||||
{
|
||||
/// <summary>
|
||||
/// Провайдер сервисов.
|
||||
/// </summary>
|
||||
public IServiceProvider ServiceProvider { get; } = serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Контекст базы данных.
|
||||
/// </summary>
|
||||
public Pf2eDbContext Context { get; } = serviceProvider.GetService<Pf2eDbContext>()!;
|
||||
|
||||
/// <summary>
|
||||
/// Ввод.
|
||||
/// Входные данные обработчика.
|
||||
/// </summary>
|
||||
public ProcessorInput Input { get; } = input;
|
||||
|
||||
|
||||
@@ -7,22 +7,11 @@ namespace Pf2eDataScrapper.Processors;
|
||||
/// <summary>
|
||||
/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса.
|
||||
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
||||
/// для которых указан атрибут <see cref="ProcessAttribute"/>.
|
||||
/// для которых указан атрибут <see cref="ProcessorAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">Провайдер сервисов.</param>
|
||||
/// <seealso cref="ProcessAttribute"/>
|
||||
internal abstract class AbstractProcessor(IServiceProvider serviceProvider) : IProcessor
|
||||
/// <seealso cref="ProcessorAttribute"/>
|
||||
internal abstract class AbstractProcessor : IProcessor
|
||||
{
|
||||
/// <summary>
|
||||
/// Провайдер сервисов.
|
||||
/// </summary>
|
||||
public IServiceProvider ServiceProvider { get; } = serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Контекст базы данных.
|
||||
/// </summary>
|
||||
public Pf2eDbContext Context { get; } = serviceProvider.GetService<Pf2eDbContext>()!;
|
||||
|
||||
/// <summary>
|
||||
/// Основной метод обработки данных.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Pf2eDataScrapper.App;
|
||||
using Pf2eModel;
|
||||
|
||||
namespace Pf2eDataScrapper.Processors;
|
||||
|
||||
[Processor("truncate", Description = "Отчистка таблиц БД", Group = ProcessorGroupEnum.General)]
|
||||
internal class DatabaseTruncateProcessor : IProcessor
|
||||
{
|
||||
public void Process()
|
||||
{
|
||||
using Pf2eDbContext context = new();
|
||||
string _ = context.Entities.Truncate() + "\n" + context.TruncateAll();
|
||||
}
|
||||
|
||||
public void Save() { }
|
||||
}
|
||||
@@ -1,14 +1,7 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Pf2eDataScrapper.Processors;
|
||||
namespace Pf2eDataScrapper.Processors;
|
||||
|
||||
public interface IProcessor
|
||||
{
|
||||
/// <summary>
|
||||
/// Провайдер сервисов.
|
||||
/// </summary>
|
||||
IServiceProvider ServiceProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Основной метод обработки данных.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
namespace Pf2eDataScrapper.Processors;
|
||||
|
||||
internal class ProcessProgress
|
||||
{
|
||||
/// <summary>
|
||||
/// Прогресс обработки обработчиков <see cref="IProcessor"/>.
|
||||
/// </summary>
|
||||
public ProgressItem Processors { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Прогресс работы конкретного обработчика <see cref="IProcessor"/>.
|
||||
/// </summary>
|
||||
public ProgressItem Local { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор класса <see cref="ProcessProgress"/>.
|
||||
/// </summary>
|
||||
public ProcessProgress()
|
||||
{
|
||||
Processors.Update += Update;
|
||||
Local.Update += Update;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Событие обновления
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
ProgressUpdate?.Invoke(this);
|
||||
}
|
||||
|
||||
public void Message(string message)
|
||||
{
|
||||
ProgressMessage?.Invoke(this, message);
|
||||
}
|
||||
|
||||
public delegate void ProgressUpdateDelegate(ProcessProgress sender);
|
||||
public event ProgressUpdateDelegate? ProgressUpdate;
|
||||
|
||||
public delegate void ProgressMessageDelegate(ProcessProgress sender, string message);
|
||||
public event ProgressMessageDelegate? ProgressMessage;
|
||||
|
||||
/// <summary>
|
||||
/// Класс прогресса.
|
||||
/// </summary>
|
||||
public class ProgressItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Количество обрабатываемых процессов.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get => _count;
|
||||
set
|
||||
{
|
||||
_count = value;
|
||||
Update?.Invoke();
|
||||
}
|
||||
}
|
||||
private int _count = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Индекс текущего обрабатываемого процесса.
|
||||
/// </summary>
|
||||
public int Current
|
||||
{
|
||||
get => _current;
|
||||
set
|
||||
{
|
||||
_current = value;
|
||||
Update?.Invoke();
|
||||
}
|
||||
}
|
||||
private int _current = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Название текущего обрабатываемого процесса.
|
||||
/// </summary>
|
||||
public string Text
|
||||
{
|
||||
get => _text;
|
||||
set
|
||||
{
|
||||
_text = value;
|
||||
Update?.Invoke();
|
||||
}
|
||||
}
|
||||
private string _text = "";
|
||||
|
||||
/// <summary>
|
||||
/// Значение прогресса.
|
||||
/// </summary>
|
||||
public double Percent => Count > 0 ? 1.0 * Current / Count : 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// Сброс прогресса до нуля и установка нового максимального значения.
|
||||
/// </summary>
|
||||
/// <param name="max"></param>
|
||||
public void Reset(int max = 0)
|
||||
{
|
||||
_count = max;
|
||||
_current = 0;
|
||||
_text = "";
|
||||
Update?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отмечает начало работы над процессом, описываемым строкой <paramref name="text"/>.
|
||||
/// </summary>
|
||||
/// <param name="text">Строка, описывающая процесс.</param>
|
||||
public void Start(string text)
|
||||
{
|
||||
_text = text;
|
||||
Update?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отмечает конец работы над процессом и увеличивает значение прогресса.
|
||||
/// </summary>
|
||||
public void End()
|
||||
{
|
||||
_text = "";
|
||||
_current++;
|
||||
Update?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отмечает прогресс завершённым.
|
||||
/// </summary>
|
||||
public void Complete()
|
||||
{
|
||||
_current = _count;
|
||||
_text = "Готово!";
|
||||
Update?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение строкового представления прогресса.
|
||||
/// </summary>
|
||||
/// <returns>Строковое представление прогресса.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Text} [{Current} / {Count}; {Percent:P}]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Делегат события обновления.
|
||||
/// </summary>
|
||||
public delegate void UpdateDelegate();
|
||||
|
||||
/// <summary>
|
||||
/// Событие обновление.
|
||||
/// </summary>
|
||||
public event UpdateDelegate? Update;
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,15 @@ namespace Pf2eDataScrapper.Processors;
|
||||
/// <summary>
|
||||
/// Класс для работы с JSON-объектом.
|
||||
/// </summary>
|
||||
/// <param name="name">Название объекта, ассоциированного с вводом.</param>
|
||||
/// <param name="input">JSON-объект, который будет использоваться для доступа к данным.</param>
|
||||
internal class ProcessorInput(JObject input)
|
||||
internal class ProcessorInput(string name, JObject input)
|
||||
{
|
||||
/// <summary>
|
||||
/// Название объекта, ассоциированного с вводом.
|
||||
/// </summary>
|
||||
public string Name { get; } = name;
|
||||
|
||||
/// <summary>
|
||||
/// Входящий JSON-объект, который содержит данные для обработки.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user