Продолжение работы над фундаментальным обновлением проекта (всё ещё без сборки)
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())
|
foreach (Type type in assembly.GetTypes())
|
||||||
{
|
{
|
||||||
if (type.GetCustomAttributes(typeof(ProcessAttribute), true).Length <= 0)
|
if (type.GetCustomAttributes(typeof(ProcessorAttribute), true).Length <= 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -51,21 +51,15 @@ internal class ProcessorCollection
|
|||||||
if (!type.IsSubclassOf(typeof(IProcessor)))
|
if (!type.IsSubclassOf(typeof(IProcessor)))
|
||||||
{
|
{
|
||||||
throw new(
|
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>()!;
|
ProcessorAttribute processorAttribute = type.GetCustomAttribute<ProcessorAttribute>()!;
|
||||||
DescriptionAttribute? descriptionAttribute =
|
|
||||||
type.GetCustomAttribute<DescriptionAttribute>();
|
|
||||||
ProcessorGroupAttribute? groupAttribute =
|
|
||||||
type.GetCustomAttribute<ProcessorGroupAttribute>();
|
|
||||||
ProcessorDependenciesAttribute? dependenciesAttribute =
|
ProcessorDependenciesAttribute? dependenciesAttribute =
|
||||||
type.GetCustomAttribute<ProcessorDependenciesAttribute>();
|
type.GetCustomAttribute<ProcessorDependenciesAttribute>();
|
||||||
ProcessorInnerTypeAttribute? innerTypeAttribute =
|
|
||||||
type.GetCustomAttribute<ProcessorInnerTypeAttribute>();
|
|
||||||
|
|
||||||
bool isCollection = innerTypeAttribute is not null;
|
bool isCollection = processorAttribute.InnerType is not null;
|
||||||
|
|
||||||
ConstructorInfo? constructor = isCollection
|
ConstructorInfo? constructor = isCollection
|
||||||
? type.GetConstructor([])
|
? type.GetConstructor([])
|
||||||
@@ -78,13 +72,13 @@ internal class ProcessorCollection
|
|||||||
|
|
||||||
return new()
|
return new()
|
||||||
{
|
{
|
||||||
Name = processAttribute.Name,
|
Name = processorAttribute.Name,
|
||||||
Type = type,
|
Type = type,
|
||||||
Description = descriptionAttribute?.Description ?? processAttribute.Name,
|
Description = processorAttribute.Description,
|
||||||
Group = groupAttribute?.Group ?? ProcessorGroupEnum.General,
|
Group = processorAttribute.Group,
|
||||||
Dependencies = dependenciesAttribute?.Dependencies ?? [],
|
Dependencies = dependenciesAttribute?.Dependencies ?? [],
|
||||||
IsCollectionProcessor = isCollection,
|
IsCollectionProcessor = isCollection,
|
||||||
InnerType = innerTypeAttribute?.InnerType,
|
InnerType = processorAttribute.InnerType,
|
||||||
Constructor = constructor,
|
Constructor = constructor,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-32
@@ -31,11 +31,11 @@ partial class StartForm
|
|||||||
MainSplitContainer = new SplitContainer();
|
MainSplitContainer = new SplitContainer();
|
||||||
PropertiesGroupBox = new GroupBox();
|
PropertiesGroupBox = new GroupBox();
|
||||||
SettingsPropertyGrid = new PropertyGrid();
|
SettingsPropertyGrid = new PropertyGrid();
|
||||||
StartButton = new Button();
|
|
||||||
ProcessorsGroupBox = new GroupBox();
|
ProcessorsGroupBox = new GroupBox();
|
||||||
DeselectAllButton = new Button();
|
|
||||||
SelectAllButton = new Button();
|
|
||||||
ProcessorsListView = new ListView();
|
ProcessorsListView = new ListView();
|
||||||
|
SelectAllButton = new Button();
|
||||||
|
DeselectAllButton = new Button();
|
||||||
|
StartButton = new Button();
|
||||||
((System.ComponentModel.ISupportInitialize)MainSplitContainer).BeginInit();
|
((System.ComponentModel.ISupportInitialize)MainSplitContainer).BeginInit();
|
||||||
MainSplitContainer.Panel1.SuspendLayout();
|
MainSplitContainer.Panel1.SuspendLayout();
|
||||||
MainSplitContainer.Panel2.SuspendLayout();
|
MainSplitContainer.Panel2.SuspendLayout();
|
||||||
@@ -84,17 +84,6 @@ partial class StartForm
|
|||||||
SettingsPropertyGrid.Size = new Size(288, 649);
|
SettingsPropertyGrid.Size = new Size(288, 649);
|
||||||
SettingsPropertyGrid.TabIndex = 0;
|
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
|
||||||
//
|
//
|
||||||
ProcessorsGroupBox.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
ProcessorsGroupBox.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
@@ -108,24 +97,6 @@ partial class StartForm
|
|||||||
ProcessorsGroupBox.TabStop = false;
|
ProcessorsGroupBox.TabStop = false;
|
||||||
ProcessorsGroupBox.Text = "Обработчики";
|
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
|
||||||
//
|
//
|
||||||
ProcessorsListView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
ProcessorsListView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
@@ -136,6 +107,35 @@ partial class StartForm
|
|||||||
ProcessorsListView.TabIndex = 2;
|
ProcessorsListView.TabIndex = 2;
|
||||||
ProcessorsListView.UseCompatibleStateImageBehavior = false;
|
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
|
// StartForm
|
||||||
//
|
//
|
||||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||||
@@ -144,6 +144,7 @@ partial class StartForm
|
|||||||
Controls.Add(MainSplitContainer);
|
Controls.Add(MainSplitContainer);
|
||||||
Name = "StartForm";
|
Name = "StartForm";
|
||||||
Text = "Настройки импорта данных";
|
Text = "Настройки импорта данных";
|
||||||
|
Load += StartForm_Load;
|
||||||
MainSplitContainer.Panel1.ResumeLayout(false);
|
MainSplitContainer.Panel1.ResumeLayout(false);
|
||||||
MainSplitContainer.Panel2.ResumeLayout(false);
|
MainSplitContainer.Panel2.ResumeLayout(false);
|
||||||
((System.ComponentModel.ISupportInitialize)MainSplitContainer).EndInit();
|
((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();
|
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 Pf2eModel;
|
||||||
using Slugify;
|
using Slugify;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers;
|
namespace Pf2eDataScrapper.Helpers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Класс предоставляет методы для работы с базой данных.
|
/// Класс предоставляет методы для работы с базой данных.
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Pf2eDataScrapper.App;
|
using Pf2eDataScrapper.App;
|
||||||
using Pf2eDataScrapper.Forms;
|
using Pf2eDataScrapper.Forms;
|
||||||
|
using Pf2eDataScrapper.Importers;
|
||||||
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
||||||
|
using Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry;
|
||||||
|
using Pf2eDataScrapper.Processors;
|
||||||
using Pf2eModel;
|
using Pf2eModel;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper;
|
namespace Pf2eDataScrapper;
|
||||||
@@ -15,23 +19,27 @@ internal sealed class ImportApplication : ApplicationContext
|
|||||||
|
|
||||||
#region "Внедрение зависимостей (DI)"
|
#region "Внедрение зависимостей (DI)"
|
||||||
|
|
||||||
public IServiceCollection Services = new ServiceCollection();
|
public readonly IServiceCollection Services = new ServiceCollection();
|
||||||
|
|
||||||
|
public IServiceProvider ServiceProvider { get; private set; } = null!;
|
||||||
|
|
||||||
private void InitializeServices()
|
private void InitializeServices()
|
||||||
{
|
{
|
||||||
Services.AddSingleton(this);
|
Services.AddSingleton(this);
|
||||||
Services.AddSingleton(Settings);
|
Services.AddSingleton(Settings);
|
||||||
|
Services.AddSingleton(Processors);
|
||||||
Services.AddSingleton<ProcessorCollection>();
|
|
||||||
|
|
||||||
Services.AddDbContext<Pf2eDbContext>();
|
Services.AddDbContext<Pf2eDbContext>();
|
||||||
|
|
||||||
|
ServiceProvider = Services.BuildServiceProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Настройки"
|
#region "Настройки"
|
||||||
|
|
||||||
public ApplicationSettings Settings = new();
|
public readonly ApplicationSettings Settings = new();
|
||||||
|
public readonly ProcessorCollection Processors = new();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -45,13 +53,73 @@ internal sealed class ImportApplication : ApplicationContext
|
|||||||
|
|
||||||
private void CreateStartForm()
|
private void CreateStartForm()
|
||||||
{
|
{
|
||||||
_startForm = new() { StartPosition = FormStartPosition.CenterParent };
|
_startForm = ActivatorUtilities.CreateInstance<StartForm>(ServiceProvider);
|
||||||
|
_startForm.StartPosition = FormStartPosition.CenterParent;
|
||||||
_startForm.Show();
|
_startForm.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartProcess()
|
private void StartProcess()
|
||||||
{
|
{
|
||||||
_startForm!.Close();
|
_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
|
#endregion
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Pf2eDataScrapper.Importers.Repositories;
|
using Pf2eDataScrapper.Importers.Repositories;
|
||||||
|
using Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers;
|
namespace Pf2eDataScrapper.Importers;
|
||||||
|
|
||||||
@@ -36,15 +37,32 @@ internal abstract class AbstractImporter
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Метод подготовки данных для импорта.
|
/// Метод подготовки данных для импорта.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete]
|
||||||
public abstract void Prepare();
|
public abstract void Prepare();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Импорт данных
|
/// Импорт данных
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete]
|
||||||
public abstract void Import();
|
public abstract void Import();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Построение схем данных.
|
/// Построение схем данных.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete]
|
||||||
public abstract void BuildSchemas();
|
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 Newtonsoft.Json.Linq;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.SchemaBuilder;
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
||||||
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||||
using Pf2eDataScrapper.Importers.Repositories;
|
using Pf2eDataScrapper.Importers.Repositories;
|
||||||
|
using Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
||||||
|
|
||||||
@@ -9,6 +11,11 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class AonprdImporter : AbstractImporter
|
internal class AonprdImporter : AbstractImporter
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Название внешней ссылки.
|
||||||
|
/// </summary>
|
||||||
|
public const string TargetName = "Archives of Nethys Pathfinder 2e";
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override string Name => TargetName;
|
public override string Name => TargetName;
|
||||||
|
|
||||||
@@ -16,8 +23,7 @@ internal class AonprdImporter : AbstractImporter
|
|||||||
public override string Slug => "aonprd";
|
public override string Slug => "aonprd";
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override AbstractImporterRepository Repository =>
|
public override AbstractImporterRepository Repository { get; }
|
||||||
new AonprdRepository(this, "https://elasticsearch.aonprd.com");
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Инструмент для работы с данными сайта Архивов Нефеса.
|
/// Инструмент для работы с данными сайта Архивов Нефеса.
|
||||||
@@ -29,37 +35,47 @@ internal class AonprdImporter : AbstractImporter
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public AonprdImporter()
|
public AonprdImporter()
|
||||||
{
|
{
|
||||||
|
Repository = new AonprdRepository(this, "https://elasticsearch.aonprd.com");
|
||||||
Loader = new(this);
|
Loader = new(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <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();
|
return Loader.Compendium.Count(type);
|
||||||
Loader.Prepare();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <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();
|
foreach (JToken item in array)
|
||||||
builder.Save(EnvSettings.OutputDir);
|
{
|
||||||
|
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 Newtonsoft.Json.Linq;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||||
using Pf2eDataScrapper.Processors;
|
using Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Класс для работы с JSON-объектом при обработки данных с Архивов Нефиса.
|
/// Класс для работы с JSON-объектом при обработки данных с Архивов Нефиса.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">JSON-объект, который будет использоваться для доступа к данным.</param>
|
/// <param name="input">JSON-объект, который будет использоваться для доступа к данным.</param>
|
||||||
internal class AonprdProcessorInput(JObject input) : ProcessorInput(input)
|
internal class AonprdProcessorInput(string name, JObject input) : ProcessorInput(name, input)
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override T Enum<T>(string value)
|
public override T Enum<T>(string value)
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Konsole;
|
using Konsole;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Pf2eDataScrapper.Importers.Repositories;
|
using Pf2eDataScrapper.Importers.Repositories;
|
||||||
|
using Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
||||||
|
|
||||||
@@ -38,18 +39,21 @@ internal class AonprdRepository(AbstractImporter importer, string searchUrl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Update()
|
public override void Update(ProcessProgress progress)
|
||||||
{
|
{
|
||||||
if (CheckRevision())
|
if (CheckRevision())
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Данные Aonprd актуальны, текущая ревизия {Revision}.");
|
progress.Local.Complete();
|
||||||
|
progress.Message($"Данные Aonprd актуальны, текущая ревизия {Revision}.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine(
|
progress.Message(
|
||||||
$"Данные Aonprd устарели, обновляем {RepositoryDirPath} до ревизии {Revision}..."
|
$"Данные Aonprd устарели, обновляем {RepositoryDirPath} до ревизии {Revision}..."
|
||||||
);
|
);
|
||||||
|
|
||||||
|
progress.Local.Reset(1);
|
||||||
|
|
||||||
if (Directory.Exists(RepositoryDirPath))
|
if (Directory.Exists(RepositoryDirPath))
|
||||||
{
|
{
|
||||||
Directory.Delete(RepositoryDirPath, true);
|
Directory.Delete(RepositoryDirPath, true);
|
||||||
@@ -58,27 +62,28 @@ internal class AonprdRepository(AbstractImporter importer, string searchUrl)
|
|||||||
|
|
||||||
WriteFile("revision.txt", Revision.ToString());
|
WriteFile("revision.txt", Revision.ToString());
|
||||||
|
|
||||||
Console.WriteLine("Загрузка индекса...");
|
progress.Local.Start("Загрузка индекса...");
|
||||||
|
|
||||||
string indexContent = Load($"/json-data/aon{Revision}-index.json");
|
string indexContent = Load($"/json-data/aon{Revision}-index.json");
|
||||||
WriteFile("index.json", indexContent);
|
WriteFile("index.json", indexContent);
|
||||||
|
|
||||||
JObject indexJson = JObject.Parse(indexContent);
|
JObject indexJson = JObject.Parse(indexContent);
|
||||||
|
|
||||||
Console.WriteLine("Загрузка индексных файлов...");
|
progress.Local.Reset(indexJson.Count + 1);
|
||||||
|
progress.Local.End();
|
||||||
ProgressBar bar = new(indexJson.Count);
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, JToken?> kvp in indexJson)
|
foreach (KeyValuePair<string, JToken?> kvp in indexJson)
|
||||||
{
|
{
|
||||||
string fileName = kvp.Key;
|
string fileName = kvp.Key;
|
||||||
bar.Refresh(i++, fileName);
|
progress.Local.Start(fileName);
|
||||||
|
|
||||||
string fileContent = Load($"/json-data/{fileName}.json");
|
string fileContent = Load($"/json-data/{fileName}.json");
|
||||||
WriteFile($"{fileName}.json", fileContent);
|
WriteFile($"{fileName}.json", fileContent);
|
||||||
|
|
||||||
|
progress.Local.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
bar.Refresh(indexJson.Count, "Готово!");
|
progress.Local.Complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -35,18 +35,32 @@ internal class AonprdCompendium
|
|||||||
/// <returns>Количество элементов.</returns>
|
/// <returns>Количество элементов.</returns>
|
||||||
public int Count() => Types.Values.Sum(t => t.Count);
|
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>
|
||||||
/// Возвращает количество элементов для указанных типов данных.
|
/// Возвращает количество элементов для указанных типов данных.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="types">Список типов.</param>
|
/// <param name="types">Список типов данных.</param>
|
||||||
/// <returns>Количество элементов.</returns>
|
/// <returns>Количество элементов.</returns>
|
||||||
public int Count(IEnumerable<string> types) =>
|
public int Count(IEnumerable<string> types) =>
|
||||||
Types.Values.Where(t => types.Contains(t.Type)).Sum(t => t.Count);
|
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>
|
||||||
/// Возвращает список файлов для выбора сущностей указанных типов данных.
|
/// Возвращает список файлов для выбора сущностей указанных типов данных.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="types">Список типов.</param>
|
/// <param name="types">Список типов данных.</param>
|
||||||
/// <returns>Список искомых файлов.</returns>
|
/// <returns>Список искомых файлов.</returns>
|
||||||
public IEnumerable<string> Files(IEnumerable<string> types) =>
|
public IEnumerable<string> Files(IEnumerable<string> types) =>
|
||||||
Types.Values.Where(t => types.Contains(t.Type)).SelectMany(t => t.Files).Distinct();
|
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>
|
||||||
/// Определение типа сущности как префикса идентификатора.
|
/// Определение типа сущности как префикса идентификатора.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static string ResolveType(string id)
|
public static string ResolveType(string id)
|
||||||
{
|
{
|
||||||
string type = string.Join('-', id.Split('-')[..^1]);
|
string type = string.Join('-', id.Split('-')[..^1]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Класс AonprdType представляет собой уникальный тип данных, связанный с Aon (Advanced Opportunity Network).
|
/// Класс типа элементов с Архива Нефиса.
|
||||||
/// Это основной класс, который хранит информацию о различных элементах системы.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class AonprdType(string type)
|
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;
|
using Pf2eModel.Model.Base.Targets;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Класс-помощник, хранящий необходимые глобальные данные.
|
/// Класс-помощник, хранящий необходимые глобальные данные.
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Класс, помогающий разрешить строковые значения с Архивов Нефиса в перечисления.
|
/// Класс, помогающий разрешить строковые значения с Архивов Нефиса в перечисления.
|
||||||
+2
-1
@@ -1,9 +1,10 @@
|
|||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
||||||
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors;
|
||||||
using Pf2eModel.Model.Base;
|
using Pf2eModel.Model.Base;
|
||||||
using Pf2eModel.Model.Base.Source;
|
using Pf2eModel.Model.Base.Source;
|
||||||
using Pf2eModel.Model.Common.I18n;
|
using Pf2eModel.Model.Common.I18n;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обработчик сущностей, помеченных как устаревшие.
|
/// Обработчик сущностей, помеченных как устаревшие.
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
using Pf2eModel.Model.Base.Source;
|
using Pf2eModel.Model.Base.Source;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types.Rules;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Класс коллекции книг, содержащих правила.
|
/// Класс коллекции книг, содержащих правила.
|
||||||
+19
-5
@@ -3,6 +3,10 @@ using System.Text;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
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 Pf2eDataScrapper.Processors;
|
||||||
using Pf2eModel;
|
using Pf2eModel;
|
||||||
using Pf2eModel.Model;
|
using Pf2eModel.Model;
|
||||||
@@ -13,18 +17,28 @@ using Pf2eModel.Model.Common.I18n;
|
|||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
using Pf2eModel.Model.Structure;
|
using Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Абстрактный класс-обработчик сущностей, полученных из Архивов Нефиса.
|
/// Абстрактный класс-обработчик сущностей, полученных из Архивов Нефиса.
|
||||||
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
||||||
/// для которых указан атрибут <see cref="AonprdProcessorAttribute"/>.
|
/// для которых указан атрибут <see cref="ProcessorAttribute"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">Объект обработки вводимого JSON.</param>
|
/// <param name="input">Объект обработки вводимого JSON.</param>
|
||||||
/// <seealso cref="AonprdProcessorAttribute"/>
|
/// <seealso cref="ProcessorAttribute"/>
|
||||||
internal abstract class AbstractEntityProcessor(AonprdProcessorInput input)
|
internal abstract class AbstractEntityProcessor(
|
||||||
: AbstractProcessor(input)
|
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>
|
||||||
/// Корневая сущность.
|
/// Корневая сущность.
|
||||||
/// </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.Base;
|
||||||
using Pf2eModel.Model.Common.I18n;
|
using Pf2eModel.Model.Common.I18n;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
using Pf2eModel.Model.Structure;
|
using Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Абстрактный класс-обработчик сущностей подклассов, полученных из Архивов Нефиса.
|
/// Абстрактный класс-обработчик сущностей подклассов, полученных из Архивов Нефиса.
|
||||||
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
||||||
/// для которых указан атрибут <see cref="AonprdProcessorAttribute"/>.
|
/// для которых указан атрибут <see cref="ProcessorAttribute"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">Объект обработки вводимого JSON.</param>
|
internal abstract class AbstractSubclassProcessor(
|
||||||
/// <seealso cref="AonprdProcessorAttribute"/>
|
AonprdProcessorInput input,
|
||||||
internal abstract class AbstractSubclassProcessor(AonprdProcessorInput input)
|
Pf2eDbContext context,
|
||||||
: AbstractEntityProcessor(input)
|
StringHelper stringHelper,
|
||||||
|
DatabaseHelper helper,
|
||||||
|
AonprdBuilderGlobals globals
|
||||||
|
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals)
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override EntityType Type => EntityType.Subclass;
|
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.App;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
using Pf2eDataScrapper.Processors;
|
||||||
using Pf2eDataScrapper.SchemaBuilder;
|
using Pf2eDataScrapper.SchemaBuilder;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.SchemaBuilder;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
|
||||||
|
|
||||||
/// <summary>
|
[Processor(
|
||||||
/// Класс создания схемы данных с сайта Архивов Нефеса.
|
"aonprd:schema",
|
||||||
/// </summary>
|
Description = "Построение схемы данных",
|
||||||
/// <param name="loader">Загузчик данных с сайта Архивов Нефеса.</param>
|
Group = ProcessorGroupEnum.AonprdPreparation
|
||||||
internal class AonprdSchemaBuilder(AonprdLoader loader)
|
)]
|
||||||
|
[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>
|
||||||
/// Загузчик данных с сайта Архивов Нефеса.
|
/// Загузчик данных с сайта Архивов Нефеса.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly AonprdLoader Loader = loader;
|
public AonprdLoader Loader => Importer.Loader;
|
||||||
|
|
||||||
/// <inheritdoc cref="AonprdLoader.Compendium"/>
|
|
||||||
public readonly AonprdCompendium Compendium = loader.Compendium;
|
|
||||||
|
|
||||||
// public readonly AonprdSchemaTypeResolver Resolver = new();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Дополнительные схемы данных.
|
/// Дополнительные схемы данных.
|
||||||
@@ -28,6 +33,44 @@ internal class AonprdSchemaBuilder(AonprdLoader loader)
|
|||||||
["_subclass"] = new() { Path = "_subclass" },
|
["_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>
|
||||||
/// Список типов, являющихся подклассами.
|
/// Список типов, являющихся подклассами.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -87,50 +130,6 @@ internal class AonprdSchemaBuilder(AonprdLoader loader)
|
|||||||
return value;
|
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>
|
||||||
/// Сохранение отдельной схемы данных.
|
/// Сохранение отдельной схемы данных.
|
||||||
/// </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;
|
||||||
using Pf2eModel.Model.Common.I18n;
|
using Pf2eModel.Model.Common.I18n;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
|
||||||
|
|
||||||
[AonprdProcessor("skill", [], false)]
|
[Processor(
|
||||||
internal class SkillProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
"aonprd:skill",
|
||||||
|
InnerType = "skill",
|
||||||
|
Description = "Создание цели внешних ссылок",
|
||||||
|
Group = ProcessorGroupEnum.AonprdPreparation
|
||||||
|
)]
|
||||||
|
internal class SkillProcessor(AonprdProcessorInput input, Pf2eDbContext context)
|
||||||
|
: AbstractInputProcessor(input)
|
||||||
{
|
{
|
||||||
|
public Pf2eDbContext Context { get; } = context;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обучаемый объект.
|
/// Обучаемый объект.
|
||||||
/// </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.Base.Source;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
|
||||||
|
|
||||||
[AonprdProcessor("source", [], false)]
|
[Processor(
|
||||||
internal class SourceProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
"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>
|
||||||
/// Источник сущности.
|
/// Источник сущности.
|
||||||
/// </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.Base;
|
||||||
using Pf2eModel.Model.Common;
|
using Pf2eModel.Model.Common;
|
||||||
using Pf2eModel.Model.Common.I18n;
|
using Pf2eModel.Model.Common.I18n;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
using Pf2eModel.Model.Structure;
|
using Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Subclasses;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Subclasses;
|
||||||
|
|
||||||
[AonprdProcessor("apparition", ["class", "spell", "skill"])]
|
[Processor(
|
||||||
internal class ApparitionProcessor(AonprdProcessorInput input) : AbstractSubclassProcessor(input)
|
"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/>
|
/// <inheritdoc/>
|
||||||
public override Subclass Object { get; } = new();
|
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")]
|
[Processor(
|
||||||
internal class ActionProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
"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/>
|
/// <inheritdoc/>
|
||||||
public override EntityType Type => EntityType.Action;
|
public override EntityType Type => EntityType.Action;
|
||||||
+20
-3
@@ -1,11 +1,28 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
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.Enum;
|
||||||
using Pf2eModel.Model.Structure;
|
using Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||||
|
|
||||||
[AonprdProcessor("ancestry", ["trait", "source", "language"])]
|
[Processor(
|
||||||
internal class AncestryProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
"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/>
|
/// <inheritdoc/>
|
||||||
public override EntityType Type => EntityType.Ancestry;
|
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 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.Enum;
|
||||||
using Pf2eModel.Model.Structure;
|
using Pf2eModel.Model.Structure;
|
||||||
using Pf2eModel.Model.Structure.BackgroundRelation;
|
using Pf2eModel.Model.Structure.BackgroundRelation;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||||
|
|
||||||
[AonprdProcessor("background")]
|
[Processor(
|
||||||
internal class BackgroundProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
"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/>
|
/// <inheritdoc/>
|
||||||
public override EntityType Type => EntityType.Background;
|
public override EntityType Type => EntityType.Background;
|
||||||
+19
-3
@@ -1,5 +1,9 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Newtonsoft.Json.Linq;
|
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;
|
||||||
using Pf2eModel.Model.Common;
|
using Pf2eModel.Model.Common;
|
||||||
using Pf2eModel.Model.Common.I18n;
|
using Pf2eModel.Model.Common.I18n;
|
||||||
@@ -8,10 +12,22 @@ using Pf2eModel.Model.Structure;
|
|||||||
using Pf2eModel.Model.Structure.ClassRelation;
|
using Pf2eModel.Model.Structure.ClassRelation;
|
||||||
using static System.Text.RegularExpressions.Regex;
|
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"])]
|
[Processor(
|
||||||
internal partial class ClassProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
"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/>
|
/// <inheritdoc/>
|
||||||
public override EntityType Type => EntityType.Class;
|
public override EntityType Type => EntityType.Class;
|
||||||
+19
-3
@@ -1,12 +1,28 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
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;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
using Pf2eModel.Model.Structure;
|
using Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||||
|
|
||||||
[AonprdProcessor("feat", ["trait", "source", "archetype"])]
|
[Processor(
|
||||||
internal class FeatProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
"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/>
|
/// <inheritdoc/>
|
||||||
public override EntityType Type => EntityType.Feat;
|
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 System.Text.RegularExpressions;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Pf2eDataScrapper.App;
|
||||||
|
using Pf2eDataScrapper.Helpers;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||||
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||||
using Pf2eModel;
|
using Pf2eModel;
|
||||||
using Pf2eModel.Model.Common.I18n;
|
using Pf2eModel.Model.Common.I18n;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
using Pf2eModel.Model.Structure;
|
using Pf2eModel.Model.Structure;
|
||||||
using Pf2eModel.Model.Structure.RitualRelation;
|
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"])]
|
[Processor(
|
||||||
internal partial class RitualProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
"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/>
|
/// <inheritdoc/>
|
||||||
public override EntityType Type => EntityType.Ritual;
|
public override EntityType Type => EntityType.Ritual;
|
||||||
+20
-3
@@ -1,14 +1,31 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
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.Source;
|
||||||
using Pf2eModel.Model.Base.Targets;
|
using Pf2eModel.Model.Base.Targets;
|
||||||
using Pf2eModel.Model.Common.I18n;
|
using Pf2eModel.Model.Common.I18n;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
using Rule = Pf2eModel.Model.Structure.Rule;
|
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"])]
|
[Processor(
|
||||||
internal class RuleProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
"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/>
|
/// <inheritdoc/>
|
||||||
public override EntityType Type => EntityType.Rule;
|
public override EntityType Type => EntityType.Rule;
|
||||||
+1
@@ -6,6 +6,7 @@
|
|||||||
// Ну а пока просто расставляем родительские и дочерние элементы.
|
// Ну а пока просто расставляем родительские и дочерние элементы.
|
||||||
|
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||||
using Pf2eDataScrapper.Processors;
|
using Pf2eDataScrapper.Processors;
|
||||||
using Pf2eModel.Model.Structure;
|
using Pf2eModel.Model.Structure;
|
||||||
using Rule = Pf2eModel.Model.Structure.Rule;
|
using Rule = Pf2eModel.Model.Structure.Rule;
|
||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
using System.Web;
|
using System.Web;
|
||||||
using AngleSharp;
|
using AngleSharp;
|
||||||
using AngleSharp.Dom;
|
using AngleSharp.Dom;
|
||||||
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
|
||||||
using Pf2eDataScrapper.Processors;
|
using Pf2eDataScrapper.Processors;
|
||||||
using Pf2eModel.Model.Base.Source;
|
using Pf2eModel.Model.Base.Source;
|
||||||
|
|
||||||
+20
-3
@@ -1,13 +1,30 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
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.Common.I18n;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
using Pf2eModel.Model.Structure;
|
using Pf2eModel.Model.Structure;
|
||||||
using Pf2eModel.Model.Structure.SpellRelation;
|
using Pf2eModel.Model.Structure.SpellRelation;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
|
||||||
|
|
||||||
[AonprdProcessor("spell")]
|
[Processor(
|
||||||
internal class SpellProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
"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/>
|
/// <inheritdoc/>
|
||||||
public override EntityType Type => EntityType.Spell;
|
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 System.Text;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Pf2eDataScrapper.Helpers;
|
||||||
using Pf2eDataScrapper.Processors;
|
using Pf2eDataScrapper.Processors;
|
||||||
using Pf2eModel;
|
using Pf2eModel;
|
||||||
using Pf2eModel.Model;
|
using Pf2eModel.Model;
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace Pf2eDataScrapper.Importers.Repositories;
|
using Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper.Importers.Repositories;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Класс абстрактного репозитория.
|
/// Класс абстрактного репозитория.
|
||||||
@@ -22,5 +24,5 @@ internal abstract class AbstractImporterRepository(AbstractImporter importer)
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обновление данных в репозитории.
|
/// Обновление данных в репозитории.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract void Update();
|
public abstract void Update(ProcessProgress progress);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Repositories;
|
namespace Pf2eDataScrapper.Importers.Repositories;
|
||||||
|
|
||||||
@@ -16,11 +17,14 @@ internal class GitRepository(AbstractImporter importer, string url)
|
|||||||
public string Url { get; } = url;
|
public string Url { get; } = url;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Update()
|
public override void Update(ProcessProgress progress)
|
||||||
{
|
{
|
||||||
|
progress.Local.Reset(1);
|
||||||
|
|
||||||
if (Directory.Exists(RepositoryDirPath))
|
if (Directory.Exists(RepositoryDirPath))
|
||||||
{
|
{
|
||||||
// git pull
|
progress.Local.Start("git pull");
|
||||||
|
|
||||||
Process process = new()
|
Process process = new()
|
||||||
{
|
{
|
||||||
StartInfo = new()
|
StartInfo = new()
|
||||||
@@ -34,7 +38,8 @@ internal class GitRepository(AbstractImporter importer, string url)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// git clone
|
progress.Local.Start("git clone");
|
||||||
|
|
||||||
Process process = new()
|
Process process = new()
|
||||||
{
|
{
|
||||||
StartInfo = new()
|
StartInfo = new()
|
||||||
@@ -46,5 +51,7 @@ internal class GitRepository(AbstractImporter importer, string url)
|
|||||||
};
|
};
|
||||||
process.Start();
|
process.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progress.Local.Complete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,18 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Pf2eDataScrapper.App;
|
||||||
using Pf2eDataScrapper.App;
|
|
||||||
using Pf2eModel;
|
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Processors;
|
namespace Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса.
|
/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса.
|
||||||
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
||||||
/// для которых указан атрибут <see cref="ProcessAttribute"/>.
|
/// для которых указан атрибут <see cref="ProcessorAttribute"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="serviceProvider">Провайдер сервисов.</param>
|
/// <param name="input">Входные данные обработчика.</param>
|
||||||
/// <param name="input">Провайдер сервисов.</param>
|
/// <seealso cref="ProcessorAttribute"/>
|
||||||
/// <seealso cref="ProcessAttribute"/>
|
internal abstract class AbstractInputProcessor(ProcessorInput input) : IProcessor
|
||||||
internal abstract class AbstractInputProcessor(
|
|
||||||
IServiceProvider serviceProvider,
|
|
||||||
ProcessorInput input
|
|
||||||
) : IProcessor
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Провайдер сервисов.
|
/// Входные данные обработчика.
|
||||||
/// </summary>
|
|
||||||
public IServiceProvider ServiceProvider { get; } = serviceProvider;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Контекст базы данных.
|
|
||||||
/// </summary>
|
|
||||||
public Pf2eDbContext Context { get; } = serviceProvider.GetService<Pf2eDbContext>()!;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Ввод.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ProcessorInput Input { get; } = input;
|
public ProcessorInput Input { get; } = input;
|
||||||
|
|
||||||
|
|||||||
@@ -7,22 +7,11 @@ namespace Pf2eDataScrapper.Processors;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса.
|
/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса.
|
||||||
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
||||||
/// для которых указан атрибут <see cref="ProcessAttribute"/>.
|
/// для которых указан атрибут <see cref="ProcessorAttribute"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="serviceProvider">Провайдер сервисов.</param>
|
/// <seealso cref="ProcessorAttribute"/>
|
||||||
/// <seealso cref="ProcessAttribute"/>
|
internal abstract class AbstractProcessor : IProcessor
|
||||||
internal abstract class AbstractProcessor(IServiceProvider serviceProvider) : IProcessor
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Провайдер сервисов.
|
|
||||||
/// </summary>
|
|
||||||
public IServiceProvider ServiceProvider { get; } = serviceProvider;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Контекст базы данных.
|
|
||||||
/// </summary>
|
|
||||||
public Pf2eDbContext Context { get; } = serviceProvider.GetService<Pf2eDbContext>()!;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Основной метод обработки данных.
|
/// Основной метод обработки данных.
|
||||||
/// </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
|
public interface IProcessor
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Провайдер сервисов.
|
|
||||||
/// </summary>
|
|
||||||
IServiceProvider ServiceProvider { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Основной метод обработки данных.
|
/// Основной метод обработки данных.
|
||||||
/// </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>
|
/// <summary>
|
||||||
/// Класс для работы с JSON-объектом.
|
/// Класс для работы с JSON-объектом.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="name">Название объекта, ассоциированного с вводом.</param>
|
||||||
/// <param name="input">JSON-объект, который будет использоваться для доступа к данным.</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>
|
/// <summary>
|
||||||
/// Входящий JSON-объект, который содержит данные для обработки.
|
/// Входящий JSON-объект, который содержит данные для обработки.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user