diff --git a/Pf2eDataScrapper/App/Attributes.cs b/Pf2eDataScrapper/App/Attributes.cs new file mode 100644 index 0000000..df60b8b --- /dev/null +++ b/Pf2eDataScrapper/App/Attributes.cs @@ -0,0 +1,62 @@ +namespace Pf2eDataScrapper.App; + +/// +/// Общий аттрибут обработчика. +/// +/// Название обработчика. +/// Названия обработчиков, которые должны быть выполнены до запуска этого обработчика. +[AttributeUsage(AttributeTargets.Class)] +public class ProcessAttribute(string name, ICollection dependencies) : Attribute +{ + /// + /// Название обработчика. + /// + public string Name { get; init; } = name; + + /// + /// Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика. + /// + public ICollection Dependencies { get; init; } = dependencies; + + public ProcessAttribute(string name) + : this(name, []) { } +} + +/// +/// Аттрибут обработчика для уточнения группы. +/// +/// Группа обработчиков, к которому относится обработчик. +[AttributeUsage(AttributeTargets.Class)] +internal class ProcessorGroupAttribute(ProcessorGroupEnum group) : Attribute +{ + /// + /// Название обработчика, к которому относится обработчик. + /// + public ProcessorGroupEnum Group { get; init; } = group; +} + +/// +/// Аттрибут обработчика для уточнения списка зависимостей. +/// +/// Список названий зависимостей. +[AttributeUsage(AttributeTargets.Class)] +internal class ProcessorDependenciesAttribute(ICollection dependencies) : Attribute +{ + /// + /// Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика. + /// + public ICollection Dependencies { get; init; } = dependencies; +} + +/// +/// Аттрибут обработчика для внутреннего типа элемента. +/// +/// Внутренний типа элемента. +[AttributeUsage(AttributeTargets.Class)] +internal class ProcessorInnerTypeAttribute(string innerType) : Attribute +{ + /// + /// Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика. + /// + public string InnerType { get; init; } = innerType; +} diff --git a/Pf2eDataScrapper/App/ProcessorCollection.cs b/Pf2eDataScrapper/App/ProcessorCollection.cs new file mode 100644 index 0000000..ffea206 --- /dev/null +++ b/Pf2eDataScrapper/App/ProcessorCollection.cs @@ -0,0 +1,229 @@ +using System.ComponentModel; +using System.Reflection; +using Pf2eDataScrapper.Processors; + +namespace Pf2eDataScrapper.App; + +/// +/// Класс с коллекцией обработчиков. +/// +internal class ProcessorCollection +{ + /// + /// Коллекция всех доступных обработчиков. + /// + public ICollection AllItems { get; } = []; + + /// + /// Коллекция обработчиков, которые будут обрабатываться. + /// Для изменения необходимо использовать . + /// + public List Items { get; private set; } = []; + + /// + /// Конструктор класса . + /// + 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([]); + } + + /// + /// Создание элемента коллекции обработчиков. + /// + /// Тип обработчика. + /// + 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()!; + DescriptionAttribute? descriptionAttribute = + type.GetCustomAttribute(); + ProcessorGroupAttribute? groupAttribute = + type.GetCustomAttribute(); + ProcessorDependenciesAttribute? dependenciesAttribute = + type.GetCustomAttribute(); + ProcessorInnerTypeAttribute? innerTypeAttribute = + type.GetCustomAttribute(); + + 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, + }; + } + + /// + /// Проверка, что все зависимости всех обработчиков могут быть удовлетворены. + /// + 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."); + } + } + } + } + + /// + /// Сортировать обработчики в соответсвии со всеми зависимостями. + /// + public void SortItems() + { + Dictionary priorities = []; + + while (priorities.Count < Items.Count) + { + foreach (ProcessorCollectionItem item in Items) + { + if (item.Priority > 0) + { + continue; + } + + IEnumerable 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); + } + + /// + /// Ограничить список используемых обработчиков по названию. + /// Автоматически включает все обработчики, от которых зависят указанные в аргументе обработчики. + /// + /// Коллекция названиий требуемых обработчиков. + public void FilterProcessors(ICollection processorNames) + { + if (processorNames.Count == 0) + { + Items = [.. AllItems]; + SortItems(); + return; + } + + Dictionary nameFlags = processorNames.ToDictionary(name => name, _ => false); + + while (nameFlags.Values.Any(v => !v)) + { + foreach ( + KeyValuePair 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(); + } +} + +/// +/// Элемент коллекции обработчиков. +/// +internal class ProcessorCollectionItem +{ + /// + /// Название обработчика. + /// + public required string Name { get; init; } + + /// + /// Тип класса обработчика. + /// + public required Type Type { get; init; } + + /// + /// Описание обработчика. + /// + public string Description { get; init; } = ""; + + /// + /// Группа обработчика. + /// + public required ProcessorGroupEnum Group { get; init; } + + /// + /// Коллекция названий обработчиков, после которых должен выполняться обработчик. + /// + public ICollection Dependencies { get; init; } = []; + + /// + /// Приоритет выполнения обработчика. + /// + public int Priority { get; set; } = -1; + + /// + /// Флаг, указывающий, обрабатывает ли обработчик коллекцию элементов. + /// Внутренний тип элементов указывается в . + /// + public required bool IsCollectionProcessor { get; init; } + + /// + /// Флаг, указывающий внутренний тип коллекции обрабатываемых элементов. + /// + public string? InnerType { get; init; } + + /// + /// Конструктор обработчика. + /// + public required ConstructorInfo Constructor { get; init; } +} diff --git a/Pf2eDataScrapper/App/ProcessorGroupEnum.cs b/Pf2eDataScrapper/App/ProcessorGroupEnum.cs new file mode 100644 index 0000000..09d40ac --- /dev/null +++ b/Pf2eDataScrapper/App/ProcessorGroupEnum.cs @@ -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, +} diff --git a/Pf2eDataScrapper/ApplicationSettings.cs b/Pf2eDataScrapper/ApplicationSettings.cs new file mode 100644 index 0000000..48a80a7 --- /dev/null +++ b/Pf2eDataScrapper/ApplicationSettings.cs @@ -0,0 +1,80 @@ +using System.ComponentModel; +using dotenv.net; +using dotenv.net.Utilities; + +namespace Pf2eDataScrapper; + +/// +/// Настройки программы. +/// +internal class ApplicationSettings +{ + /// + /// Конструктор класса . + /// + public ApplicationSettings() + { + DotEnv.Load(); + } + + #region Настройки из .env + + /// + /// Путь к папке с входными данными. + /// + [Browsable(true)] + [ReadOnly(true)] + [DisplayName("Путь к папке с входными данными.")] + [Description("Редактирование через .env-файл.")] + public string DataDirPath { get; } = EnvReader.GetStringValue("DATA_DIR"); + + /// + /// Папка в входными данными. + /// + [Browsable(false)] + public DirectoryInfo DataDir => new(DataDirPath); + + /// + /// Путь к папке для сохранения результатов. + /// + [Browsable(true)] + [ReadOnly(true)] + [DisplayName("Путь к папке для сохранения результатов.")] + [Description("Редактирование через .env-файл.")] + public string OutputDirPath { get; } = EnvReader.GetStringValue("OUTPUT_DIR"); + + /// + /// Папка для сохранения результатов. + /// + [Browsable(false)] + public string OutputDir => new(OutputDirPath); + + /// + /// Строка подключения к базе данных. + /// + [Browsable(true)] + [ReadOnly(true)] + [DisplayName("Строка подключения к базе данных.")] + [Description("Редактирование через .env-файл.")] + public string DatabaseConnection { get; } = EnvReader.GetStringValue("DATABASE_CONNECTION"); + + #endregion + + #region Основные настройки + + /// + /// Флаг, указывающий, что все старые записи необходимо удалить. + /// + [Browsable(true)] + [DisplayName("Удаление всех записей перед запуском.")] + [Description("Редактирование через .env-файл.")] + public bool TruncateAllTables { get; set; } = true; + + /// + /// Список обработчиков, которые должны быть выполнены. + /// Пустой список означает, что должны быть выполнены все обработчики. + /// + public ICollection ProcessorNames { get; } = new List(); + + #endregion +} diff --git a/Pf2eDataScrapper/Forms/StartForm.Designer.cs b/Pf2eDataScrapper/Forms/StartForm.Designer.cs new file mode 100644 index 0000000..387245b --- /dev/null +++ b/Pf2eDataScrapper/Forms/StartForm.Designer.cs @@ -0,0 +1,166 @@ +namespace Pf2eDataScrapper.Forms; + +partial class StartForm +{ + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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; +} \ No newline at end of file diff --git a/Pf2eDataScrapper/Forms/StartForm.cs b/Pf2eDataScrapper/Forms/StartForm.cs new file mode 100644 index 0000000..70bbf4d --- /dev/null +++ b/Pf2eDataScrapper/Forms/StartForm.cs @@ -0,0 +1,9 @@ +namespace Pf2eDataScrapper.Forms; + +public partial class StartForm : Form +{ + public StartForm() + { + InitializeComponent(); + } +} diff --git a/Pf2eDataScrapper/Forms/StartForm.resx b/Pf2eDataScrapper/Forms/StartForm.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/Pf2eDataScrapper/Forms/StartForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Pf2eDataScrapper/ImportApplication.cs b/Pf2eDataScrapper/ImportApplication.cs new file mode 100644 index 0000000..18cf2ee --- /dev/null +++ b/Pf2eDataScrapper/ImportApplication.cs @@ -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(); + + Services.AddDbContext(); + } + + #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 +} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdDataBuilder.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdDataBuilder.cs index 9fb3ca6..ae02027 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdDataBuilder.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdDataBuilder.cs @@ -2,6 +2,7 @@ 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; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorAttribute.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorAttribute.cs index faac790..301d742 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorAttribute.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorAttribute.cs @@ -1,43 +1,22 @@ -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder; +using Pf2eDataScrapper.App.Attributes; + +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder; /// /// Атрибут обработчика данных Архивов Нефиса. /// -/// Название обработчика. -/// Тип данных, которые обработчик обрабатывает. -/// Названия обработчиков, которые должны быть выполнены до запуска этого обработчика. -/// Флаг, указывающий, следует ли добавить важные общие зависимости для обработчка. [AttributeUsage(AttributeTargets.Class)] -public class AonprdProcessorAttribute( - string name, - string? type, - string[] dependencies, - bool includeDefaults = true -) : Attribute +public class AonprdProcessorAttribute : Attributes { /// /// Важные общие зависимости для обработчка. /// - private static readonly string[] DefaultDependencies = ["trait", "source"]; - - /// - /// Название обработчика. - /// - public readonly string Name = name; + private static readonly string[] DefaultDependencies = ["aonprd:trait", "aonprd:source"]; /// /// Тип данных, которые обработчик обрабатывает. /// - public readonly string? Type = type; - - /// - /// Названия обработчиков, которые должны быть выполнены до запуска этого обработчика. - /// - public readonly IEnumerable Dependencies = - [ - .. includeDefaults ? DefaultDependencies : [], - .. dependencies, - ]; + public string Type { get; init; } /// /// Конструктор класса со стандартными общими зависимости для обработчка. @@ -62,4 +41,22 @@ public class AonprdProcessorAttribute( /// Тип данных, которые обработчик обрабатывает. public AonprdProcessorAttribute(string name, string type) : this(name, type, DefaultDependencies) { } + + /// + /// Основной конструктор класса . + /// + /// Название обработчика. + /// Тип данных, которые обработчик обрабатывает. + /// Названия обработчиков, которые должны быть выполнены до запуска этого обработчика. + /// Флаг, указывающий, следует ли добавить важные общие зависимости для обработчка. + public AonprdProcessorAttribute( + string name, + string? type, + ICollection dependencies, + bool includeDefaults = true + ) + : base($"aonprd:{name}", [.. includeDefaults ? DefaultDependencies : [], .. dependencies]) + { + Type = type; + } } diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorCollection.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorCollection.cs index 9d66d8a..4ec1ccf 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorCollection.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorCollection.cs @@ -1,5 +1,5 @@ using System.Reflection; -using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors; +using Pf2eDataScrapper.Processors; namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorInput.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorInput.cs index d369fec..d2fde33 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorInput.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorInput.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json.Linq; using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Processors; namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractEntityProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractEntityProcessor.cs index 7876221..03f14a5 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractEntityProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractEntityProcessor.cs @@ -3,6 +3,7 @@ using System.Text; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.Processors; using Pf2eModel; using Pf2eModel.Model; using Pf2eModel.Model.Base; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractProcessor.cs deleted file mode 100644 index 2129587..0000000 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractProcessor.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; -using Pf2eModel; - -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors; - -/// -/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса. -/// Класс предназначен для обработки данных с помощью различных обработчиков, -/// для которых указан атрибут . -/// -/// Объект обработки вводимого JSON. -/// -internal abstract class AbstractProcessor(AonprdProcessorInput input) -{ - /// - /// Вспомогательный класс для работы с базой данных. - /// - protected readonly DatabaseHelper Helper = DatabaseHelper.Instance; - - /// - /// Вспомогательный класс для работы со строками и форматированием. - /// - protected readonly StringHelper StringHelper = StringHelper.Instance; - - /// - /// Вспомогательный класс для работы с глобальными настройками. - /// - protected readonly AonprdBuilderGlobals Globals = AonprdBuilderGlobals.Instance; - - /// - /// Контекст базы данных для работы с данными. - /// - public readonly Pf2eDbContext Context = DatabaseHelper.DbContext; - - /// - /// Объект обработки вводимого JSON. - /// - public readonly AonprdProcessorInput Input = input; - - /// - /// Основной метод обработки данных. - /// - public abstract void Process(); - - /// - /// Метод для сохранения изменений в базе данных. - /// - public abstract void Save(); -} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/ExternalProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/ExternalProcessor.cs index fd688fc..18508df 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/ExternalProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/ExternalProcessor.cs @@ -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; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SkillProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SkillProcessor.cs index 26ab2ed..f0b6ef4 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SkillProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SkillProcessor.cs @@ -1,4 +1,5 @@ -using Pf2eModel.Model.Common; +using Pf2eDataScrapper.Processors; +using Pf2eModel.Model.Common; using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Enum; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SourceProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SourceProcessor.cs index 8f0a417..1cd6a68 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SourceProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SourceProcessor.cs @@ -1,4 +1,5 @@ -using Pf2eModel.Model.Base.Source; +using Pf2eDataScrapper.Processors; +using Pf2eModel.Model.Base.Source; using Pf2eModel.Model.Enum; namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/FeatProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/FeatProcessor.cs index aa93139..c863398 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/FeatProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/FeatProcessor.cs @@ -53,7 +53,7 @@ internal class FeatProcessor(AonprdProcessorInput input) : AbstractEntityProcess Archetype[] archetypes = Context // ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall .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(); if (archetypes.Length != 0) diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesOrderProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesOrderProcessor.cs index 98c23d3..9d673e3 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesOrderProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesOrderProcessor.cs @@ -6,6 +6,7 @@ // Ну а пока просто расставляем родительские и дочерние элементы. using System.Data; +using Pf2eDataScrapper.Processors; using Pf2eModel.Model.Structure; using Rule = Pf2eModel.Model.Structure.Rule; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesTocProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesTocProcessor.cs index 511d4a4..5d76d93 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesTocProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesTocProcessor.cs @@ -2,6 +2,7 @@ using System.Web; using AngleSharp; using AngleSharp.Dom; +using Pf2eDataScrapper.Processors; using Pf2eModel.Model.Base.Source; namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types.Rules; diff --git a/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/Compendium/CompendiumFolder.cs b/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/Compendium/CompendiumFolder.cs index 07557b5..e51fe04 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/Compendium/CompendiumFolder.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/Compendium/CompendiumFolder.cs @@ -83,6 +83,6 @@ internal class CompendiumFolder /// Строковое представление данных о папки компендиума. 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"}])"; } } diff --git a/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/AbstractProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/AbstractProcessor.cs index 8ff9468..80b7cc3 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/AbstractProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/AbstractProcessor.cs @@ -2,6 +2,7 @@ using System.Text; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.Processors; using Pf2eModel; using Pf2eModel.Model; using Pf2eModel.Model.Base; @@ -51,7 +52,7 @@ internal abstract class AbstractProcessor(ProcessorInput input) EntityAlias alias = new() { Type = LocaleType.English, - Alias = Entity.Name, + Alias = Entity.Group, EntityId = Entity.Id, Entity = Entity }; @@ -147,13 +148,13 @@ internal abstract class AbstractProcessor(ProcessorInput input) /* foreach (string name in names) { - if (result.Any(t => t.Entity.Name.Contains(name))) + if (result.Any(t => t.Entity.Group.Contains(name))) { continue; } Trait trait = new() { - Name = name, + Group = name, Slug = name, Type = TraitType.Regular, Description = "", diff --git a/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/PF2eFoundryDataBuilder.cs b/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/PF2eFoundryDataBuilder.cs index cd88174..16ca5e1 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/PF2eFoundryDataBuilder.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/PF2eFoundryDataBuilder.cs @@ -2,6 +2,7 @@ using Konsole; using Newtonsoft.Json.Linq; using Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.Compendium; +using Pf2eDataScrapper.Processors; using Pf2eModel; namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder; diff --git a/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/Processors/ActionProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/Processors/ActionProcessor.cs index b17f9b2..5e0d2b5 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/Processors/ActionProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/Processors/ActionProcessor.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.Processors; using Pf2eModel.Model.Enum; namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder.Processors; diff --git a/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/Processors/ConditionProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/Processors/ConditionProcessor.cs index f549256..acb7ca1 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/Processors/ConditionProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/Processors/ConditionProcessor.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.Processors; using Pf2eModel.Model.Enum; using Pf2eModel.Model.Structure; diff --git a/Pf2eDataScrapper/Pf2eDataScrapper.csproj b/Pf2eDataScrapper/Pf2eDataScrapper.csproj index a61becb..504d388 100644 --- a/Pf2eDataScrapper/Pf2eDataScrapper.csproj +++ b/Pf2eDataScrapper/Pf2eDataScrapper.csproj @@ -1,10 +1,10 @@  - 13.0 - Exe - net9.0 - enable + WinExe + net9.0-windows7.0 enable + true + enable diff --git a/Pf2eDataScrapper/Processors/AbstractInputProcessor.cs b/Pf2eDataScrapper/Processors/AbstractInputProcessor.cs new file mode 100644 index 0000000..a576ae2 --- /dev/null +++ b/Pf2eDataScrapper/Processors/AbstractInputProcessor.cs @@ -0,0 +1,44 @@ +using Microsoft.Extensions.DependencyInjection; +using Pf2eDataScrapper.App; +using Pf2eModel; + +namespace Pf2eDataScrapper.Processors; + +/// +/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса. +/// Класс предназначен для обработки данных с помощью различных обработчиков, +/// для которых указан атрибут . +/// +/// Провайдер сервисов. +/// Провайдер сервисов. +/// +internal abstract class AbstractInputProcessor( + IServiceProvider serviceProvider, + ProcessorInput input +) : IProcessor +{ + /// + /// Провайдер сервисов. + /// + public IServiceProvider ServiceProvider { get; } = serviceProvider; + + /// + /// Контекст базы данных. + /// + public Pf2eDbContext Context { get; } = serviceProvider.GetService()!; + + /// + /// Ввод. + /// + public ProcessorInput Input { get; } = input; + + /// + /// Основной метод обработки данных. + /// + public abstract void Process(); + + /// + /// Метод для сохранения изменений в базе данных. + /// + public abstract void Save(); +} diff --git a/Pf2eDataScrapper/Processors/AbstractProcessor.cs b/Pf2eDataScrapper/Processors/AbstractProcessor.cs new file mode 100644 index 0000000..155a670 --- /dev/null +++ b/Pf2eDataScrapper/Processors/AbstractProcessor.cs @@ -0,0 +1,35 @@ +using Microsoft.Extensions.DependencyInjection; +using Pf2eDataScrapper.App; +using Pf2eModel; + +namespace Pf2eDataScrapper.Processors; + +/// +/// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса. +/// Класс предназначен для обработки данных с помощью различных обработчиков, +/// для которых указан атрибут . +/// +/// Провайдер сервисов. +/// +internal abstract class AbstractProcessor(IServiceProvider serviceProvider) : IProcessor +{ + /// + /// Провайдер сервисов. + /// + public IServiceProvider ServiceProvider { get; } = serviceProvider; + + /// + /// Контекст базы данных. + /// + public Pf2eDbContext Context { get; } = serviceProvider.GetService()!; + + /// + /// Основной метод обработки данных. + /// + public abstract void Process(); + + /// + /// Метод для сохранения изменений в базе данных. + /// + public abstract void Save(); +} diff --git a/Pf2eDataScrapper/Processors/IProcessor.cs b/Pf2eDataScrapper/Processors/IProcessor.cs new file mode 100644 index 0000000..33849eb --- /dev/null +++ b/Pf2eDataScrapper/Processors/IProcessor.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Pf2eDataScrapper.Processors; + +public interface IProcessor +{ + /// + /// Провайдер сервисов. + /// + IServiceProvider ServiceProvider { get; } + + /// + /// Основной метод обработки данных. + /// + void Process(); + + /// + /// Метод для сохранения изменений в базе данных. + /// + void Save(); +} diff --git a/Pf2eDataScrapper/Importers/ProcessorInput.cs b/Pf2eDataScrapper/Processors/ProcessorInput.cs similarity index 99% rename from Pf2eDataScrapper/Importers/ProcessorInput.cs rename to Pf2eDataScrapper/Processors/ProcessorInput.cs index 85081e7..cb683be 100644 --- a/Pf2eDataScrapper/Importers/ProcessorInput.cs +++ b/Pf2eDataScrapper/Processors/ProcessorInput.cs @@ -2,7 +2,7 @@ using NpgsqlTypes; using Pf2eModel.Model.Common.I18n; -namespace Pf2eDataScrapper.Importers; +namespace Pf2eDataScrapper.Processors; /// /// Класс для работы с JSON-объектом. diff --git a/Pf2eDataScrapper/Program.cs b/Pf2eDataScrapper/Program.cs index d32ba97..328179e 100644 --- a/Pf2eDataScrapper/Program.cs +++ b/Pf2eDataScrapper/Program.cs @@ -1,18 +1,23 @@ -using Pf2eDataScrapper; -using Pf2eDataScrapper.Importers.Implementations.Aonprd; +namespace Pf2eDataScrapper; -// Console.SetWindowSize(Console.LargestWindowWidth - 20, Console.LargestWindowHeight - 10); +internal static class Program +{ + /// + /// The main entry point for the application. + /// + [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); -/* -Pf2EFoundryImporter importer = new(); -*/ +#pragma warning disable WFO5001 + Application.SetColorMode(SystemColorMode.System); +#pragma warning restore WFO5001 -AonprdImporter importer = new(); - -// importer.ProcessorNames = ["rules", "rules-order"]; - -importer.Prepare(); -importer.Import(); -// importer.BuildSchemas(); + Application.Run(new ImportApplication()); + } +} diff --git a/Pf2eViewer/Pf2eViewer.csproj b/Pf2eViewer/Pf2eViewer.csproj index d479e08..973136e 100644 --- a/Pf2eViewer/Pf2eViewer.csproj +++ b/Pf2eViewer/Pf2eViewer.csproj @@ -26,7 +26,4 @@ Settings.Designer.cs - - -