diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractEntityProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractEntityProcessor.cs index 342811b..878a0e7 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractEntityProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractEntityProcessor.cs @@ -36,9 +36,16 @@ internal abstract class AbstractEntityProcessor( AonprdBuilderGlobals globals ) : AbstractInputProcessor(input) { + /// public Pf2eDbContext Context { get; } = new(); + + /// public StringHelper StringHelper { get; } = stringHelper; + + /// public DatabaseHelper Helper { get; } = helper; + + /// public AonprdBuilderGlobals Globals { get; } = globals; /// @@ -86,7 +93,7 @@ internal abstract class AbstractEntityProcessor( { if (Globals.MergeSources.ContainsKey(Input.GetRequired("id"))) { - throw new SkipItemException(Input.GetRequired("name"), "помечено на слияние."); + throw new SkipItemException(GetEntityName(), "помечено на слияние."); } } @@ -145,6 +152,12 @@ internal abstract class AbstractEntityProcessor( #region "Генерация сущности" + /// + /// Получает имя сущности из входных данных. + /// + /// Имя сущности. + protected virtual string GetEntityName() => Input.GetRequired("name"); + /// /// Генерация основных полей корневой сущности. /// @@ -156,7 +169,7 @@ internal abstract class AbstractEntityProcessor( } Entity.Type = Type; - Entity.Name[LocaleType.English] = Input.GetRequired("name"); + Entity.Name[LocaleType.English] = GetEntityName(); Entity.Img = ""; Entity.Description = GetDescription(); Entity.Rarity = Input.EnumOptional("rarity", EntityRarity.Common); diff --git a/Pf2eDataScrapper/Importers/Implementations/FoundryEn/Processors/Entities/ActionProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/FoundryEn/Processors/Entities/ActionProcessor.cs index 4aadb35..c1c31b5 100644 --- a/Pf2eDataScrapper/Importers/Implementations/FoundryEn/Processors/Entities/ActionProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/FoundryEn/Processors/Entities/ActionProcessor.cs @@ -1,9 +1,7 @@ -using Newtonsoft.Json.Linq; -using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Helpers; using Pf2eDataScrapper.Importers.Implementations.FoundryEn.Helpers; using Pf2eDataScrapper.Processors; using Pf2eDataScrapper.Processors.Attributes; -using Pf2eDataScrapper.Processors.Collection; using Pf2eModel; using Pf2eModel.Model.Enum; @@ -17,7 +15,7 @@ namespace Pf2eDataScrapper.Importers.Implementations.FoundryEn.Processors.Entiti Group = ProcessorGroupEnum.FoundryEnEntities, Active = false )] -[ProcessorDependencies(["foundry-en:compendium"])] +[ProcessorDependencies(["foundry-en:compendium", "foundry-en:external"])] internal class ActionProcessor( DatabaseHelper databaseHelper, Pf2eDbContext context, diff --git a/Pf2eDataScrapper/Importers/Implementations/FoundryEn/Processors/FoundryEnAbstractProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/FoundryEn/Processors/FoundryEnAbstractProcessor.cs index c2e72f7..604f62f 100644 --- a/Pf2eDataScrapper/Importers/Implementations/FoundryEn/Processors/FoundryEnAbstractProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/FoundryEn/Processors/FoundryEnAbstractProcessor.cs @@ -1,105 +1,162 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Windows.Documents; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json.Linq; using Pf2eDataScrapper.Helpers; using Pf2eDataScrapper.Importers.Implementations.FoundryEn.Helpers; using Pf2eDataScrapper.Processors; +using Pf2eDataScrapper.Processors.Attributes; using Pf2eDataScrapper.Processors.Definitions; using Pf2eModel; using Pf2eModel.Model; using Pf2eModel.Model.Base; -using Pf2eModel.Model.Base.Source; using Pf2eModel.Model.Base.Targets; using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Enum; -using Pf2eModel.Model.Structure; namespace Pf2eDataScrapper.Importers.Implementations.FoundryEn.Processors; +/// +/// Абстрактный класс-обработчик сущностей, полученных из молуля Foundry pf2e. +/// Класс предназначен для обработки данных с помощью различных обработчиков, +/// для которых указан атрибут . +/// +/// +/// [DI] +/// [DI] +/// [DI] +/// Объект обработки вводимого JSON. internal abstract class FoundryEnAbstractProcessor( DatabaseHelper databaseHelper, Pf2eDbContext context, FoundryEnGlobals enGlobals, ProcessorInput input ) : AbstractInputProcessor(input) - where TEntity : class, IEntity? + where TEntity : class, IEntity { + /// protected DatabaseHelper Helper { get; } = databaseHelper; + /// public Pf2eDbContext Context { get; } = context; + /// public FoundryEnGlobals EnGlobals { get; } = enGlobals; + /// + /// Тип сущности. + /// public abstract EntityType Type { get; } + /// + /// Представление сущности, которое будет использоваться для обработки данных. + /// public EntityView View { get; private set; } = null!; + /// + /// Основная сущность, которая будет использоваться для обработки данных. + /// public Entity Entity => View.Entity; + /// + /// Подчинённая сущность, которая будет использоваться для обработки данных. + /// public TEntity Object => View.SubEntity as TEntity ?? throw new InvalidOperationException( $"Сущность {View.SubEntity} некорректного типа, ожидался тип {typeof(TEntity)}." ); - public virtual void ResolveEntity() + /// + /// Разрешает сущность, основываясь на входных данных. + /// + /// Идентификатор сущности. + public virtual int ResolveEntity() { - string name = Input.GetRequired("name"); + string name = GetEntityName(); try { - int id = Context - .Entities.Include(e => e.Name) + List entities = Context + .Entities.AsNoTracking() + .Include(e => e.Traits) + .ThenInclude(t => t.Entity) .Where(e => Pf2eDbContext.LocaleSearch(e.Name, name) && e.Type == Type) - .Select(e => e.Id) - .FirstOrDefault(); + .ToList(); - View = new EntityView(Context, Type, id); + switch (entities.Count) + { + case 0: + throw new("сущность не найдена."); + case 1: + return entities[0].Id; + } + + List inputTraits = Input + .GetRequired("system.traits.value") + .Select(token => token.ToString()) + .Order() + .ToList(); + + foreach (Entity entity in entities) + { + List entityTraits = entity + .Traits.Select(t => t.Entity.Name[LocaleType.English]) + .Order() + .ToList(); + + if (entityTraits.SequenceEqual(inputTraits)) + { + return entity.Id; + } + } } catch (Exception ex) { throw new SkipItemException(name, ex.Message); } + + throw new SkipItemException( + name, + $"Несколько сущностей \"{name}\" найдено, но ни одна не совпадает с входными данными по признакам." + ); } + /// public override void Process() { - ResolveEntity(); + View = new(Context, Type, ResolveEntity()); + AddExternal(); + } + + /// + public override void Save() + { + Context.SaveChanges(); + } + + /// + /// Получает имя сущности из входных данных. + /// + /// Имя сущности. + protected virtual string GetEntityName() => Input.GetRequired("name"); + + /// + /// Генерация внешних ссылок сущности. + /// + protected virtual void AddExternal() + { // External EntityExternal external = new() { - Entity = Entity, - Target = EnGlobals.FoundryTarget, + EntityId = Entity.Id, + TargetId = EnGlobals.FoundryTarget.Id, ExternalId = Input.GetOptional("_id"), Suffix = Input.GetRequired("_id"), Md5 = Input.Md5(), }; Context.EntityExternals.Add(external); } - - public override void Save() - { - Context.SaveChanges(); - } - - protected Source GetSource(string name) - { - Source? source = Context.Sources.FirstOrDefault(s => s.Name == name); - - if (source != null) - { - return source; - } - - source = new() { Name = name }; - - Context.Sources.Add(source); - return source; - } }