Глобальное обновление #1
@@ -0,0 +1,62 @@
|
|||||||
|
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,229 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using System.Reflection;
|
||||||
|
using Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper.App;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Класс с коллекцией обработчиков.
|
||||||
|
/// </summary>
|
||||||
|
internal class ProcessorCollection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Коллекция всех доступных обработчиков.
|
||||||
|
/// </summary>
|
||||||
|
public ICollection<ProcessorCollectionItem> AllItems { get; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Коллекция обработчиков, которые будут обрабатываться.
|
||||||
|
/// Для изменения необходимо использовать <see cref="FilterProcessors"/>.
|
||||||
|
/// </summary>
|
||||||
|
public List<ProcessorCollectionItem> Items { get; private set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Конструктор класса <see cref="ProcessorCollection"/>.
|
||||||
|
/// </summary>
|
||||||
|
public ProcessorCollection()
|
||||||
|
{
|
||||||
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||||
|
|
||||||
|
foreach (Type type in assembly.GetTypes())
|
||||||
|
{
|
||||||
|
if (type.GetCustomAttributes(typeof(ProcessAttribute), true).Length <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AllItems.Add(CreateItem(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckDependencies();
|
||||||
|
FilterProcessors([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Создание элемента коллекции обработчиков.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">Тип обработчика.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private ProcessorCollectionItem CreateItem(Type type)
|
||||||
|
{
|
||||||
|
if (!type.IsSubclassOf(typeof(IProcessor)))
|
||||||
|
{
|
||||||
|
throw new(
|
||||||
|
$"'ProcessAttribute' attribute should only be applied to children of 'IProcessor' class. '{type.FullName}' is not."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessAttribute processAttribute = type.GetCustomAttribute<ProcessAttribute>()!;
|
||||||
|
DescriptionAttribute? descriptionAttribute =
|
||||||
|
type.GetCustomAttribute<DescriptionAttribute>();
|
||||||
|
ProcessorGroupAttribute? groupAttribute =
|
||||||
|
type.GetCustomAttribute<ProcessorGroupAttribute>();
|
||||||
|
ProcessorDependenciesAttribute? dependenciesAttribute =
|
||||||
|
type.GetCustomAttribute<ProcessorDependenciesAttribute>();
|
||||||
|
ProcessorInnerTypeAttribute? innerTypeAttribute =
|
||||||
|
type.GetCustomAttribute<ProcessorInnerTypeAttribute>();
|
||||||
|
|
||||||
|
bool isCollection = innerTypeAttribute is not null;
|
||||||
|
|
||||||
|
ConstructorInfo? constructor = isCollection
|
||||||
|
? type.GetConstructor([])
|
||||||
|
: type.GetConstructor([typeof(ProcessorInput)])!;
|
||||||
|
|
||||||
|
if (constructor is null)
|
||||||
|
{
|
||||||
|
throw new($"Не удаётся определить конструктор класса {type}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
Name = processAttribute.Name,
|
||||||
|
Type = type,
|
||||||
|
Description = descriptionAttribute?.Description ?? processAttribute.Name,
|
||||||
|
Group = groupAttribute?.Group ?? ProcessorGroupEnum.General,
|
||||||
|
Dependencies = dependenciesAttribute?.Dependencies ?? [],
|
||||||
|
IsCollectionProcessor = isCollection,
|
||||||
|
InnerType = innerTypeAttribute?.InnerType,
|
||||||
|
Constructor = constructor,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Проверка, что все зависимости всех обработчиков могут быть удовлетворены.
|
||||||
|
/// </summary>
|
||||||
|
private void CheckDependencies()
|
||||||
|
{
|
||||||
|
foreach (ProcessorCollectionItem item in Items)
|
||||||
|
{
|
||||||
|
foreach (string dependency in item.Dependencies)
|
||||||
|
{
|
||||||
|
if (Items.All(i => i.Name != dependency))
|
||||||
|
{
|
||||||
|
throw new($"Dependency '{dependency}' for processor '{item.Name}' not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Сортировать обработчики в соответсвии со всеми зависимостями.
|
||||||
|
/// </summary>
|
||||||
|
public void SortItems()
|
||||||
|
{
|
||||||
|
Dictionary<string, int> priorities = [];
|
||||||
|
|
||||||
|
while (priorities.Count < Items.Count)
|
||||||
|
{
|
||||||
|
foreach (ProcessorCollectionItem item in Items)
|
||||||
|
{
|
||||||
|
if (item.Priority > 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<int> dependencyPriorities = item.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.Name, item.Priority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Items.Sort((a, b) => a.Priority - b.Priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ограничить список используемых обработчиков по названию.
|
||||||
|
/// Автоматически включает все обработчики, от которых зависят указанные в аргументе обработчики.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="processorNames">Коллекция названиий требуемых обработчиков.</param>
|
||||||
|
public void FilterProcessors(ICollection<string> processorNames)
|
||||||
|
{
|
||||||
|
if (processorNames.Count == 0)
|
||||||
|
{
|
||||||
|
Items = [.. AllItems];
|
||||||
|
SortItems();
|
||||||
|
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()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ProcessorCollectionItem item = AllItems.First(item => item.Name == pair.Key);
|
||||||
|
|
||||||
|
foreach (string dependency in item.Dependencies)
|
||||||
|
{
|
||||||
|
nameFlags.TryAdd(dependency, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
nameFlags[pair.Key] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Items = AllItems.Where(item => nameFlags.ContainsKey(item.Name)).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Элемент коллекции обработчиков.
|
||||||
|
/// </summary>
|
||||||
|
internal class ProcessorCollectionItem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Название обработчика.
|
||||||
|
/// </summary>
|
||||||
|
public required string Name { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Тип класса обработчика.
|
||||||
|
/// </summary>
|
||||||
|
public required Type Type { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Описание обработчика.
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; init; } = "";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Группа обработчика.
|
||||||
|
/// </summary>
|
||||||
|
public required ProcessorGroupEnum Group { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Коллекция названий обработчиков, после которых должен выполняться обработчик.
|
||||||
|
/// </summary>
|
||||||
|
public ICollection<string> Dependencies { get; init; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Приоритет выполнения обработчика.
|
||||||
|
/// </summary>
|
||||||
|
public int Priority { get; set; } = -1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Флаг, указывающий, обрабатывает ли обработчик коллекцию элементов.
|
||||||
|
/// Внутренний тип элементов указывается в <see cref="InnerType"/>.
|
||||||
|
/// </summary>
|
||||||
|
public required bool IsCollectionProcessor { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Флаг, указывающий внутренний тип коллекции обрабатываемых элементов.
|
||||||
|
/// </summary>
|
||||||
|
public string? InnerType { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Конструктор обработчика.
|
||||||
|
/// </summary>
|
||||||
|
public required ConstructorInfo Constructor { get; init; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper.App;
|
||||||
|
|
||||||
|
public enum ProcessorGroupEnum
|
||||||
|
{
|
||||||
|
[Description("Общие процессоры")]
|
||||||
|
General,
|
||||||
|
|
||||||
|
[Description("Архивы Нефиса: Подготовка")]
|
||||||
|
AonprdPreparation,
|
||||||
|
|
||||||
|
[Description("Архивы Нефиса: Основные сущности")]
|
||||||
|
AonprdEntities,
|
||||||
|
|
||||||
|
[Description("Архивы Нефиса: Подклассы")]
|
||||||
|
AonprdSubclasses,
|
||||||
|
|
||||||
|
[Description("Foundry EN: Подготовка")]
|
||||||
|
FoundryEnPreparation,
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using dotenv.net;
|
||||||
|
using dotenv.net.Utilities;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Настройки программы.
|
||||||
|
/// </summary>
|
||||||
|
internal class ApplicationSettings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Конструктор класса <see cref="ApplicationSettings"/>.
|
||||||
|
/// </summary>
|
||||||
|
public ApplicationSettings()
|
||||||
|
{
|
||||||
|
DotEnv.Load();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Настройки из .env
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Путь к папке с входными данными.
|
||||||
|
/// </summary>
|
||||||
|
[Browsable(true)]
|
||||||
|
[ReadOnly(true)]
|
||||||
|
[DisplayName("Путь к папке с входными данными.")]
|
||||||
|
[Description("Редактирование через .env-файл.")]
|
||||||
|
public string DataDirPath { get; } = EnvReader.GetStringValue("DATA_DIR");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Папка в входными данными.
|
||||||
|
/// </summary>
|
||||||
|
[Browsable(false)]
|
||||||
|
public DirectoryInfo DataDir => new(DataDirPath);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Путь к папке для сохранения результатов.
|
||||||
|
/// </summary>
|
||||||
|
[Browsable(true)]
|
||||||
|
[ReadOnly(true)]
|
||||||
|
[DisplayName("Путь к папке для сохранения результатов.")]
|
||||||
|
[Description("Редактирование через .env-файл.")]
|
||||||
|
public string OutputDirPath { get; } = EnvReader.GetStringValue("OUTPUT_DIR");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Папка для сохранения результатов.
|
||||||
|
/// </summary>
|
||||||
|
[Browsable(false)]
|
||||||
|
public string OutputDir => new(OutputDirPath);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Строка подключения к базе данных.
|
||||||
|
/// </summary>
|
||||||
|
[Browsable(true)]
|
||||||
|
[ReadOnly(true)]
|
||||||
|
[DisplayName("Строка подключения к базе данных.")]
|
||||||
|
[Description("Редактирование через .env-файл.")]
|
||||||
|
public string DatabaseConnection { get; } = EnvReader.GetStringValue("DATABASE_CONNECTION");
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Основные настройки
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Флаг, указывающий, что все старые записи необходимо удалить.
|
||||||
|
/// </summary>
|
||||||
|
[Browsable(true)]
|
||||||
|
[DisplayName("Удаление всех записей перед запуском.")]
|
||||||
|
[Description("Редактирование через .env-файл.")]
|
||||||
|
public bool TruncateAllTables { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Список обработчиков, которые должны быть выполнены.
|
||||||
|
/// Пустой список означает, что должны быть выполнены все обработчики.
|
||||||
|
/// </summary>
|
||||||
|
public ICollection<string> ProcessorNames { get; } = new List<string>();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
+166
@@ -0,0 +1,166 @@
|
|||||||
|
namespace Pf2eDataScrapper.Forms;
|
||||||
|
|
||||||
|
partial class StartForm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
MainSplitContainer = new SplitContainer();
|
||||||
|
PropertiesGroupBox = new GroupBox();
|
||||||
|
SettingsPropertyGrid = new PropertyGrid();
|
||||||
|
StartButton = new Button();
|
||||||
|
ProcessorsGroupBox = new GroupBox();
|
||||||
|
DeselectAllButton = new Button();
|
||||||
|
SelectAllButton = new Button();
|
||||||
|
ProcessorsListView = new ListView();
|
||||||
|
((System.ComponentModel.ISupportInitialize)MainSplitContainer).BeginInit();
|
||||||
|
MainSplitContainer.Panel1.SuspendLayout();
|
||||||
|
MainSplitContainer.Panel2.SuspendLayout();
|
||||||
|
MainSplitContainer.SuspendLayout();
|
||||||
|
PropertiesGroupBox.SuspendLayout();
|
||||||
|
ProcessorsGroupBox.SuspendLayout();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// MainSplitContainer
|
||||||
|
//
|
||||||
|
MainSplitContainer.Dock = DockStyle.Fill;
|
||||||
|
MainSplitContainer.Location = new Point(0, 0);
|
||||||
|
MainSplitContainer.Name = "MainSplitContainer";
|
||||||
|
//
|
||||||
|
// MainSplitContainer.Panel1
|
||||||
|
//
|
||||||
|
MainSplitContainer.Panel1.Controls.Add(PropertiesGroupBox);
|
||||||
|
MainSplitContainer.Panel1MinSize = 300;
|
||||||
|
//
|
||||||
|
// MainSplitContainer.Panel2
|
||||||
|
//
|
||||||
|
MainSplitContainer.Panel2.Controls.Add(ProcessorsGroupBox);
|
||||||
|
MainSplitContainer.Panel2.Controls.Add(StartButton);
|
||||||
|
MainSplitContainer.Panel2MinSize = 300;
|
||||||
|
MainSplitContainer.Size = new Size(931, 677);
|
||||||
|
MainSplitContainer.SplitterDistance = 300;
|
||||||
|
MainSplitContainer.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// PropertiesGroupBox
|
||||||
|
//
|
||||||
|
PropertiesGroupBox.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
PropertiesGroupBox.Controls.Add(SettingsPropertyGrid);
|
||||||
|
PropertiesGroupBox.Location = new Point(3, 3);
|
||||||
|
PropertiesGroupBox.Name = "PropertiesGroupBox";
|
||||||
|
PropertiesGroupBox.Size = new Size(294, 671);
|
||||||
|
PropertiesGroupBox.TabIndex = 0;
|
||||||
|
PropertiesGroupBox.TabStop = false;
|
||||||
|
PropertiesGroupBox.Text = "Свойства";
|
||||||
|
//
|
||||||
|
// SettingsPropertyGrid
|
||||||
|
//
|
||||||
|
SettingsPropertyGrid.BackColor = SystemColors.Control;
|
||||||
|
SettingsPropertyGrid.Dock = DockStyle.Fill;
|
||||||
|
SettingsPropertyGrid.Location = new Point(3, 19);
|
||||||
|
SettingsPropertyGrid.Name = "SettingsPropertyGrid";
|
||||||
|
SettingsPropertyGrid.Size = new Size(288, 649);
|
||||||
|
SettingsPropertyGrid.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// StartButton
|
||||||
|
//
|
||||||
|
StartButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
StartButton.Font = new Font("Segoe UI", 18F, FontStyle.Bold);
|
||||||
|
StartButton.Location = new Point(3, 611);
|
||||||
|
StartButton.Name = "StartButton";
|
||||||
|
StartButton.Size = new Size(621, 63);
|
||||||
|
StartButton.TabIndex = 0;
|
||||||
|
StartButton.Text = "Запуск";
|
||||||
|
StartButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// ProcessorsGroupBox
|
||||||
|
//
|
||||||
|
ProcessorsGroupBox.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
ProcessorsGroupBox.Controls.Add(ProcessorsListView);
|
||||||
|
ProcessorsGroupBox.Controls.Add(SelectAllButton);
|
||||||
|
ProcessorsGroupBox.Controls.Add(DeselectAllButton);
|
||||||
|
ProcessorsGroupBox.Location = new Point(3, 3);
|
||||||
|
ProcessorsGroupBox.Name = "ProcessorsGroupBox";
|
||||||
|
ProcessorsGroupBox.Size = new Size(621, 602);
|
||||||
|
ProcessorsGroupBox.TabIndex = 1;
|
||||||
|
ProcessorsGroupBox.TabStop = false;
|
||||||
|
ProcessorsGroupBox.Text = "Обработчики";
|
||||||
|
//
|
||||||
|
// DeselectAllButton
|
||||||
|
//
|
||||||
|
DeselectAllButton.Location = new Point(6, 19);
|
||||||
|
DeselectAllButton.Name = "DeselectAllButton";
|
||||||
|
DeselectAllButton.Size = new Size(137, 23);
|
||||||
|
DeselectAllButton.TabIndex = 0;
|
||||||
|
DeselectAllButton.Text = "Снять выделение всех";
|
||||||
|
DeselectAllButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// SelectAllButton
|
||||||
|
//
|
||||||
|
SelectAllButton.Location = new Point(149, 19);
|
||||||
|
SelectAllButton.Name = "SelectAllButton";
|
||||||
|
SelectAllButton.Size = new Size(137, 23);
|
||||||
|
SelectAllButton.TabIndex = 1;
|
||||||
|
SelectAllButton.Text = "Выделить все";
|
||||||
|
SelectAllButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// ProcessorsListView
|
||||||
|
//
|
||||||
|
ProcessorsListView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
ProcessorsListView.CheckBoxes = true;
|
||||||
|
ProcessorsListView.Location = new Point(6, 48);
|
||||||
|
ProcessorsListView.Name = "ProcessorsListView";
|
||||||
|
ProcessorsListView.Size = new Size(606, 548);
|
||||||
|
ProcessorsListView.TabIndex = 2;
|
||||||
|
ProcessorsListView.UseCompatibleStateImageBehavior = false;
|
||||||
|
//
|
||||||
|
// StartForm
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||||
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
|
ClientSize = new Size(931, 677);
|
||||||
|
Controls.Add(MainSplitContainer);
|
||||||
|
Name = "StartForm";
|
||||||
|
Text = "Настройки импорта данных";
|
||||||
|
MainSplitContainer.Panel1.ResumeLayout(false);
|
||||||
|
MainSplitContainer.Panel2.ResumeLayout(false);
|
||||||
|
((System.ComponentModel.ISupportInitialize)MainSplitContainer).EndInit();
|
||||||
|
MainSplitContainer.ResumeLayout(false);
|
||||||
|
PropertiesGroupBox.ResumeLayout(false);
|
||||||
|
ProcessorsGroupBox.ResumeLayout(false);
|
||||||
|
ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private SplitContainer MainSplitContainer;
|
||||||
|
private GroupBox PropertiesGroupBox;
|
||||||
|
private PropertyGrid SettingsPropertyGrid;
|
||||||
|
private Button StartButton;
|
||||||
|
private GroupBox ProcessorsGroupBox;
|
||||||
|
private Button SelectAllButton;
|
||||||
|
private Button DeselectAllButton;
|
||||||
|
private ListView ProcessorsListView;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Pf2eDataScrapper.Forms;
|
||||||
|
|
||||||
|
public partial class StartForm : Form
|
||||||
|
{
|
||||||
|
public StartForm()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Pf2eDataScrapper.App;
|
||||||
|
using Pf2eDataScrapper.Forms;
|
||||||
|
using Pf2eModel;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper;
|
||||||
|
|
||||||
|
internal sealed class ImportApplication : ApplicationContext
|
||||||
|
{
|
||||||
|
public ImportApplication()
|
||||||
|
{
|
||||||
|
InitializeServices();
|
||||||
|
CreateStartForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region "Внедрение зависимостей (DI)"
|
||||||
|
|
||||||
|
public IServiceCollection Services = new ServiceCollection();
|
||||||
|
|
||||||
|
private void InitializeServices()
|
||||||
|
{
|
||||||
|
Services.AddSingleton(this);
|
||||||
|
Services.AddSingleton(Settings);
|
||||||
|
|
||||||
|
Services.AddSingleton<ProcessorCollection>();
|
||||||
|
|
||||||
|
Services.AddDbContext<Pf2eDbContext>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region "Настройки"
|
||||||
|
|
||||||
|
public ApplicationSettings Settings = new();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region "Формы"
|
||||||
|
|
||||||
|
private StartForm? _startForm;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region "Жизненный цикл"
|
||||||
|
|
||||||
|
private void CreateStartForm()
|
||||||
|
{
|
||||||
|
_startForm = new() { StartPosition = FormStartPosition.CenterParent };
|
||||||
|
_startForm.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartProcess()
|
||||||
|
{
|
||||||
|
_startForm!.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
||||||
|
using Pf2eDataScrapper.Processors;
|
||||||
using Pf2eModel;
|
using Pf2eModel;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||||
|
|||||||
+24
-27
@@ -1,43 +1,22 @@
|
|||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
using Pf2eDataScrapper.App.Attributes;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Атрибут обработчика данных Архивов Нефиса.
|
/// Атрибут обработчика данных Архивов Нефиса.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">Название обработчика.</param>
|
|
||||||
/// <param name="type">Тип данных, которые обработчик обрабатывает.</param>
|
|
||||||
/// <param name="dependencies">Названия обработчиков, которые должны быть выполнены до запуска этого обработчика.</param>
|
|
||||||
/// <param name="includeDefaults">Флаг, указывающий, следует ли добавить важные общие зависимости для обработчка.</param>
|
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public class AonprdProcessorAttribute(
|
public class AonprdProcessorAttribute : Attributes
|
||||||
string name,
|
|
||||||
string? type,
|
|
||||||
string[] dependencies,
|
|
||||||
bool includeDefaults = true
|
|
||||||
) : Attribute
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Важные общие зависимости для обработчка.
|
/// Важные общие зависимости для обработчка.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly string[] DefaultDependencies = ["trait", "source"];
|
private static readonly string[] DefaultDependencies = ["aonprd:trait", "aonprd:source"];
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Название обработчика.
|
|
||||||
/// </summary>
|
|
||||||
public readonly string Name = name;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Тип данных, которые обработчик обрабатывает.
|
/// Тип данных, которые обработчик обрабатывает.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly string? Type = type;
|
public string Type { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Названия обработчиков, которые должны быть выполнены до запуска этого обработчика.
|
|
||||||
/// </summary>
|
|
||||||
public readonly IEnumerable<string> Dependencies =
|
|
||||||
[
|
|
||||||
.. includeDefaults ? DefaultDependencies : [],
|
|
||||||
.. dependencies,
|
|
||||||
];
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Конструктор класса <see cref="AonprdProcessorAttribute"/> со стандартными общими зависимости для обработчка.
|
/// Конструктор класса <see cref="AonprdProcessorAttribute"/> со стандартными общими зависимости для обработчка.
|
||||||
@@ -62,4 +41,22 @@ public class AonprdProcessorAttribute(
|
|||||||
/// <param name="type">Тип данных, которые обработчик обрабатывает.</param>
|
/// <param name="type">Тип данных, которые обработчик обрабатывает.</param>
|
||||||
public AonprdProcessorAttribute(string name, string type)
|
public AonprdProcessorAttribute(string name, string type)
|
||||||
: this(name, type, DefaultDependencies) { }
|
: 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
using Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||||
|
using Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||||
|
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ 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.Processors;
|
||||||
using Pf2eModel;
|
using Pf2eModel;
|
||||||
using Pf2eModel.Model;
|
using Pf2eModel.Model;
|
||||||
using Pf2eModel.Model.Base;
|
using Pf2eModel.Model.Base;
|
||||||
|
|||||||
-49
@@ -1,49 +0,0 @@
|
|||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
|
||||||
using Pf2eModel;
|
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса.
|
|
||||||
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
|
||||||
/// для которых указан атрибут <see cref="AonprdProcessorAttribute"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input">Объект обработки вводимого JSON.</param>
|
|
||||||
/// <seealso cref="AonprdProcessorAttribute"/>
|
|
||||||
internal abstract class AbstractProcessor(AonprdProcessorInput input)
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Вспомогательный класс для работы с базой данных.
|
|
||||||
/// </summary>
|
|
||||||
protected readonly DatabaseHelper Helper = DatabaseHelper.Instance;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Вспомогательный класс для работы со строками и форматированием.
|
|
||||||
/// </summary>
|
|
||||||
protected readonly StringHelper StringHelper = StringHelper.Instance;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Вспомогательный класс для работы с глобальными настройками.
|
|
||||||
/// </summary>
|
|
||||||
protected readonly AonprdBuilderGlobals Globals = AonprdBuilderGlobals.Instance;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Контекст базы данных для работы с данными.
|
|
||||||
/// </summary>
|
|
||||||
public readonly Pf2eDbContext Context = DatabaseHelper.DbContext;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Объект обработки вводимого JSON.
|
|
||||||
/// </summary>
|
|
||||||
public readonly AonprdProcessorInput Input = input;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Основной метод обработки данных.
|
|
||||||
/// </summary>
|
|
||||||
public abstract void Process();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Метод для сохранения изменений в базе данных.
|
|
||||||
/// </summary>
|
|
||||||
public abstract void Save();
|
|
||||||
}
|
|
||||||
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
using Pf2eModel.Model.Base.Targets;
|
using Pf2eDataScrapper.Processors;
|
||||||
|
using Pf2eModel.Model.Base.Targets;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common;
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
using Pf2eModel.Model.Common;
|
using Pf2eDataScrapper.Processors;
|
||||||
|
using Pf2eModel.Model.Common;
|
||||||
using Pf2eModel.Model.Common.I18n;
|
using Pf2eModel.Model.Common.I18n;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
using Pf2eModel.Model.Base.Source;
|
using Pf2eDataScrapper.Processors;
|
||||||
|
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.DataBuilder.Processors.Common;
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ internal class FeatProcessor(AonprdProcessorInput input) : AbstractEntityProcess
|
|||||||
Archetype[] archetypes = Context
|
Archetype[] archetypes = Context
|
||||||
// ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall
|
// ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall
|
||||||
.Archetypes.Where(a => Pf2eDbContext.LocaleSearchArray(a.Entity.Name, archetypeStrings))
|
.Archetypes.Where(a => Pf2eDbContext.LocaleSearchArray(a.Entity.Name, archetypeStrings))
|
||||||
// .Where(a => archetypeStrings.Contains(a.Entity.Name.ToString()))
|
// .Where(a => archetypeStrings.Contains(a.Entity.Group.ToString()))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
if (archetypes.Length != 0)
|
if (archetypes.Length != 0)
|
||||||
|
|||||||
+1
@@ -6,6 +6,7 @@
|
|||||||
// Ну а пока просто расставляем родительские и дочерние элементы.
|
// Ну а пока просто расставляем родительские и дочерние элементы.
|
||||||
|
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
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.Processors;
|
||||||
using Pf2eModel.Model.Base.Source;
|
using Pf2eModel.Model.Base.Source;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types.Rules;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types.Rules;
|
||||||
|
|||||||
+1
-1
@@ -83,6 +83,6 @@ internal class CompendiumFolder
|
|||||||
/// <returns>Строковое представление данных о папки компендиума.</returns>
|
/// <returns>Строковое представление данных о папки компендиума.</returns>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"CompendiumFolder([Id={Id}][Type={Type}][Name={Name}][Path={Path}][Parent={Parent?.Name ?? "null"}])";
|
return $"CompendiumFolder([Id={Id}][Type={Type}][Group={Name}][Path={Path}][Parent={Parent?.Name ?? "null"}])";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -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.Processors;
|
||||||
using Pf2eModel;
|
using Pf2eModel;
|
||||||
using Pf2eModel.Model;
|
using Pf2eModel.Model;
|
||||||
using Pf2eModel.Model.Base;
|
using Pf2eModel.Model.Base;
|
||||||
@@ -51,7 +52,7 @@ internal abstract class AbstractProcessor(ProcessorInput input)
|
|||||||
EntityAlias alias = new()
|
EntityAlias alias = new()
|
||||||
{
|
{
|
||||||
Type = LocaleType.English,
|
Type = LocaleType.English,
|
||||||
Alias = Entity.Name,
|
Alias = Entity.Group,
|
||||||
EntityId = Entity.Id,
|
EntityId = Entity.Id,
|
||||||
Entity = Entity
|
Entity = Entity
|
||||||
};
|
};
|
||||||
@@ -147,13 +148,13 @@ internal abstract class AbstractProcessor(ProcessorInput input)
|
|||||||
/*
|
/*
|
||||||
foreach (string name in names)
|
foreach (string name in names)
|
||||||
{
|
{
|
||||||
if (result.Any(t => t.Entity.Name.Contains(name)))
|
if (result.Any(t => t.Entity.Group.Contains(name)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Trait trait = new()
|
Trait trait = new()
|
||||||
{
|
{
|
||||||
Name = name,
|
Group = name,
|
||||||
Slug = name,
|
Slug = name,
|
||||||
Type = TraitType.Regular,
|
Type = TraitType.Regular,
|
||||||
Description = "",
|
Description = "",
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
using Konsole;
|
using Konsole;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.Compendium;
|
using Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.Compendium;
|
||||||
|
using Pf2eDataScrapper.Processors;
|
||||||
using Pf2eModel;
|
using Pf2eModel;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder;
|
namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder;
|
||||||
|
|||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Pf2eDataScrapper.Processors;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder.Processors;
|
namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder.Processors;
|
||||||
|
|||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Pf2eDataScrapper.Processors;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
using Pf2eModel.Model.Structure;
|
using Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<LangVersion>13.0</LangVersion>
|
<OutputType>WinExe</OutputType>
|
||||||
<OutputType>Exe</OutputType>
|
<TargetFramework>net9.0-windows7.0</TargetFramework>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AngleSharp" Version="1.3.0" />
|
<PackageReference Include="AngleSharp" Version="1.3.0" />
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Pf2eDataScrapper.App;
|
||||||
|
using Pf2eModel;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса.
|
||||||
|
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
||||||
|
/// для которых указан атрибут <see cref="ProcessAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceProvider">Провайдер сервисов.</param>
|
||||||
|
/// <param name="input">Провайдер сервисов.</param>
|
||||||
|
/// <seealso cref="ProcessAttribute"/>
|
||||||
|
internal abstract class AbstractInputProcessor(
|
||||||
|
IServiceProvider serviceProvider,
|
||||||
|
ProcessorInput input
|
||||||
|
) : IProcessor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Провайдер сервисов.
|
||||||
|
/// </summary>
|
||||||
|
public IServiceProvider ServiceProvider { get; } = serviceProvider;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Контекст базы данных.
|
||||||
|
/// </summary>
|
||||||
|
public Pf2eDbContext Context { get; } = serviceProvider.GetService<Pf2eDbContext>()!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ввод.
|
||||||
|
/// </summary>
|
||||||
|
public ProcessorInput Input { get; } = input;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Основной метод обработки данных.
|
||||||
|
/// </summary>
|
||||||
|
public abstract void Process();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Метод для сохранения изменений в базе данных.
|
||||||
|
/// </summary>
|
||||||
|
public abstract void Save();
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Pf2eDataScrapper.App;
|
||||||
|
using Pf2eModel;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса.
|
||||||
|
/// Класс предназначен для обработки данных с помощью различных обработчиков,
|
||||||
|
/// для которых указан атрибут <see cref="ProcessAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceProvider">Провайдер сервисов.</param>
|
||||||
|
/// <seealso cref="ProcessAttribute"/>
|
||||||
|
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>
|
||||||
|
public abstract void Process();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Метод для сохранения изменений в базе данных.
|
||||||
|
/// </summary>
|
||||||
|
public abstract void Save();
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
|
public interface IProcessor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Провайдер сервисов.
|
||||||
|
/// </summary>
|
||||||
|
IServiceProvider ServiceProvider { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Основной метод обработки данных.
|
||||||
|
/// </summary>
|
||||||
|
void Process();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Метод для сохранения изменений в базе данных.
|
||||||
|
/// </summary>
|
||||||
|
void Save();
|
||||||
|
}
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
using NpgsqlTypes;
|
using NpgsqlTypes;
|
||||||
using Pf2eModel.Model.Common.I18n;
|
using Pf2eModel.Model.Common.I18n;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers;
|
namespace Pf2eDataScrapper.Processors;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Класс для работы с JSON-объектом.
|
/// Класс для работы с JSON-объектом.
|
||||||
+19
-14
@@ -1,18 +1,23 @@
|
|||||||
using Pf2eDataScrapper;
|
namespace Pf2eDataScrapper;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd;
|
|
||||||
|
|
||||||
// Console.SetWindowSize(Console.LargestWindowWidth - 20, Console.LargestWindowHeight - 10);
|
internal static class Program
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The main entry point for the application.
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
// To customize application configuration such as set high DPI settings or default font,
|
||||||
|
// see https://aka.ms/applicationconfiguration.
|
||||||
|
ApplicationConfiguration.Initialize();
|
||||||
|
|
||||||
EnvSettings.Load();
|
Application.SetHighDpiMode(HighDpiMode.SystemAware);
|
||||||
|
|
||||||
/*
|
#pragma warning disable WFO5001
|
||||||
Pf2EFoundryImporter importer = new();
|
Application.SetColorMode(SystemColorMode.System);
|
||||||
*/
|
#pragma warning restore WFO5001
|
||||||
|
|
||||||
AonprdImporter importer = new();
|
Application.Run(new ImportApplication());
|
||||||
|
}
|
||||||
// importer.ProcessorNames = ["rules", "rules-order"];
|
}
|
||||||
|
|
||||||
importer.Prepare();
|
|
||||||
importer.Import();
|
|
||||||
// importer.BuildSchemas();
|
|
||||||
|
|||||||
@@ -26,7 +26,4 @@
|
|||||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Resources\" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user