diff --git a/Pf2eDataScrapper/Helpers/DatabaseHelper.cs b/Pf2eDataScrapper/Helpers/DatabaseHelper.cs index 690f4f3..8559b54 100644 --- a/Pf2eDataScrapper/Helpers/DatabaseHelper.cs +++ b/Pf2eDataScrapper/Helpers/DatabaseHelper.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Threading; using Pf2eModel; using Slugify; @@ -30,6 +31,8 @@ public class DatabaseHelper /// public int NextEntityId => ++_id; + public Lock IdLock { get; } = new(); + public DatabaseHelper(Pf2eDbContext context, SlugHelper slugHelper) { Context = context; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/AonprdBuilderGlobals.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/AonprdBuilderGlobals.cs index 74633e4..32cace0 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/AonprdBuilderGlobals.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Helpers/AonprdBuilderGlobals.cs @@ -43,6 +43,12 @@ internal class AonprdBuilderGlobals /// public Dictionary MergeSources { get; } = []; + /// + /// Словарь сущностей, которые нужно слить с другой/другими. + /// Ключ - пропускаемая сущность. Значение - целевая сущность. + /// + public Dictionary SubclassGroups { get; } = []; + /// /// Конструктор класса . /// @@ -60,6 +66,7 @@ internal class AonprdBuilderGlobals SlugSuffixes = JsonToDictionary(json, "SlugSuffixes"); LegacyRemasterExtra = JsonToDictionary(json, "LegacyRemasterExtra"); MergeSources = JsonToDictionary(json, "MergeSources"); + SubclassGroups = JsonToDictionary(json, "SubclassGroups"); } } diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractEntityProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractEntityProcessor.cs index 94aa8d4..68698ba 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractEntityProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractEntityProcessor.cs @@ -147,7 +147,11 @@ internal abstract class AbstractEntityProcessor( /// protected virtual void AddEntity() { - Entity.Id = Helper.NextEntityId; + lock (Helper.IdLock) + { + Entity.Id = Helper.NextEntityId; + } + Entity.Type = Type; Entity.Name[LocaleType.English] = Input.GetRequired("name"); Entity.Img = ""; diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractSubclassProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractSubclassProcessor.cs index 9548329..245690c 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractSubclassProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/AbstractSubclassProcessor.cs @@ -63,39 +63,8 @@ internal abstract class AbstractSubclassProcessor( /// CLR-представления группы подклассов. public SubclassGroup GetGroup() { - SubclassGroup? group = Context.SubclassGroups.FirstOrDefault(g => + return Context.SubclassGroups.First(g => Pf2eDbContext.LocaleSearch(g.Entity.Name, GroupName) ); - - if (group is not null) - { - return group; - } - - Class? cl = ClassName is not null - ? Context.Classes.FirstOrDefault(c => - Pf2eDbContext.LocaleSearch(c.Entity.Name, GroupName) - ) - : null; - - Entity groupEntity = new() - { - Id = Helper.NextEntityId, - Type = EntityType.SubclassGroup, - Img = "", - Description = "", - Rarity = EntityRarity.Common, - IsTranslated = false, - IsChecked = false, - Name = { [LocaleType.English] = GroupName }, - Slug = Helper.GenerateSlug(GroupName), - }; - - Context.Entities.Add(groupEntity); - - group = new() { Entity = groupEntity, Class = cl }; - Context.SubclassGroups.Add(group); - - return group; } } diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Subclasses/ApparitionProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Subclasses/ApparitionProcessor.cs index 78b30b8..75ec77a 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Subclasses/ApparitionProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Subclasses/ApparitionProcessor.cs @@ -24,9 +24,7 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Subclasse Description = "Apparitions", Group = ProcessorGroupEnum.AonprdSubclasses )] -[ProcessorDependencies( - ["aonprd:trait", "aonprd:source", "aonprd:class", "aonprd:spell", "aonprd:skill"] -)] +[ProcessorDependencies(["aonprd:subclass-group"])] internal partial class ApparitionProcessor( ProcessorInput input, StringHelper stringHelper, @@ -88,8 +86,7 @@ internal partial class ApparitionProcessor( string aonprdId = $"spell-{match.Groups[1].Value}"; var entity = Context - .EntityExternals.AsNoTracking() - .Where(x => x.ExternalId == aonprdId) + .EntityExternals.Where(x => x.ExternalId == aonprdId) .Select(x => x.Entity) .First(); diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Subclasses/SubclassGroupProcessorFactory.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Subclasses/SubclassGroupProcessorFactory.cs new file mode 100644 index 0000000..ee946a6 --- /dev/null +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Subclasses/SubclassGroupProcessorFactory.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Finalization; +using Pf2eDataScrapper.Processors.Attributes; +using Pf2eDataScrapper.Processors.Definitions; +using Pf2eDataScrapper.Processors.Factory; +using Pf2eModel; +using Pf2eModel.Model.Base; +using Pf2eModel.Model.Common.I18n; +using Pf2eModel.Model.Enum; +using Pf2eModel.Model.Structure; + +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Subclasses; + +[ProcessorFactory( + "aonprd:subclass-group", + ProcessorType = typeof(SubclassGroupProcessor), + Description = "Группы подклассов", + Group = ProcessorGroupEnum.AonprdSubclasses, + Parallel = true +)] +[ProcessorDependencies( + ["aonprd:trait", "aonprd:source", "aonprd:class", "aonprd:spell", "aonprd:skill"] +)] +internal class SubclassGroupProcessorFactory( + IServiceProvider serviceProvider, + AonprdBuilderGlobals globals +) : AbstractProcessorFactory +{ + public IServiceProvider ServiceProvider { get; } = serviceProvider; + public AonprdBuilderGlobals Globals { get; } = globals; + + public override int Count() => Globals.SubclassGroups.Count; + + public override IEnumerable> GetEnumerator() + { + foreach ((string key, string value) in Globals.SubclassGroups) + { + var processor = + value == "_null" + ? ActivatorUtilities.CreateInstance( + ServiceProvider, + key + ) + : ActivatorUtilities.CreateInstance( + ServiceProvider, + key, + value + ); + + yield return new($"{key} -> {value}", processor); + } + } +} + +internal class SubclassGroupProcessor(string groupName, string? className, DatabaseHelper helper) + : IProcessor +{ + public string GroupName { get; } = groupName; + public string? ClassName { get; } = className; + public DatabaseHelper Helper { get; } = helper; + + public SubclassGroupProcessor(string groupName, DatabaseHelper helper) + : this(groupName, null, helper) { } + + public Pf2eDbContext Context { get; } = new(); + + public void Process() + { + Class? cl = ClassName is not null + ? Context.Classes.FirstOrDefault(c => + Pf2eDbContext.LocaleSearch(c.Entity.Name, GroupName) + ) + : null; + + int id; + lock (Helper.IdLock) + { + id = Helper.NextEntityId; + } + + Entity groupEntity = new() + { + Id = id, + Type = EntityType.SubclassGroup, + Img = "", + Description = "", + Rarity = EntityRarity.Common, + IsTranslated = false, + IsChecked = false, + Name = { [LocaleType.English] = GroupName }, + Slug = Helper.GenerateSlug(GroupName), + }; + + Context.Entities.Add(groupEntity); + + SubclassGroup group = new() { Entity = groupEntity, Class = cl }; + Context.SubclassGroups.Add(group); + } + + public void Save() + { + Context.SaveChanges(); + } +} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/AncestryProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/AncestryProcessor.cs index d0d6c1a..f7ccee0 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/AncestryProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/AncestryProcessor.cs @@ -37,16 +37,19 @@ internal class AncestryProcessor( /// protected override void Add() => Context.Ancestries.Add(Object); + public override void Check() + { + base.Check(); + + if (Input.GetRequired("type") != "Ancestry") + { + throw new SkipItemException(Input.GetRequired("name"), "не родословная"); + } + } + /// public override void Process() { - string type = Input.GetRequired("type"); - - if (type != "Ancestry") - { - throw new SkipItemException(Input.GetRequired("name"), "not an ancestry"); - } - base.Process(); Object.Size = Input diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/FeatProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/FeatProcessor.cs index fe4e806..b6589b9 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/FeatProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/FeatProcessor.cs @@ -46,14 +46,7 @@ internal class FeatProcessor( ? FeatCategory.Class : FeatCategory.Uncategorized; - AonprdProcessorInputExtension.ActionStruct action = Input.ResolveActionString( - Input.GetOptional("actions") ?? "" - ); - Object.Actions = action.Actions; - Object.MaxActions = action.MaxActions; - Object.IsFreeAction = action.IsFreeAction; - Object.IsPassive = action.IsPassive; - Object.IsReaction = action.IsReaction; + Object.Actions = Input.EnumOptional("actions", ActionEnum.Unknown); Object.Extra = GenerateJsonString( "archetype", diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/HeritageProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/HeritageProcessor.cs new file mode 100644 index 0000000..e826abb --- /dev/null +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/HeritageProcessor.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; +using Pf2eDataScrapper.Processors; +using Pf2eDataScrapper.Processors.Attributes; +using Pf2eModel.Model.Enum; +using Pf2eModel.Model.Structure; + +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types; + +[ProcessorCollection( + "aonprd:heritage", + InnerType = "heritage", + CompendiumType = ProcessorCompendiumEnum.Aonprd, + Description = "Наследства", + Group = ProcessorGroupEnum.AonprdEntities +)] +[ProcessorDependencies(["aonprd:ancestry"])] +internal class HeritageProcessor( + ProcessorInput input, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, stringHelper, helper, globals) +{ + /// + public override EntityType Type => EntityType.Heritage; + + /// + public override Heritage Object { get; } = new(); + + /// + protected override void Add() => Context.Heritages.Add(Object); + + /// + public override void Process() + { + base.Process(); + } +} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/SkillActionsProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/SkillActionsProcessor.cs new file mode 100644 index 0000000..4c3ff04 --- /dev/null +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/SkillActionsProcessor.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; +using Pf2eDataScrapper.Processors; +using Pf2eDataScrapper.Processors.Attributes; +using Pf2eModel.Model.Enum; + +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types; + +[ProcessorCollection( + "aonprd:skill-general-action", + InnerType = "skill-general-action", + CompendiumType = ProcessorCompendiumEnum.Aonprd, + Description = "Действия скиллов", + Group = ProcessorGroupEnum.AonprdEntities +)] +[ProcessorDependencies(["aonprd:trait", "aonprd:source"])] +internal class SkillActionsProcessor( + ProcessorInput input, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, stringHelper, helper, globals) +{ + /// + public override EntityType Type => EntityType.Action; + + /// + public override Pf2eModel.Model.Structure.Action Object { get; } = new(); + + /// + protected override void Add() => Context.Actions.Add(Object); + + /// + public override void Process() + { + Check(); + + base.Process(); + + Object.Actions = ActionEnum.Other; + Object.Category = ActionCategory.SkillAction; + } + + /// + protected override string[] AddedDescriptionPaths() => + [ + "cost_markdown", + "trait_markdown", + "source_markdown", + "search_markdown", + "requirement_markdown", + "trigger_markdown", + "summary_markdown", + ]; +} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/VersitileHeritageProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/VersitileHeritageProcessor.cs new file mode 100644 index 0000000..22b0a96 --- /dev/null +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/Processors/Types/VersitileHeritageProcessor.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Pf2eDataScrapper.Helpers; +using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; +using Pf2eDataScrapper.Processors; +using Pf2eDataScrapper.Processors.Attributes; +using Pf2eModel.Model.Enum; +using Pf2eModel.Model.Structure; + +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types; + +[ProcessorCollection( + "aonprd:versitile-heritage", + InnerType = "ancestry", + CompendiumType = ProcessorCompendiumEnum.Aonprd, + Description = "Универсальные наследства", + Group = ProcessorGroupEnum.AonprdEntities +)] +[ProcessorDependencies(["aonprd:ancestry"])] +internal class VersitileHeritageProcessor( + ProcessorInput input, + StringHelper stringHelper, + DatabaseHelper helper, + AonprdBuilderGlobals globals +) : AbstractEntityProcessor(input, stringHelper, helper, globals) +{ + /// + public override EntityType Type => EntityType.Heritage; + + /// + public override Heritage Object { get; } = new(); + + /// + protected override void Add() => Context.Heritages.Add(Object); + + public override void Check() + { + base.Check(); + + if (Input.GetRequired("type") == "Ancestry") + { + throw new SkipItemException( + Input.GetRequired("name"), + "не универсальное наследие" + ); + } + } + + /// + public override void Process() + { + base.Process(); + } +} diff --git a/Pf2eDataScrapper/Resources/ImportAdaptation.json b/Pf2eDataScrapper/Resources/ImportAdaptation.json index c9a36d1..e5bbed8 100644 --- a/Pf2eDataScrapper/Resources/ImportAdaptation.json +++ b/Pf2eDataScrapper/Resources/ImportAdaptation.json @@ -77,6 +77,38 @@ "spell-571": "spell-1975", "spell-578": "spell-1566", "spell-654": "spell-819" + }, + "SubclassGroups": { + "Research Field": "Alchemist", + "Apparition": "Animist", + "Practice": "Animist", + "Instinct": "Barbarian", + "Muse": "Bard", + "Cause": "Champion", + "Tenet": "Champion", + "Doctrine": "Cleric", + "Druidic Order": "Druid", + "Methodology": "Investigator", + "Element": "Kineticist", + "Hybrid Study": "Magus", + "Mystery": "Oracle", + "Conscious Mind": "Psychic", + "Subconscious Mind": "Psychic", + "Hunters Edge": "Ranger", + "Racket": "Rogue", + "Bloodline": "Sorcerer", + "Style": "Swashbuckler", + "Implement": "Thaumaturge", + "Lesson": "Witch", + "Patron": "Witch", + "Arcane School": "Wizard", + "Arcane Thesis": "Wizard", + "Way": "Gunslinger", + "Innovation": "Innovator", + "Ikon": "Exemplar", + "Epithet": "Exemplar", + "Hellknight Order": "_null", + "Eidolon": "_null" } } } \ No newline at end of file diff --git a/Pf2eDataScrapper/WPF/EntityViewer/ViewModel/EntityFormViewModel.cs b/Pf2eDataScrapper/WPF/EntityViewer/ViewModel/EntityFormViewModel.cs index d587fa7..74b690e 100644 --- a/Pf2eDataScrapper/WPF/EntityViewer/ViewModel/EntityFormViewModel.cs +++ b/Pf2eDataScrapper/WPF/EntityViewer/ViewModel/EntityFormViewModel.cs @@ -63,7 +63,7 @@ internal class EntityFormViewModel : ViewModelBase private void LoadEntityTypes() { - EntityTypes = Context.Entities.Select(e => e.Type).Distinct().ToList(); + EntityTypes = Context.Entities.Select(e => e.Type).Distinct().Order().ToList(); OnPropertyChanged(nameof(EntityTypes)); SelectedEntityTypeStore.SelectedEntityType = EntityTypes.Any() ? EntityTypes.First() : null; diff --git a/Pf2eModel/Migrations/20250521155437_1.Designer.cs b/Pf2eModel/Migrations/20250522130215_1.Designer.cs similarity index 99% rename from Pf2eModel/Migrations/20250521155437_1.Designer.cs rename to Pf2eModel/Migrations/20250522130215_1.Designer.cs index 2525e09..d6a39c2 100644 --- a/Pf2eModel/Migrations/20250521155437_1.Designer.cs +++ b/Pf2eModel/Migrations/20250522130215_1.Designer.cs @@ -13,7 +13,7 @@ using Pf2eModel.Model.Enum; namespace Pf2eModel.Migrations { [DbContext(typeof(Pf2eDbContext))] - [Migration("20250521155437_1")] + [Migration("20250522130215_1")] partial class _1 { /// @@ -24,7 +24,7 @@ namespace Pf2eModel.Migrations .HasAnnotation("ProductVersion", "9.0.4") .HasAnnotation("Relational:MaxIdentifierLength", 63); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "action_category", new[] { "archetype", "army_tactic", "army_war_action", "class-feat", "class-feature", "defensive", "familiar", "interaction", "kingdom_activity", "kingdom_feat", "kingdom_feature", "offensive", "unknown" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "action_category", new[] { "archetype", "army_tactic", "army_war_action", "class-feat", "class-feature", "defensive", "familiar", "interaction", "kingdom_activity", "kingdom_feat", "kingdom_feature", "offensive", "skill-action", "unknown" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "action_enum", new[] { "1", "1 hour", "1 minute", "1-2", "1-3", "10 minutes", "2", "2-3", "2/2 rounds", "3", "30 minutes", "5 minutes", "free", "free/1", "other", "passive", "reaction", "reaction/1", "reaction/2", "reaction/3", "unknown" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "attribute_values", new[] { "cha", "con", "dex", "free", "int", "str", "wis" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "class_progression_type", new[] { "ancestry_feat", "attribute_increase", "class_feat", "entity", "general_feat", "skill_feat", "skill_increase" }); @@ -548,10 +548,16 @@ namespace Pf2eModel.Migrations .HasColumnOrder(2) .HasComment("Количество действий"); + b.Property("Category") + .HasColumnType("action_category") + .HasColumnName("category") + .HasColumnOrder(3) + .HasComment("Категория действия"); + b.Property("Extra") .HasColumnType("text") .HasColumnName("extra") - .HasColumnOrder(3) + .HasColumnOrder(4) .HasComment("Дополнительная информация"); b.HasKey("Id") @@ -1239,8 +1245,8 @@ namespace Pf2eModel.Migrations .HasColumnOrder(1) .HasComment("Идентификатор"); - b.Property("Actions") - .HasColumnType("integer") + b.Property("Actions") + .HasColumnType("action_enum") .HasColumnName("actions") .HasColumnOrder(5) .HasComment("Количество действий"); @@ -1254,35 +1260,15 @@ namespace Pf2eModel.Migrations b.Property("Extra") .HasColumnType("text") .HasColumnName("extra") - .HasColumnOrder(10) + .HasColumnOrder(6) .HasComment("Дополнительная информация"); - b.Property("IsFreeAction") - .HasColumnType("boolean") - .HasColumnName("is_free_action") - .HasColumnOrder(8); - - b.Property("IsPassive") - .HasColumnType("boolean") - .HasColumnName("is_passive") - .HasColumnOrder(9); - - b.Property("IsReaction") - .HasColumnType("boolean") - .HasColumnName("is_reaction") - .HasColumnOrder(7); - b.Property("Level") .HasColumnType("integer") .HasColumnName("level") .HasColumnOrder(4) .HasComment("Уровень способности"); - b.Property("MaxActions") - .HasColumnType("integer") - .HasColumnName("max_actions") - .HasColumnOrder(6); - b.HasKey("Id") .HasName("pk_feats"); diff --git a/Pf2eModel/Migrations/20250521155437_1.cs b/Pf2eModel/Migrations/20250522130215_1.cs similarity index 99% rename from Pf2eModel/Migrations/20250521155437_1.cs rename to Pf2eModel/Migrations/20250522130215_1.cs index e773ece..2dc5d93 100644 --- a/Pf2eModel/Migrations/20250521155437_1.cs +++ b/Pf2eModel/Migrations/20250522130215_1.cs @@ -14,7 +14,7 @@ namespace Pf2eModel.Migrations protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.AlterDatabase() - .Annotation("Npgsql:Enum:action_category", "archetype,army_tactic,army_war_action,class-feat,class-feature,defensive,familiar,interaction,kingdom_activity,kingdom_feat,kingdom_feature,offensive,unknown") + .Annotation("Npgsql:Enum:action_category", "archetype,army_tactic,army_war_action,class-feat,class-feature,defensive,familiar,interaction,kingdom_activity,kingdom_feat,kingdom_feature,offensive,skill-action,unknown") .Annotation("Npgsql:Enum:action_enum", "1,1 hour,1 minute,1-2,1-3,10 minutes,2,2-3,2/2 rounds,3,30 minutes,5 minutes,free,free/1,other,passive,reaction,reaction/1,reaction/2,reaction/3,unknown") .Annotation("Npgsql:Enum:attribute_values", "cha,con,dex,free,int,str,wis") .Annotation("Npgsql:Enum:class_progression_type", "ancestry_feat,attribute_increase,class_feat,entity,general_feat,skill_feat,skill_increase") @@ -136,6 +136,7 @@ namespace Pf2eModel.Migrations { id = table.Column(type: "integer", nullable: false, comment: "Идентификатор"), actions = table.Column(type: "action_enum", nullable: false, comment: "Количество действий"), + category = table.Column(type: "action_category", nullable: false, comment: "Категория действия"), extra = table.Column(type: "text", nullable: true, comment: "Дополнительная информация") }, constraints: table => @@ -275,11 +276,7 @@ namespace Pf2eModel.Migrations id = table.Column(type: "integer", nullable: false, comment: "Идентификатор"), category = table.Column(type: "feat_category", nullable: false, comment: "Категория способности"), level = table.Column(type: "integer", nullable: false, comment: "Уровень способности"), - actions = table.Column(type: "integer", nullable: true, comment: "Количество действий"), - max_actions = table.Column(type: "integer", nullable: true), - is_reaction = table.Column(type: "boolean", nullable: false), - is_free_action = table.Column(type: "boolean", nullable: false), - is_passive = table.Column(type: "boolean", nullable: false), + actions = table.Column(type: "action_enum", nullable: false, comment: "Количество действий"), extra = table.Column(type: "text", nullable: true, comment: "Дополнительная информация") }, constraints: table => diff --git a/Pf2eModel/Migrations/Pf2eDbContextModelSnapshot.cs b/Pf2eModel/Migrations/Pf2eDbContextModelSnapshot.cs index 749c2b1..1692a71 100644 --- a/Pf2eModel/Migrations/Pf2eDbContextModelSnapshot.cs +++ b/Pf2eModel/Migrations/Pf2eDbContextModelSnapshot.cs @@ -21,7 +21,7 @@ namespace Pf2eModel.Migrations .HasAnnotation("ProductVersion", "9.0.4") .HasAnnotation("Relational:MaxIdentifierLength", 63); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "action_category", new[] { "archetype", "army_tactic", "army_war_action", "class-feat", "class-feature", "defensive", "familiar", "interaction", "kingdom_activity", "kingdom_feat", "kingdom_feature", "offensive", "unknown" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "action_category", new[] { "archetype", "army_tactic", "army_war_action", "class-feat", "class-feature", "defensive", "familiar", "interaction", "kingdom_activity", "kingdom_feat", "kingdom_feature", "offensive", "skill-action", "unknown" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "action_enum", new[] { "1", "1 hour", "1 minute", "1-2", "1-3", "10 minutes", "2", "2-3", "2/2 rounds", "3", "30 minutes", "5 minutes", "free", "free/1", "other", "passive", "reaction", "reaction/1", "reaction/2", "reaction/3", "unknown" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "attribute_values", new[] { "cha", "con", "dex", "free", "int", "str", "wis" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "class_progression_type", new[] { "ancestry_feat", "attribute_increase", "class_feat", "entity", "general_feat", "skill_feat", "skill_increase" }); @@ -545,10 +545,16 @@ namespace Pf2eModel.Migrations .HasColumnOrder(2) .HasComment("Количество действий"); + b.Property("Category") + .HasColumnType("action_category") + .HasColumnName("category") + .HasColumnOrder(3) + .HasComment("Категория действия"); + b.Property("Extra") .HasColumnType("text") .HasColumnName("extra") - .HasColumnOrder(3) + .HasColumnOrder(4) .HasComment("Дополнительная информация"); b.HasKey("Id") @@ -1236,8 +1242,8 @@ namespace Pf2eModel.Migrations .HasColumnOrder(1) .HasComment("Идентификатор"); - b.Property("Actions") - .HasColumnType("integer") + b.Property("Actions") + .HasColumnType("action_enum") .HasColumnName("actions") .HasColumnOrder(5) .HasComment("Количество действий"); @@ -1251,35 +1257,15 @@ namespace Pf2eModel.Migrations b.Property("Extra") .HasColumnType("text") .HasColumnName("extra") - .HasColumnOrder(10) + .HasColumnOrder(6) .HasComment("Дополнительная информация"); - b.Property("IsFreeAction") - .HasColumnType("boolean") - .HasColumnName("is_free_action") - .HasColumnOrder(8); - - b.Property("IsPassive") - .HasColumnType("boolean") - .HasColumnName("is_passive") - .HasColumnOrder(9); - - b.Property("IsReaction") - .HasColumnType("boolean") - .HasColumnName("is_reaction") - .HasColumnOrder(7); - b.Property("Level") .HasColumnType("integer") .HasColumnName("level") .HasColumnOrder(4) .HasComment("Уровень способности"); - b.Property("MaxActions") - .HasColumnType("integer") - .HasColumnName("max_actions") - .HasColumnOrder(6); - b.HasKey("Id") .HasName("pk_feats"); diff --git a/Pf2eModel/Model/Enum/ActionCategory.cs b/Pf2eModel/Model/Enum/ActionCategory.cs index 14a0adf..7dd5b0d 100644 --- a/Pf2eModel/Model/Enum/ActionCategory.cs +++ b/Pf2eModel/Model/Enum/ActionCategory.cs @@ -19,6 +19,9 @@ public enum ActionCategory [PgName("archetype")] Archetype, + [PgName("skill-action")] + SkillAction, + [PgName("class-feature")] ClassFeature, diff --git a/Pf2eModel/Model/Structure/Action.cs b/Pf2eModel/Model/Structure/Action.cs index 81052d4..6eb1997 100644 --- a/Pf2eModel/Model/Structure/Action.cs +++ b/Pf2eModel/Model/Structure/Action.cs @@ -30,9 +30,16 @@ public class Action : IEntity public ActionEnum Actions { get; set; } = ActionEnum.Unknown; /// - /// Дополнительная информация. + /// Категория действия. /// [Column(Order = 3)] + [Comment("Категория действия")] + public ActionCategory Category { get; set; } = ActionCategory.Unknown; + + /// + /// Дополнительная информация. + /// + [Column(Order = 4)] [Comment("Дополнительная информация")] public string? Extra { get; set; } } diff --git a/Pf2eModel/Model/Structure/Feat.cs b/Pf2eModel/Model/Structure/Feat.cs index 8dd05c5..b76b675 100644 --- a/Pf2eModel/Model/Structure/Feat.cs +++ b/Pf2eModel/Model/Structure/Feat.cs @@ -37,26 +37,17 @@ public class Feat : IEntity [Comment("Уровень способности")] public int Level { get; set; } + /// + /// Количество действий, необходимых для применения фита. + /// [Column(Order = 5)] [Comment("Количество действий")] - public int? Actions { get; set; } = null; - - [Column(Order = 6)] - public int? MaxActions { get; set; } = null; - - [Column(Order = 7)] - public bool IsReaction { get; set; } = false; - - [Column(Order = 8)] - public bool IsFreeAction { get; set; } = false; - - [Column(Order = 9)] - public bool IsPassive { get; set; } = false; + public ActionEnum Actions { get; set; } = ActionEnum.Other; /// /// Дополнительная информация. /// - [Column(Order = 10)] + [Column(Order = 6)] [Comment("Дополнительная информация")] public string? Extra { get; set; } diff --git a/README.md b/README.md index bfcb721..e672e51 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ schema.AddValue(data); // Добавление данных ## Aonprd (Архивы Нефиса) -### Общее (14 из 36) +### Общее (15 из 36) - [x] action.yaml - [x] ancestry.yaml @@ -175,8 +175,13 @@ schema.AddValue(data); // Добавление данных - [ ] class-kit.yaml - [ ] class-sample.yaml +### Что не дополучено с Архивов + +- Ссылка наследий (`heritage`) на родословные (`ancestry`). # TODO - Добавление экипировки - Добавление бестиария + +