diff --git a/Pf2eDataScrapper/App/Attributes.cs b/Pf2eDataScrapper/App/Attributes.cs deleted file mode 100644 index df60b8b..0000000 --- a/Pf2eDataScrapper/App/Attributes.cs +++ /dev/null @@ -1,62 +0,0 @@ -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/ProcessorAttribute.cs b/Pf2eDataScrapper/App/ProcessorAttribute.cs new file mode 100644 index 0000000..e1b0d7b --- /dev/null +++ b/Pf2eDataScrapper/App/ProcessorAttribute.cs @@ -0,0 +1,42 @@ +namespace Pf2eDataScrapper.App; + +/// +/// Общий аттрибут обработчика. +/// +/// Название обработчика. +[AttributeUsage(AttributeTargets.Class)] +public class ProcessorAttribute(string name) : Attribute +{ + /// + /// Название обработчика. + /// + public string Name { get; init; } = name; + + /// + /// Описание обработчика. + /// + public string Description { get; init; } = name; + + /// + /// Группа обработчиков, к которому относится обработчик. + /// + public ProcessorGroupEnum Group { get; init; } = ProcessorGroupEnum.General; + + /// + /// Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика. + /// + public string? InnerType { get; init; } = null; +} + +/// +/// Аттрибут зависимостей обработчика. +/// +/// Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика. +[AttributeUsage(AttributeTargets.Class)] +public class ProcessorDependenciesAttribute(string[] dependencies) : Attribute +{ + /// + /// Коллекция названий обработчиков, которые должны быть выполнены до этого оброботчика. + /// + public ICollection Dependencies { get; } = dependencies; +} diff --git a/Pf2eDataScrapper/App/ProcessorCollection.cs b/Pf2eDataScrapper/App/ProcessorCollection.cs index ffea206..7dbae40 100644 --- a/Pf2eDataScrapper/App/ProcessorCollection.cs +++ b/Pf2eDataScrapper/App/ProcessorCollection.cs @@ -29,7 +29,7 @@ internal class ProcessorCollection foreach (Type type in assembly.GetTypes()) { - if (type.GetCustomAttributes(typeof(ProcessAttribute), true).Length <= 0) + if (type.GetCustomAttributes(typeof(ProcessorAttribute), true).Length <= 0) { continue; } @@ -51,21 +51,15 @@ internal class ProcessorCollection if (!type.IsSubclassOf(typeof(IProcessor))) { throw new( - $"'ProcessAttribute' attribute should only be applied to children of 'IProcessor' class. '{type.FullName}' is not." + $"'ProcessorAttribute' attribute should only be applied to children of 'IProcessor' class. '{type.FullName}' is not." ); } - ProcessAttribute processAttribute = type.GetCustomAttribute()!; - DescriptionAttribute? descriptionAttribute = - type.GetCustomAttribute(); - ProcessorGroupAttribute? groupAttribute = - type.GetCustomAttribute(); + ProcessorAttribute processorAttribute = type.GetCustomAttribute()!; ProcessorDependenciesAttribute? dependenciesAttribute = type.GetCustomAttribute(); - ProcessorInnerTypeAttribute? innerTypeAttribute = - type.GetCustomAttribute(); - bool isCollection = innerTypeAttribute is not null; + bool isCollection = processorAttribute.InnerType is not null; ConstructorInfo? constructor = isCollection ? type.GetConstructor([]) @@ -78,13 +72,13 @@ internal class ProcessorCollection return new() { - Name = processAttribute.Name, + Name = processorAttribute.Name, Type = type, - Description = descriptionAttribute?.Description ?? processAttribute.Name, - Group = groupAttribute?.Group ?? ProcessorGroupEnum.General, + Description = processorAttribute.Description, + Group = processorAttribute.Group, Dependencies = dependenciesAttribute?.Dependencies ?? [], IsCollectionProcessor = isCollection, - InnerType = innerTypeAttribute?.InnerType, + InnerType = processorAttribute.InnerType, Constructor = constructor, }; } diff --git a/Pf2eDataScrapper/Forms/StartForm.Designer.cs b/Pf2eDataScrapper/Forms/StartForm.Designer.cs index 387245b..31eb6f5 100644 --- a/Pf2eDataScrapper/Forms/StartForm.Designer.cs +++ b/Pf2eDataScrapper/Forms/StartForm.Designer.cs @@ -31,11 +31,11 @@ partial class StartForm MainSplitContainer = new SplitContainer(); PropertiesGroupBox = new GroupBox(); SettingsPropertyGrid = new PropertyGrid(); - StartButton = new Button(); ProcessorsGroupBox = new GroupBox(); - DeselectAllButton = new Button(); - SelectAllButton = new Button(); ProcessorsListView = new ListView(); + SelectAllButton = new Button(); + DeselectAllButton = new Button(); + StartButton = new Button(); ((System.ComponentModel.ISupportInitialize)MainSplitContainer).BeginInit(); MainSplitContainer.Panel1.SuspendLayout(); MainSplitContainer.Panel2.SuspendLayout(); @@ -84,17 +84,6 @@ partial class StartForm SettingsPropertyGrid.Size = new Size(288, 649); SettingsPropertyGrid.TabIndex = 0; // - // StartButton - // - StartButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; - StartButton.Font = new Font("Segoe UI", 18F, FontStyle.Bold); - StartButton.Location = new Point(3, 611); - StartButton.Name = "StartButton"; - StartButton.Size = new Size(621, 63); - StartButton.TabIndex = 0; - StartButton.Text = "Запуск"; - StartButton.UseVisualStyleBackColor = true; - // // ProcessorsGroupBox // ProcessorsGroupBox.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; @@ -108,24 +97,6 @@ partial class StartForm ProcessorsGroupBox.TabStop = false; ProcessorsGroupBox.Text = "Обработчики"; // - // DeselectAllButton - // - DeselectAllButton.Location = new Point(6, 19); - DeselectAllButton.Name = "DeselectAllButton"; - DeselectAllButton.Size = new Size(137, 23); - DeselectAllButton.TabIndex = 0; - DeselectAllButton.Text = "Снять выделение всех"; - DeselectAllButton.UseVisualStyleBackColor = true; - // - // SelectAllButton - // - SelectAllButton.Location = new Point(149, 19); - SelectAllButton.Name = "SelectAllButton"; - SelectAllButton.Size = new Size(137, 23); - SelectAllButton.TabIndex = 1; - SelectAllButton.Text = "Выделить все"; - SelectAllButton.UseVisualStyleBackColor = true; - // // ProcessorsListView // ProcessorsListView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; @@ -136,6 +107,35 @@ partial class StartForm ProcessorsListView.TabIndex = 2; ProcessorsListView.UseCompatibleStateImageBehavior = false; // + // SelectAllButton + // + SelectAllButton.Location = new Point(149, 19); + SelectAllButton.Name = "SelectAllButton"; + SelectAllButton.Size = new Size(137, 23); + SelectAllButton.TabIndex = 1; + SelectAllButton.Text = "Выделить все"; + SelectAllButton.UseVisualStyleBackColor = true; + // + // DeselectAllButton + // + DeselectAllButton.Location = new Point(6, 19); + DeselectAllButton.Name = "DeselectAllButton"; + DeselectAllButton.Size = new Size(137, 23); + DeselectAllButton.TabIndex = 0; + DeselectAllButton.Text = "Снять выделение всех"; + DeselectAllButton.UseVisualStyleBackColor = true; + // + // StartButton + // + StartButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + StartButton.Font = new Font("Segoe UI", 18F, FontStyle.Bold); + StartButton.Location = new Point(3, 611); + StartButton.Name = "StartButton"; + StartButton.Size = new Size(621, 63); + StartButton.TabIndex = 0; + StartButton.Text = "Запуск"; + StartButton.UseVisualStyleBackColor = true; + // // StartForm // AutoScaleDimensions = new SizeF(7F, 15F); @@ -144,6 +144,7 @@ partial class StartForm Controls.Add(MainSplitContainer); Name = "StartForm"; Text = "Настройки импорта данных"; + Load += StartForm_Load; MainSplitContainer.Panel1.ResumeLayout(false); MainSplitContainer.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)MainSplitContainer).EndInit(); diff --git a/Pf2eDataScrapper/Forms/StartForm.cs b/Pf2eDataScrapper/Forms/StartForm.cs index 70bbf4d..58811ff 100644 --- a/Pf2eDataScrapper/Forms/StartForm.cs +++ b/Pf2eDataScrapper/Forms/StartForm.cs @@ -1,9 +1,64 @@ -namespace Pf2eDataScrapper.Forms; +using System.ComponentModel; +using System.Reflection; +using Pf2eDataScrapper.App; -public partial class StartForm : Form +namespace Pf2eDataScrapper.Forms; + +internal partial class StartForm : Form { - public StartForm() + private readonly ProcessorCollection _processorCollection; + + public StartForm(ProcessorCollection processorCollection) { InitializeComponent(); + + _processorCollection = processorCollection; + } + + private void StartForm_Load(object sender, EventArgs e) + { + PopulateListView(); + } + + private void PopulateListView() + { + Dictionary> 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? 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); + } + } } } diff --git a/Pf2eDataScrapper/Importers/DatabaseHelper.cs b/Pf2eDataScrapper/Helpers/DatabaseHelper.cs similarity index 98% rename from Pf2eDataScrapper/Importers/DatabaseHelper.cs rename to Pf2eDataScrapper/Helpers/DatabaseHelper.cs index 420a102..7b0960e 100644 --- a/Pf2eDataScrapper/Importers/DatabaseHelper.cs +++ b/Pf2eDataScrapper/Helpers/DatabaseHelper.cs @@ -1,7 +1,7 @@ using Pf2eModel; using Slugify; -namespace Pf2eDataScrapper.Importers; +namespace Pf2eDataScrapper.Helpers; /// /// Класс предоставляет методы для работы с базой данных. diff --git a/Pf2eDataScrapper/ImportApplication.cs b/Pf2eDataScrapper/ImportApplication.cs index 18cf2ee..16b8671 100644 --- a/Pf2eDataScrapper/ImportApplication.cs +++ b/Pf2eDataScrapper/ImportApplication.cs @@ -1,6 +1,10 @@ using Microsoft.Extensions.DependencyInjection; using Pf2eDataScrapper.App; using Pf2eDataScrapper.Forms; +using Pf2eDataScrapper.Importers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd; +using Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry; +using Pf2eDataScrapper.Processors; using Pf2eModel; namespace Pf2eDataScrapper; @@ -15,23 +19,27 @@ internal sealed class ImportApplication : ApplicationContext #region "Внедрение зависимостей (DI)" - public IServiceCollection Services = new ServiceCollection(); + public readonly IServiceCollection Services = new ServiceCollection(); + + public IServiceProvider ServiceProvider { get; private set; } = null!; private void InitializeServices() { Services.AddSingleton(this); Services.AddSingleton(Settings); - - Services.AddSingleton(); + Services.AddSingleton(Processors); Services.AddDbContext(); + + ServiceProvider = Services.BuildServiceProvider(); } #endregion #region "Настройки" - public ApplicationSettings Settings = new(); + public readonly ApplicationSettings Settings = new(); + public readonly ProcessorCollection Processors = new(); #endregion @@ -45,13 +53,73 @@ internal sealed class ImportApplication : ApplicationContext private void CreateStartForm() { - _startForm = new() { StartPosition = FormStartPosition.CenterParent }; + _startForm = ActivatorUtilities.CreateInstance(ServiceProvider); + _startForm.StartPosition = FormStartPosition.CenterParent; _startForm.Show(); } private void StartProcess() { _startForm!.Close(); + + Processors.SortItems(); + + ProcessProgress progress = new ProcessProgress(); + + foreach (ProcessorCollectionItem item in Processors.Items) + { + if (item.IsCollectionProcessor) + { + RunCollection(item, progress); + } + else + { + RunSingle(item, progress); + } + } + } + + private void RunSingle(ProcessorCollectionItem item, ProcessProgress progress) + { + progress.Local.Reset(1); + progress.Local.Start(""); + + IProcessor processor = (IProcessor) + ActivatorUtilities.CreateInstance(ServiceProvider, item.Type); + + processor.Process(); + processor.Save(); + + progress.Local.Complete(); + } + + private void RunCollection(ProcessorCollectionItem item, ProcessProgress progress) + { + AbstractImporter importer = item.Group switch + { + ProcessorGroupEnum.AonprdPreparation + or ProcessorGroupEnum.AonprdEntities + or ProcessorGroupEnum.AonprdSubclasses => new AonprdImporter(), + ProcessorGroupEnum.FoundryEnPreparation => new Pf2EFoundryImporter(), + _ => throw new("Can't recognize importer"), + }; + + progress.Local.Reset(importer.CountInputs(item.InnerType!)); + + foreach (ProcessorInput input in importer.ResolveInputs(item.InnerType!)) + { + progress.Local.Start(input.Name); + + IProcessor processor = (IProcessor) + ActivatorUtilities.CreateInstance(ServiceProvider, item.Type); + + processor.Process(); + processor.Save(); + + progress.Local.End(); + } + + progress.Local.Complete(); } #endregion diff --git a/Pf2eDataScrapper/Importers/AbstractImporter.cs b/Pf2eDataScrapper/Importers/AbstractImporter.cs index fcddf09..ae2cc29 100644 --- a/Pf2eDataScrapper/Importers/AbstractImporter.cs +++ b/Pf2eDataScrapper/Importers/AbstractImporter.cs @@ -1,4 +1,5 @@ using Pf2eDataScrapper.Importers.Repositories; +using Pf2eDataScrapper.Processors; namespace Pf2eDataScrapper.Importers; @@ -36,15 +37,32 @@ internal abstract class AbstractImporter /// /// Метод подготовки данных для импорта. /// + [Obsolete] public abstract void Prepare(); /// /// Импорт данных /// + [Obsolete] public abstract void Import(); /// /// Построение схем данных. /// + [Obsolete] public abstract void BuildSchemas(); + + /// + /// Получение количества записей, принаделажащих типу . + /// + /// Тип записей. + /// Количество записей. + public abstract int CountInputs(string type); + + /// + /// Итератор ввода для записей, принаделажащих типу . + /// + /// Тип записей. + /// Итератор. + public abstract IEnumerable ResolveInputs(string type); } diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdImporter.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdImporter.cs index b6443dc..114573e 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdImporter.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdImporter.cs @@ -1,6 +1,8 @@ -using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder; -using Pf2eDataScrapper.Importers.Implementations.Aonprd.SchemaBuilder; +using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder; using Pf2eDataScrapper.Importers.Repositories; +using Pf2eDataScrapper.Processors; namespace Pf2eDataScrapper.Importers.Implementations.Aonprd; @@ -9,6 +11,11 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd; /// internal class AonprdImporter : AbstractImporter { + /// + /// Название внешней ссылки. + /// + public const string TargetName = "Archives of Nethys Pathfinder 2e"; + /// public override string Name => TargetName; @@ -16,8 +23,7 @@ internal class AonprdImporter : AbstractImporter public override string Slug => "aonprd"; /// - public override AbstractImporterRepository Repository => - new AonprdRepository(this, "https://elasticsearch.aonprd.com"); + public override AbstractImporterRepository Repository { get; } /// /// Инструмент для работы с данными сайта Архивов Нефеса. @@ -29,37 +35,47 @@ internal class AonprdImporter : AbstractImporter /// public AonprdImporter() { + Repository = new AonprdRepository(this, "https://elasticsearch.aonprd.com"); Loader = new(this); } /// - public override void Prepare() + public override void Prepare() { } + + /// + public override void BuildSchemas() { } + + /// + public override void Import() { } + + /// + public override int CountInputs(string type) { - Repository.Update(); - Loader.Prepare(); + return Loader.Compendium.Count(type); } /// - public override void BuildSchemas() + public override IEnumerable ResolveInputs(string type) { - AonprdSchemaBuilder builder = new(Loader); + foreach (string file in Loader.Compendium.Files(type)) + { + using StreamReader fileReader = new(Path.Combine(Dir, $"{file}.json")); + JArray array = JArray.Parse(fileReader.ReadToEnd()); - builder.BuildSchemas(); - builder.Save(EnvSettings.OutputDir); + foreach (JToken item in array) + { + string? id = item.SelectToken("id")?.ToString(); + + if (id is null) + { + continue; + } + + if (AonprdReference.ResolveType(id) == type) + { + yield return new AonprdProcessorInput(id, (JObject)item); + } + } + } } - - /// - public override void Import() - { - AonprdDataBuilder builder = new(Loader); - builder.Processors.UseOnlyNames(ProcessorNames); - - builder.TruncateTables(); - builder.Build(); - } - - /// - /// Название внешней ссылки. - /// - public const string TargetName = "Archives of Nethys Pathfinder 2e"; } diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorInput.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdProcessorInput.cs similarity index 95% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorInput.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdProcessorInput.cs index d2fde33..31b6bcd 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorInput.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdProcessorInput.cs @@ -1,14 +1,14 @@ using Newtonsoft.Json.Linq; -using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; using Pf2eDataScrapper.Processors; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd; /// /// Класс для работы с JSON-объектом при обработки данных с Архивов Нефиса. /// /// JSON-объект, который будет использоваться для доступа к данным. -internal class AonprdProcessorInput(JObject input) : ProcessorInput(input) +internal class AonprdProcessorInput(string name, JObject input) : ProcessorInput(name, input) { /// public override T Enum(string value) diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdRepository.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdRepository.cs index ba05d9b..0a21ba3 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdRepository.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/AonprdRepository.cs @@ -1,6 +1,7 @@ using Konsole; using Newtonsoft.Json.Linq; using Pf2eDataScrapper.Importers.Repositories; +using Pf2eDataScrapper.Processors; namespace Pf2eDataScrapper.Importers.Implementations.Aonprd; @@ -38,18 +39,21 @@ internal class AonprdRepository(AbstractImporter importer, string searchUrl) } /// - public override void Update() + public override void Update(ProcessProgress progress) { if (CheckRevision()) { - Console.WriteLine($"Данные Aonprd актуальны, текущая ревизия {Revision}."); + progress.Local.Complete(); + progress.Message($"Данные Aonprd актуальны, текущая ревизия {Revision}."); return; } - Console.WriteLine( + progress.Message( $"Данные Aonprd устарели, обновляем {RepositoryDirPath} до ревизии {Revision}..." ); + progress.Local.Reset(1); + if (Directory.Exists(RepositoryDirPath)) { Directory.Delete(RepositoryDirPath, true); @@ -58,27 +62,28 @@ internal class AonprdRepository(AbstractImporter importer, string searchUrl) WriteFile("revision.txt", Revision.ToString()); - Console.WriteLine("Загрузка индекса..."); + progress.Local.Start("Загрузка индекса..."); + string indexContent = Load($"/json-data/aon{Revision}-index.json"); WriteFile("index.json", indexContent); JObject indexJson = JObject.Parse(indexContent); - Console.WriteLine("Загрузка индексных файлов..."); - - ProgressBar bar = new(indexJson.Count); - int i = 0; + progress.Local.Reset(indexJson.Count + 1); + progress.Local.End(); foreach (KeyValuePair kvp in indexJson) { string fileName = kvp.Key; - bar.Refresh(i++, fileName); + progress.Local.Start(fileName); string fileContent = Load($"/json-data/{fileName}.json"); WriteFile($"{fileName}.json", fileContent); + + progress.Local.End(); } - bar.Refresh(indexJson.Count, "Готово!"); + progress.Local.Complete(); } /// diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdCompendium.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdCompendium.cs index e7df834..4b5242c 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdCompendium.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdCompendium.cs @@ -35,18 +35,32 @@ internal class AonprdCompendium /// Количество элементов. public int Count() => Types.Values.Sum(t => t.Count); + /// + /// Возвращает количество элементов для указанного типа данных. + /// + /// Тип данных. + /// Количество элементов. + public int Count(string type) => Types.Values.First(t => t.Type == type).Count; + /// /// Возвращает количество элементов для указанных типов данных. /// - /// Список типов. + /// Список типов данных. /// Количество элементов. public int Count(IEnumerable types) => Types.Values.Where(t => types.Contains(t.Type)).Sum(t => t.Count); + /// + /// Возвращает список файлов для выбора сущностей указанного типа данных. + /// + /// Тип данных. + /// Список искомых файлов. + public IEnumerable Files(string type) => Types.Values.First(t => t.Type == type).Files; + /// /// Возвращает список файлов для выбора сущностей указанных типов данных. /// - /// Список типов. + /// Список типов данных. /// Список искомых файлов. public IEnumerable Files(IEnumerable types) => Types.Values.Where(t => types.Contains(t.Type)).SelectMany(t => t.Files).Distinct(); diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdReference.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdReference.cs index 98ebbdd..c1fcd51 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdReference.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdReference.cs @@ -25,7 +25,7 @@ internal class AonprdReference(string id, string file) /// /// Определение типа сущности как префикса идентификатора. /// - private static string ResolveType(string id) + public static string ResolveType(string id) { string type = string.Join('-', id.Split('-')[..^1]); diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdType.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdType.cs index 8f43ff7..e55f1b8 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdType.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Compendium/AonprdType.cs @@ -1,8 +1,7 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium; /// -/// Класс AonprdType представляет собой уникальный тип данных, связанный с Aon (Advanced Opportunity Network). -/// Это основной класс, который хранит информацию о различных элементах системы. +/// Класс типа элементов с Архива Нефиса. /// internal class AonprdType(string type) { diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdDataBuilder.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdDataBuilder.cs deleted file mode 100644 index ae02027..0000000 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdDataBuilder.cs +++ /dev/null @@ -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; - -/// -/// Класс для создание схемы данных Архива Нефиса. -/// -/// -internal class AonprdDataBuilder(AonprdLoader loader) -{ - /// - /// Основной класс для работы с данными Архива Нефиса. - /// - public readonly AonprdLoader Loader = loader; - - /// - /// Коллекция папок компендиума. - /// - public AonprdCompendium Compendium => Loader.Compendium; - - /// - /// Коллекция обработчиков данных. - /// - public readonly AonprdProcessorCollection Processors = new(); - - /// - /// Очистить таблицы в базе данных. - /// - 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!"); - } - - /// - /// Конфигурация интерфейса вывода результатов. - /// - protected ConcurrentWriter Window = null!; - - /// - /// Основное окно для вывода информации. - /// - protected Window Output = null!; - - /// - /// Полоса прогресса для основного процесса обработки данных. - /// - protected ProgressBar ProcessProgressBar = null!; - - /// - /// Полоса прогресса для под-процессов обработки данных. - /// - protected ProgressBar SubProcessProgressBar = null!; - - /// - /// Метод для настройки интерфейса. - /// - protected void ConfigureWindow() - { - Window = new Window(0, 0, Console.WindowWidth, Console.WindowHeight).Concurrent(); - - 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); - } - - /// - /// Обработка отдельного процессора данных. - /// - 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); - } - } - - /// - /// Полная обработка и сохранение данных. - /// - 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(); - } -} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorAttribute.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorAttribute.cs deleted file mode 100644 index 301d742..0000000 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorAttribute.cs +++ /dev/null @@ -1,62 +0,0 @@ -using Pf2eDataScrapper.App.Attributes; - -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder; - -/// -/// Атрибут обработчика данных Архивов Нефиса. -/// -[AttributeUsage(AttributeTargets.Class)] -public class AonprdProcessorAttribute : Attributes -{ - /// - /// Важные общие зависимости для обработчка. - /// - private static readonly string[] DefaultDependencies = ["aonprd:trait", "aonprd:source"]; - - /// - /// Тип данных, которые обработчик обрабатывает. - /// - public string Type { get; init; } - - /// - /// Конструктор класса со стандартными общими зависимости для обработчка. - /// - /// Тип данных, которые обработчик обрабатывает. Также будет использоваться в качестве названия. - public AonprdProcessorAttribute(string type) - : this(type, type, DefaultDependencies) { } - - /// - /// Конструктор класса . - /// - /// Тип данных, которые обработчик обрабатывает. Также будет использоваться в качестве названия. - /// Названия обработчиков, которые должны быть выполнены до запуска этого обработчика. - /// Флаг, указывающий, следует ли добавить важные общие зависимости для обработчка. - public AonprdProcessorAttribute(string type, string[] dependencies, bool includeDefaults = true) - : this(type, type, dependencies, includeDefaults) { } - - /// - /// Конструктор класса со стандартными общими зависимости для обработчка. - /// - /// Название обработчика. - /// Тип данных, которые обработчик обрабатывает. - public AonprdProcessorAttribute(string name, string type) - : this(name, type, DefaultDependencies) { } - - /// - /// Основной конструктор класса . - /// - /// Название обработчика. - /// Тип данных, которые обработчик обрабатывает. - /// Названия обработчиков, которые должны быть выполнены до запуска этого обработчика. - /// Флаг, указывающий, следует ли добавить важные общие зависимости для обработчка. - 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 deleted file mode 100644 index 4ec1ccf..0000000 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/AonprdProcessorCollection.cs +++ /dev/null @@ -1,187 +0,0 @@ -using System.Reflection; -using Pf2eDataScrapper.Processors; - -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder; - -/// -/// Класс отвечает за управление обработчиками, отмеченных атрибутом . -/// -internal class AonprdProcessorCollection -{ - /// - /// Элемент коллекции обработчика. - /// - /// Атрибут, связанный с обаботчиком. - /// Конструктор обработчика. - public class ProcessorItem(AonprdProcessorAttribute attribute, ConstructorInfo constructor) - { - /// - /// Атрибут, связанный с обаботчиком. - /// - public readonly AonprdProcessorAttribute Attribute = attribute; - - /// - /// Конструктор обработчика. - /// - public readonly ConstructorInfo Constructor = constructor; - - /// - /// Приоритет выполнения обработчика. - /// - public int Priority = -1; - } - - /// - /// Список всех объявленных обработчиков. - /// - private readonly List _allItems; - - /// - /// Список используемых обработчиков. - /// - public List Items { get; private set; } = []; - - /// - /// Конструктор класса , загружающий все обработчики. - /// - public AonprdProcessorCollection() - { - foreach (Type type in Assembly.GetExecutingAssembly().GetTypes()) - { - 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()!; - - 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(); - } - - /// - /// Проверка, что все зависимости всех обработчиков могут быть удовлетворены. - /// - 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." - ); - } - } - } - } - - /// - /// Сортировать обработчики в соответсвии со всеми зависимостями. - /// - private void SortItems() - { - CheckDependencies(); - - Dictionary priorities = []; - - while (priorities.Count < Items.Count) - { - foreach (ProcessorItem item in Items) - { - if (item.Priority > 0) - { - continue; - } - - IEnumerable 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); - } - - /// - /// Итерация через все используемые обработчики. - /// - /// Итератор. - public IEnumerable Iterate() - { - SortItems(); - - foreach (ProcessorItem item in Items) - { - yield return item; - } - } - - /// - /// Ограничить список используемых обработчиков по названию. - /// Автоматически включает все обработчики, от которых зависят указанные в аргументе обработчики. - /// - /// Коллекция названиий требуемых обработчиков. - public void UseOnlyNames(ICollection processorNames) - { - if (processorNames.Count == 0) - { - Items = _allItems; - return; - } - - Dictionary nameFlags = processorNames.ToDictionary(name => name, _ => false); - - while (nameFlags.Values.Any(v => !v)) - { - foreach ( - KeyValuePair 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(); - } -} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/ExternalProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/ExternalProcessor.cs deleted file mode 100644 index 18508df..0000000 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/ExternalProcessor.cs +++ /dev/null @@ -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; - } -} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/ArchetypeProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/ArchetypeProcessor.cs deleted file mode 100644 index a4f5c0b..0000000 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/ArchetypeProcessor.cs +++ /dev/null @@ -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) -{ - /// - public override EntityType Type => EntityType.Archetype; - - /// - public override Archetype Object { get; } = new(); - - /// - public override void Add() => Context.Archetypes.Add(Object); - - /// - public override void Process() - { - base.Process(); - - Object.Level = Input.GetOptional("level"); - } - - /// - protected override string[] AddedDescriptionPaths() => - ["prerequisite_markdown", "requirement_markdown", "summary_markdown"]; -} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/LanguageProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/LanguageProcessor.cs deleted file mode 100644 index 206746f..0000000 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/LanguageProcessor.cs +++ /dev/null @@ -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) -{ - /// - public override EntityType Type => EntityType.Language; - - /// - public override Language Object { get; } = new(); - - /// - public override void Add() => Context.Languages.Add(Object); -} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/TraitProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/TraitProcessor.cs deleted file mode 100644 index a2d729f..0000000 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/TraitProcessor.cs +++ /dev/null @@ -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) -{ - /// - public override EntityType Type => EntityType.Trait; - - /// - public override Trait Object { get; } = new(); - - /// - public override void Add() => Context.Traits.Add(Object); - - /// - public override void Process() - { - base.Process(); - - Object.Type = TraitType.Regular; - - Context.Traits.Add(Object); - } - - /// - protected override void AddTraits() - { - // Необходимо пропускать - } - - /// - protected override string GetDescription() => - base.GetDescription() + AddedDescription(["summary_markdown", "search_markdown"]); -} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdBuilderGlobals.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/AonprdBuilderGlobals.cs similarity index 90% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdBuilderGlobals.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/AonprdBuilderGlobals.cs index def6837..f065e5b 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdBuilderGlobals.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/AonprdBuilderGlobals.cs @@ -1,6 +1,6 @@ using Pf2eModel.Model.Base.Targets; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; /// /// Класс-помощник, хранящий необходимые глобальные данные. diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdEnumResolver.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/AonprdEnumResolver.cs similarity index 98% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdEnumResolver.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/AonprdEnumResolver.cs index e4f395c..1f43999 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/AonprdEnumResolver.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/AonprdEnumResolver.cs @@ -1,6 +1,6 @@ using Pf2eModel.Model.Enum; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; /// /// Класс, помогающий разрешить строковые значения с Архивов Нефиса в перечисления. diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/LegacyEntityHandler.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/LegacyEntityHandler.cs similarity index 96% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/LegacyEntityHandler.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/LegacyEntityHandler.cs index d5cfc57..240b5ff 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/LegacyEntityHandler.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/LegacyEntityHandler.cs @@ -1,9 +1,10 @@ using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors; using Pf2eModel.Model.Base; using Pf2eModel.Model.Base.Source; using Pf2eModel.Model.Common.I18n; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; /// /// Обработчик сущностей, помеченных как устаревшие. diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RuleToc.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/RuleToc.cs similarity index 99% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RuleToc.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/RuleToc.cs index 7d59e6c..6ab17bc 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RuleToc.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/RuleToc.cs @@ -1,6 +1,6 @@ using Pf2eModel.Model.Base.Source; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types.Rules; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; /// /// Класс коллекции книг, содержащих правила. diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/StringHelper.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/StringHelper.cs similarity index 100% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Helpers/StringHelper.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/StringHelper.cs diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractEntityProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractEntityProcessor.cs similarity index 93% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractEntityProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractEntityProcessor.cs index 03f14a5..c0ad18f 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractEntityProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractEntityProcessor.cs @@ -3,6 +3,10 @@ using System.Text; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; using Pf2eDataScrapper.Processors; using Pf2eModel; using Pf2eModel.Model; @@ -13,18 +17,28 @@ using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Enum; using Pf2eModel.Model.Structure; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors; /// /// Абстрактный класс-обработчик сущностей, полученных из Архивов Нефиса. /// Класс предназначен для обработки данных с помощью различных обработчиков, -/// для которых указан атрибут . +/// для которых указан атрибут . /// /// Объект обработки вводимого JSON. -/// -internal abstract class AbstractEntityProcessor(AonprdProcessorInput input) - : AbstractProcessor(input) +/// +internal abstract class AbstractEntityProcessor( + AonprdProcessorInput input, + Pf2eDbContext context, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractInputProcessor(input) { + public Pf2eDbContext Context { get; } = context; + public StringHelper StringHelper { get; } = stringHelper; + public DatabaseHelper Helper { get; } = helper; + public AonprdBuilderGlobals Globals { get; } = globals; + /// /// Корневая сущность. /// diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractSubclassProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractSubclassProcessor.cs similarity index 81% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractSubclassProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractSubclassProcessor.cs index df85831..03e0bc6 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/AbstractSubclassProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractSubclassProcessor.cs @@ -1,20 +1,27 @@ -using Pf2eModel; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; +using Pf2eModel; using Pf2eModel.Model.Base; using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Enum; using Pf2eModel.Model.Structure; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors; /// /// Абстрактный класс-обработчик сущностей подклассов, полученных из Архивов Нефиса. /// Класс предназначен для обработки данных с помощью различных обработчиков, -/// для которых указан атрибут . +/// для которых указан атрибут . /// -/// Объект обработки вводимого JSON. -/// -internal abstract class AbstractSubclassProcessor(AonprdProcessorInput input) - : AbstractEntityProcessor(input) +internal abstract class AbstractSubclassProcessor( + AonprdProcessorInput input, + Pf2eDbContext context, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) { /// public override EntityType Type => EntityType.Subclass; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/AonprdRepositoryUpdateProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/AonprdRepositoryUpdateProcessor.cs new file mode 100644 index 0000000..d4c921d --- /dev/null +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/AonprdRepositoryUpdateProcessor.cs @@ -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(); + } +} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/SchemaBuilder/AonprdSchemaBuilder.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/AonprdSchemaBuildProcessor.cs similarity index 76% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/SchemaBuilder/AonprdSchemaBuilder.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/AonprdSchemaBuildProcessor.cs index 3551a72..8d09197 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/SchemaBuilder/AonprdSchemaBuilder.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/AonprdSchemaBuildProcessor.cs @@ -1,24 +1,29 @@ -using Konsole; -using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Processors; using Pf2eDataScrapper.SchemaBuilder; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.SchemaBuilder; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common; -/// -/// Класс создания схемы данных с сайта Архивов Нефеса. -/// -/// Загузчик данных с сайта Архивов Нефеса. -internal class AonprdSchemaBuilder(AonprdLoader loader) +[Processor( + "aonprd:schema", + Description = "Построение схемы данных", + Group = ProcessorGroupEnum.AonprdPreparation +)] +[ProcessorDependencies(["aonprd:repository"])] +internal class AonprdSchemaBuildProcessor( + AonprdImporter importer, + ProcessProgress progress, + ApplicationSettings settings +) : IProcessor { + public AonprdImporter Importer { get; } = importer; + public ProcessProgress Progress { get; } = progress; + public ApplicationSettings Settings { get; } = settings; + /// /// Загузчик данных с сайта Архивов Нефеса. /// - public readonly AonprdLoader Loader = loader; - - /// - public readonly AonprdCompendium Compendium = loader.Compendium; - - // public readonly AonprdSchemaTypeResolver Resolver = new(); + public AonprdLoader Loader => Importer.Loader; /// /// Дополнительные схемы данных. @@ -28,6 +33,44 @@ internal class AonprdSchemaBuilder(AonprdLoader loader) ["_subclass"] = new() { Path = "_subclass" }, }; + /// + /// Построение схемы данных. + /// + 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(); + } + + /// + /// Сохранение постренных схем данных. + /// + public void Save() + { + string targetDir = Settings.OutputDir; + + targetDir = Path.Combine(targetDir, Loader.Importer.Slug); + + foreach (KeyValuePair kvp in Schemas) + { + SaveSchema(targetDir, kvp.Key, kvp.Value); + } + } + /// /// Список типов, являющихся подклассами. /// @@ -87,50 +130,6 @@ internal class AonprdSchemaBuilder(AonprdLoader loader) return value; } - /// - /// Построение схемы данных. - /// - 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!"); - } - - /// - /// Сохранение постренных схем данных. - /// - /// Целевой каталог. - 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 kvp in Schemas) - { - bar.Refresh(i++, kvp.Key); - SaveSchema(targetDir, kvp.Key, kvp.Value); - } - } - /// /// Сохранение отдельной схемы данных. /// diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/ExternalProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/ExternalProcessor.cs new file mode 100644 index 0000000..c5f99cf --- /dev/null +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/ExternalProcessor.cs @@ -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; + } +} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SkillProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/SkillProcessor.cs similarity index 51% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SkillProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/SkillProcessor.cs index f0b6ef4..dcf3081 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SkillProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/SkillProcessor.cs @@ -1,13 +1,23 @@ -using Pf2eDataScrapper.Processors; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Processors; +using Pf2eModel; using Pf2eModel.Model.Common; using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Enum; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common; -[AonprdProcessor("skill", [], false)] -internal class SkillProcessor(AonprdProcessorInput input) : AbstractProcessor(input) +[Processor( + "aonprd:skill", + InnerType = "skill", + Description = "Создание цели внешних ссылок", + Group = ProcessorGroupEnum.AonprdPreparation +)] +internal class SkillProcessor(AonprdProcessorInput input, Pf2eDbContext context) + : AbstractInputProcessor(input) { + public Pf2eDbContext Context { get; } = context; + /// /// Обучаемый объект. /// diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SourceProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/SourceProcessor.cs similarity index 52% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SourceProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/SourceProcessor.cs index 1cd6a68..3cea58e 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Common/SourceProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Common/SourceProcessor.cs @@ -1,12 +1,23 @@ -using Pf2eDataScrapper.Processors; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Processors; +using Pf2eModel; using Pf2eModel.Model.Base.Source; using Pf2eModel.Model.Enum; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common; -[AonprdProcessor("source", [], false)] -internal class SourceProcessor(AonprdProcessorInput input) : AbstractProcessor(input) +[Processor( + "aonprd:source", + InnerType = "source", + Description = "Создание цели внешних ссылок", + Group = ProcessorGroupEnum.AonprdPreparation +)] +[ProcessorDependencies(["aonprd:repository"])] +internal class SourceProcessor(AonprdProcessorInput input, Pf2eDbContext context) + : AbstractInputProcessor(input) { + public Pf2eDbContext Context { get; } = context; + /// /// Источник сущности. /// diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Subclasses/ApparitionProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Subclasses/ApparitionProcessor.cs similarity index 71% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Subclasses/ApparitionProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Subclasses/ApparitionProcessor.cs index b89bf55..c66bc42 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Subclasses/ApparitionProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Subclasses/ApparitionProcessor.cs @@ -1,14 +1,32 @@ -using Pf2eModel; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; +using Pf2eModel; using Pf2eModel.Model.Base; using Pf2eModel.Model.Common; using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Enum; using Pf2eModel.Model.Structure; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Subclasses; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Subclasses; -[AonprdProcessor("apparition", ["class", "spell", "skill"])] -internal class ApparitionProcessor(AonprdProcessorInput input) : AbstractSubclassProcessor(input) +[Processor( + "aonprd:apparition", + InnerType = "apparition", + Description = "Создание цели внешних ссылок", + Group = ProcessorGroupEnum.AonprdSubclasses +)] +[ProcessorDependencies( + ["aonprd:trait", "aonprd:source", "aonprd:class", "aonprd:spell", "aonprd:skill"] +)] +internal class ApparitionProcessor( + AonprdProcessorInput input, + Pf2eDbContext context, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractSubclassProcessor(input, context, stringHelper, helper, globals) { /// public override Subclass Object { get; } = new(); diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/ActionProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/ActionProcessor.cs similarity index 55% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/ActionProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/ActionProcessor.cs index 8fd6b55..86eac1d 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/ActionProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/ActionProcessor.cs @@ -1,9 +1,26 @@ -using Pf2eModel.Model.Enum; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; +using Pf2eModel; +using Pf2eModel.Model.Enum; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types; -[AonprdProcessor("action")] -internal class ActionProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input) +[Processor( + "aonprd:action", + InnerType = "action", + Description = "Создание цели внешних ссылок", + Group = ProcessorGroupEnum.AonprdEntities +)] +[ProcessorDependencies(["aonprd:trait", "aonprd:source"])] +internal class ActionProcessor( + AonprdProcessorInput input, + Pf2eDbContext context, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) { /// public override EntityType Type => EntityType.Action; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/AncestryProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/AncestryProcessor.cs similarity index 70% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/AncestryProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/AncestryProcessor.cs index d0f16b0..841ab9a 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/AncestryProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/AncestryProcessor.cs @@ -1,11 +1,28 @@ using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; +using Pf2eModel; using Pf2eModel.Model.Enum; using Pf2eModel.Model.Structure; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types; -[AonprdProcessor("ancestry", ["trait", "source", "language"])] -internal class AncestryProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input) +[Processor( + "aonprd:ancestry", + InnerType = "ancestry", + Description = "Создание цели внешних ссылок", + Group = ProcessorGroupEnum.AonprdEntities +)] +[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:language"])] +internal class AncestryProcessor( + AonprdProcessorInput input, + Pf2eDbContext context, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) { /// public override EntityType Type => EntityType.Ancestry; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/ArchetypeProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/ArchetypeProcessor.cs new file mode 100644 index 0000000..dcab3e8 --- /dev/null +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/ArchetypeProcessor.cs @@ -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) +{ + /// + public override EntityType Type => EntityType.Archetype; + + /// + public override Archetype Object { get; } = new(); + + /// + public override void Add() => Context.Archetypes.Add(Object); + + /// + public override void Process() + { + base.Process(); + + Object.Level = Input.GetOptional("level"); + } + + /// + protected override string[] AddedDescriptionPaths() => + ["prerequisite_markdown", "requirement_markdown", "summary_markdown"]; +} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/BackgroundProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/BackgroundProcessor.cs similarity index 56% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/BackgroundProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/BackgroundProcessor.cs index cc1b8e2..82a266b 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/BackgroundProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/BackgroundProcessor.cs @@ -1,12 +1,29 @@ using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; +using Pf2eModel; using Pf2eModel.Model.Enum; using Pf2eModel.Model.Structure; using Pf2eModel.Model.Structure.BackgroundRelation; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types; -[AonprdProcessor("background")] -internal class BackgroundProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input) +[Processor( + "aonprd:background", + InnerType = "background", + Description = "Создание цели внешних ссылок", + Group = ProcessorGroupEnum.AonprdEntities +)] +[ProcessorDependencies(["aonprd:trait", "aonprd:source"])] +internal class BackgroundProcessor( + AonprdProcessorInput input, + Pf2eDbContext context, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) { /// public override EntityType Type => EntityType.Background; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/ClassProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/ClassProcessor.cs similarity index 91% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/ClassProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/ClassProcessor.cs index c70d24d..86d2fe8 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/ClassProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/ClassProcessor.cs @@ -1,5 +1,9 @@ using System.Text.RegularExpressions; using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; using Pf2eModel; using Pf2eModel.Model.Common; using Pf2eModel.Model.Common.I18n; @@ -8,10 +12,22 @@ using Pf2eModel.Model.Structure; using Pf2eModel.Model.Structure.ClassRelation; using static System.Text.RegularExpressions.Regex; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types; -[AonprdProcessor("class", ["trait", "source", "skill"])] -internal partial class ClassProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input) +[Processor( + "aonprd:class", + InnerType = "class", + Description = "Создание цели внешних ссылок", + Group = ProcessorGroupEnum.AonprdEntities +)] +[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:skill"])] +internal partial class ClassProcessor( + AonprdProcessorInput input, + Pf2eDbContext context, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) { /// public override EntityType Type => EntityType.Class; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/FeatProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/FeatProcessor.cs similarity index 75% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/FeatProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/FeatProcessor.cs index c863398..d281bb4 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/FeatProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/FeatProcessor.cs @@ -1,12 +1,28 @@ using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; using Pf2eModel; using Pf2eModel.Model.Enum; using Pf2eModel.Model.Structure; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types; -[AonprdProcessor("feat", ["trait", "source", "archetype"])] -internal class FeatProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input) +[Processor( + "aonprd:feat", + InnerType = "feat", + Description = "Создание цели внешних ссылок", + Group = ProcessorGroupEnum.AonprdEntities +)] +[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:archetype"])] +internal class FeatProcessor( + AonprdProcessorInput input, + Pf2eDbContext context, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) { /// public override EntityType Type => EntityType.Feat; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/LanguageProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/LanguageProcessor.cs new file mode 100644 index 0000000..d9a723a --- /dev/null +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/LanguageProcessor.cs @@ -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) +{ + /// + public override EntityType Type => EntityType.Language; + + /// + public override Language Object { get; } = new(); + + /// + public override void Add() => Context.Languages.Add(Object); +} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/RitualProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/RitualProcessor.cs similarity index 94% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/RitualProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/RitualProcessor.cs index b4e7430..7e9b611 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/RitualProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/RitualProcessor.cs @@ -1,16 +1,31 @@ using System.Text.RegularExpressions; using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Helpers; using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; using Pf2eModel; using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Enum; using Pf2eModel.Model.Structure; using Pf2eModel.Model.Structure.RitualRelation; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types; -[AonprdProcessor("ritual", ["trait", "source", "skill"])] -internal partial class RitualProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input) +[Processor( + "aonprd:ritual", + InnerType = "ritual", + Description = "Создание цели внешних ссылок", + Group = ProcessorGroupEnum.AonprdEntities +)] +[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:skill"])] +internal partial class RitualProcessor( + AonprdProcessorInput input, + Pf2eDbContext context, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) { /// public override EntityType Type => EntityType.Ritual; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RuleProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/Rules/RuleProcessor.cs similarity index 81% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RuleProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/Rules/RuleProcessor.cs index 43cbd04..b3f4e53 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RuleProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/Rules/RuleProcessor.cs @@ -1,14 +1,31 @@ using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; +using Pf2eModel; using Pf2eModel.Model.Base.Source; using Pf2eModel.Model.Base.Targets; using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Enum; using Rule = Pf2eModel.Model.Structure.Rule; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types.Rules; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types.Rules; -[AonprdProcessor("rules", ["rules-toc"])] -internal class RuleProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input) +[Processor( + "aonprd:rules", + InnerType = "rules", + Description = "Создание цели внешних ссылок", + Group = ProcessorGroupEnum.AonprdEntities +)] +[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:rules-toc"])] +internal class RuleProcessor( + AonprdProcessorInput input, + Pf2eDbContext context, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) { /// public override EntityType Type => EntityType.Rule; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesOrderProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/Rules/RulesOrderProcessor.cs similarity index 98% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesOrderProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/Rules/RulesOrderProcessor.cs index 9d673e3..7a1d6f0 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesOrderProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/Rules/RulesOrderProcessor.cs @@ -6,6 +6,7 @@ // Ну а пока просто расставляем родительские и дочерние элементы. using System.Data; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; using Pf2eDataScrapper.Processors; using Pf2eModel.Model.Structure; using Rule = Pf2eModel.Model.Structure.Rule; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesTocProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/Rules/RulesTocProcessor.cs similarity index 98% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesTocProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/Rules/RulesTocProcessor.cs index 5d76d93..9ecc12d 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/Rules/RulesTocProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/Rules/RulesTocProcessor.cs @@ -2,6 +2,7 @@ using System.Web; using AngleSharp; using AngleSharp.Dom; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; using Pf2eDataScrapper.Processors; using Pf2eModel.Model.Base.Source; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/SpellProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/SpellProcessor.cs similarity index 83% rename from Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/SpellProcessor.cs rename to Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/SpellProcessor.cs index b1c4b71..27573de 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/Types/SpellProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/SpellProcessor.cs @@ -1,13 +1,30 @@ using Newtonsoft.Json.Linq; +using Pf2eDataScrapper.App; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; +using Pf2eModel; using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Enum; using Pf2eModel.Model.Structure; using Pf2eModel.Model.Structure.SpellRelation; -namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types; +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types; -[AonprdProcessor("spell")] -internal class SpellProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input) +[Processor( + "aonprd:spell", + InnerType = "spell", + Description = "Создание цели внешних ссылок", + Group = ProcessorGroupEnum.AonprdEntities +)] +[ProcessorDependencies(["aonprd:trait", "aonprd:source"])] +internal class SpellProcessor( + AonprdProcessorInput input, + Pf2eDbContext context, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) { /// public override EntityType Type => EntityType.Spell; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/TraitProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/TraitProcessor.cs new file mode 100644 index 0000000..9ac249e --- /dev/null +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/TraitProcessor.cs @@ -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) +{ + /// + public override EntityType Type => EntityType.Trait; + + /// + public override Trait Object { get; } = new(); + + /// + public override void Add() => Context.Traits.Add(Object); + + /// + public override void Process() + { + base.Process(); + + Object.Type = TraitType.Regular; + + Context.Traits.Add(Object); + } + + /// + protected override void AddTraits() + { + // Необходимо пропускать + } + + /// + protected override string GetDescription() => + base.GetDescription() + AddedDescription(["summary_markdown", "search_markdown"]); +} diff --git a/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/AbstractProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Pf2eFoundry/DataBuilder/AbstractProcessor.cs index 80b7cc3..709ae64 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.Helpers; using Pf2eDataScrapper.Processors; using Pf2eModel; using Pf2eModel.Model; diff --git a/Pf2eDataScrapper/Importers/Repositories/AbstractImporterRepository.cs b/Pf2eDataScrapper/Importers/Repositories/AbstractImporterRepository.cs index a3dedef..c88d524 100644 --- a/Pf2eDataScrapper/Importers/Repositories/AbstractImporterRepository.cs +++ b/Pf2eDataScrapper/Importers/Repositories/AbstractImporterRepository.cs @@ -1,4 +1,6 @@ -namespace Pf2eDataScrapper.Importers.Repositories; +using Pf2eDataScrapper.Processors; + +namespace Pf2eDataScrapper.Importers.Repositories; /// /// Класс абстрактного репозитория. @@ -22,5 +24,5 @@ internal abstract class AbstractImporterRepository(AbstractImporter importer) /// /// Обновление данных в репозитории. /// - public abstract void Update(); + public abstract void Update(ProcessProgress progress); } diff --git a/Pf2eDataScrapper/Importers/Repositories/GitRepository.cs b/Pf2eDataScrapper/Importers/Repositories/GitRepository.cs index d0974eb..ab73ea2 100644 --- a/Pf2eDataScrapper/Importers/Repositories/GitRepository.cs +++ b/Pf2eDataScrapper/Importers/Repositories/GitRepository.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using Pf2eDataScrapper.Processors; namespace Pf2eDataScrapper.Importers.Repositories; @@ -16,11 +17,14 @@ internal class GitRepository(AbstractImporter importer, string url) public string Url { get; } = url; /// - public override void Update() + public override void Update(ProcessProgress progress) { + progress.Local.Reset(1); + if (Directory.Exists(RepositoryDirPath)) { - // git pull + progress.Local.Start("git pull"); + Process process = new() { StartInfo = new() @@ -34,7 +38,8 @@ internal class GitRepository(AbstractImporter importer, string url) } else { - // git clone + progress.Local.Start("git clone"); + Process process = new() { StartInfo = new() @@ -46,5 +51,7 @@ internal class GitRepository(AbstractImporter importer, string url) }; process.Start(); } + + progress.Local.Complete(); } } diff --git a/Pf2eDataScrapper/Processors/AbstractInputProcessor.cs b/Pf2eDataScrapper/Processors/AbstractInputProcessor.cs index a576ae2..aae8786 100644 --- a/Pf2eDataScrapper/Processors/AbstractInputProcessor.cs +++ b/Pf2eDataScrapper/Processors/AbstractInputProcessor.cs @@ -1,34 +1,18 @@ -using Microsoft.Extensions.DependencyInjection; -using Pf2eDataScrapper.App; -using Pf2eModel; +using Pf2eDataScrapper.App; namespace Pf2eDataScrapper.Processors; /// /// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса. /// Класс предназначен для обработки данных с помощью различных обработчиков, -/// для которых указан атрибут . +/// для которых указан атрибут . /// -/// Провайдер сервисов. -/// Провайдер сервисов. -/// -internal abstract class AbstractInputProcessor( - IServiceProvider serviceProvider, - ProcessorInput input -) : IProcessor +/// Входные данные обработчика. +/// +internal abstract class AbstractInputProcessor(ProcessorInput input) : IProcessor { /// - /// Провайдер сервисов. - /// - public IServiceProvider ServiceProvider { get; } = serviceProvider; - - /// - /// Контекст базы данных. - /// - public Pf2eDbContext Context { get; } = serviceProvider.GetService()!; - - /// - /// Ввод. + /// Входные данные обработчика. /// public ProcessorInput Input { get; } = input; diff --git a/Pf2eDataScrapper/Processors/AbstractProcessor.cs b/Pf2eDataScrapper/Processors/AbstractProcessor.cs index 155a670..0731b1c 100644 --- a/Pf2eDataScrapper/Processors/AbstractProcessor.cs +++ b/Pf2eDataScrapper/Processors/AbstractProcessor.cs @@ -7,22 +7,11 @@ namespace Pf2eDataScrapper.Processors; /// /// Абстрактный класс-обработчик данных, полученных из Архивов Нефиса. /// Класс предназначен для обработки данных с помощью различных обработчиков, -/// для которых указан атрибут . +/// для которых указан атрибут . /// -/// Провайдер сервисов. -/// -internal abstract class AbstractProcessor(IServiceProvider serviceProvider) : IProcessor +/// +internal abstract class AbstractProcessor : IProcessor { - /// - /// Провайдер сервисов. - /// - public IServiceProvider ServiceProvider { get; } = serviceProvider; - - /// - /// Контекст базы данных. - /// - public Pf2eDbContext Context { get; } = serviceProvider.GetService()!; - /// /// Основной метод обработки данных. /// diff --git a/Pf2eDataScrapper/Processors/DatabaseTruncateProcessor.cs b/Pf2eDataScrapper/Processors/DatabaseTruncateProcessor.cs new file mode 100644 index 0000000..9967454 --- /dev/null +++ b/Pf2eDataScrapper/Processors/DatabaseTruncateProcessor.cs @@ -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() { } +} diff --git a/Pf2eDataScrapper/Processors/IProcessor.cs b/Pf2eDataScrapper/Processors/IProcessor.cs index 33849eb..09c675a 100644 --- a/Pf2eDataScrapper/Processors/IProcessor.cs +++ b/Pf2eDataScrapper/Processors/IProcessor.cs @@ -1,14 +1,7 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace Pf2eDataScrapper.Processors; +namespace Pf2eDataScrapper.Processors; public interface IProcessor { - /// - /// Провайдер сервисов. - /// - IServiceProvider ServiceProvider { get; } - /// /// Основной метод обработки данных. /// diff --git a/Pf2eDataScrapper/Processors/ProcessProgress.cs b/Pf2eDataScrapper/Processors/ProcessProgress.cs new file mode 100644 index 0000000..5e2f7cb --- /dev/null +++ b/Pf2eDataScrapper/Processors/ProcessProgress.cs @@ -0,0 +1,156 @@ +namespace Pf2eDataScrapper.Processors; + +internal class ProcessProgress +{ + /// + /// Прогресс обработки обработчиков . + /// + public ProgressItem Processors { get; } = new(); + + /// + /// Прогресс работы конкретного обработчика . + /// + public ProgressItem Local { get; } = new(); + + /// + /// Конструктор класса . + /// + public ProcessProgress() + { + Processors.Update += Update; + Local.Update += Update; + } + + /// + /// Событие обновления + /// + 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; + + /// + /// Класс прогресса. + /// + public class ProgressItem + { + /// + /// Количество обрабатываемых процессов. + /// + public int Count + { + get => _count; + set + { + _count = value; + Update?.Invoke(); + } + } + private int _count = 0; + + /// + /// Индекс текущего обрабатываемого процесса. + /// + public int Current + { + get => _current; + set + { + _current = value; + Update?.Invoke(); + } + } + private int _current = 0; + + /// + /// Название текущего обрабатываемого процесса. + /// + public string Text + { + get => _text; + set + { + _text = value; + Update?.Invoke(); + } + } + private string _text = ""; + + /// + /// Значение прогресса. + /// + public double Percent => Count > 0 ? 1.0 * Current / Count : 1.0; + + /// + /// Сброс прогресса до нуля и установка нового максимального значения. + /// + /// + public void Reset(int max = 0) + { + _count = max; + _current = 0; + _text = ""; + Update?.Invoke(); + } + + /// + /// Отмечает начало работы над процессом, описываемым строкой . + /// + /// Строка, описывающая процесс. + public void Start(string text) + { + _text = text; + Update?.Invoke(); + } + + /// + /// Отмечает конец работы над процессом и увеличивает значение прогресса. + /// + public void End() + { + _text = ""; + _current++; + Update?.Invoke(); + } + + /// + /// Отмечает прогресс завершённым. + /// + public void Complete() + { + _current = _count; + _text = "Готово!"; + Update?.Invoke(); + } + + /// + /// Получение строкового представления прогресса. + /// + /// Строковое представление прогресса. + public override string ToString() + { + return $"{Text} [{Current} / {Count}; {Percent:P}]"; + } + + /// + /// Делегат события обновления. + /// + public delegate void UpdateDelegate(); + + /// + /// Событие обновление. + /// + public event UpdateDelegate? Update; + } +} diff --git a/Pf2eDataScrapper/Processors/ProcessorInput.cs b/Pf2eDataScrapper/Processors/ProcessorInput.cs index cb683be..c6acd01 100644 --- a/Pf2eDataScrapper/Processors/ProcessorInput.cs +++ b/Pf2eDataScrapper/Processors/ProcessorInput.cs @@ -7,9 +7,15 @@ namespace Pf2eDataScrapper.Processors; /// /// Класс для работы с JSON-объектом. /// +/// Название объекта, ассоциированного с вводом. /// JSON-объект, который будет использоваться для доступа к данным. -internal class ProcessorInput(JObject input) +internal class ProcessorInput(string name, JObject input) { + /// + /// Название объекта, ассоциированного с вводом. + /// + public string Name { get; } = name; + /// /// Входящий JSON-объект, который содержит данные для обработки. ///