diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/ArchetypeProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/ArchetypeProcessor.cs new file mode 100644 index 0000000..745c899 --- /dev/null +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/ArchetypeProcessor.cs @@ -0,0 +1,35 @@ +using Pf2eModel.Model.Enum; +using Pf2eModel.Model.Structure; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors; + +[AonprdProcessor("archetype")] +internal class ArchetypeProcessor(AonprdProcessorInput input) : AbstractProcessor(input) +{ + public override EntityType Type => EntityType.Archetype; + + public override Archetype Object { get; } = new(); + + protected override void Add() => Context.Archetypes.Add(Object); + + public override void Process() + { + base.Process(); + + Object.Level = Input.GetOptional("level"); + + + } + + protected override string GetDescription() + => base.GetDescription() + AddedDescription([ + "prerequisite_markdown", + "requirement_markdown", + "summary_markdown" + ]); +} diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/ClassProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/ClassProcessor.cs index 755c062..f00a414 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/ClassProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/ClassProcessor.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.Options; +using LinqToDB; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; using Newtonsoft.Json.Linq; using Pf2eModel.Model; using Pf2eModel.Model.Common; @@ -76,6 +78,8 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractProcessor(in Object.Tradition = SpellTradition.All; break; } + + ProcessDependecies(); } protected ICollection GetSkillTrainings() @@ -192,4 +196,16 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractProcessor(in return classTraining; }).ToList(); } + + protected void ProcessDependecies() + { + Trait? classTrait = Context.Traits.FirstOrDefault(t => t.Entity.Name == Entity.Name); + + if (classTrait is null) + { + return; + } + + classTrait.Type = TraitType.Class; + } } diff --git a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/FeatProcessor.cs b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/FeatProcessor.cs index 3ef0132..ea0b586 100644 --- a/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/FeatProcessor.cs +++ b/Pf2eDataScrapper/Importers/Implementations/Aonprd/DataBuilder/Processors/FeatProcessor.cs @@ -1,15 +1,10 @@ using Newtonsoft.Json.Linq; using Pf2eModel.Model.Enum; using Pf2eModel.Model.Structure; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors; -[AonprdProcessor("feat", ["trait", "source", "skill"])] +[AonprdProcessor("feat", ["trait", "source", "archetype"])] internal class FeatProcessor(AonprdProcessorInput input) : AbstractProcessor(input) { public override EntityType Type => EntityType.Feat; @@ -24,6 +19,9 @@ internal class FeatProcessor(AonprdProcessorInput input) : AbstractProcessor(inp Object.Level = Input.GetRequired("level"); + Object.Category = (Entity.Traits.Any(t => t.Type == TraitType.Class)) + ? ActionCategory.ClassFeat + : ActionCategory.Unknown; AonprdProcessorInput.ActionStruct action = Input.ResolveActionString(Input.GetOptional("actions") ?? ""); Object.Actions = action.Actions; @@ -32,21 +30,34 @@ internal class FeatProcessor(AonprdProcessorInput input) : AbstractProcessor(inp Object.IsPassive = action.IsPassive; Object.IsReaction = action.IsReaction; - - - - Object.Extra = GenerateExtra( "archetype", - "element", - "heighten", + "element", + "heighten", "heighten_group", "heighten_level", "school", "frequency" ); + string[] archetypeStrings = Input.GetOptional("archetype")?.Select(t => t.ToString()).ToArray() ?? []; + var archetypes = Context.Archetypes.Where(a => archetypeStrings.Contains(a.Entity.Name)).ToArray(); + + if (archetypes.Length != 0) + { + Object.Category = ActionCategory.Archetype; + } + + foreach (var archetype in archetypes) + { + Object.Archetypes.Add(archetype); + + if (Entity.Name.Contains("Dedication")) + { + archetype.DedicationFeat = Object; + } + } } protected override string GetDescription() diff --git a/Pf2eModel/Migrations/20250420145024_1.Designer.cs b/Pf2eModel/Migrations/20250421123520_1.Designer.cs similarity index 97% rename from Pf2eModel/Migrations/20250420145024_1.Designer.cs rename to Pf2eModel/Migrations/20250421123520_1.Designer.cs index 50d4a81..54e8cfb 100644 --- a/Pf2eModel/Migrations/20250420145024_1.Designer.cs +++ b/Pf2eModel/Migrations/20250421123520_1.Designer.cs @@ -13,7 +13,7 @@ using Pf2eModel.Model.Enum; namespace Pf2eModel.Migrations { [DbContext(typeof(Pf2eDbContext))] - [Migration("20250420145024_1")] + [Migration("20250421123520_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[] { "unknown", "offensive", "defensive", "interaction", "familiar", "army_tactic", "army_war_action", "kingdom_activity", "kingdom_feat", "kingdom_feature" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "action_category", new[] { "unknown", "archetype", "class-feature", "class-feat", "offensive", "defensive", "interaction", "familiar", "army_tactic", "army_war_action", "kingdom_activity", "kingdom_feat", "kingdom_feature" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "alias_type", new[] { "legacy", "english", "legacy_english", "hobby", "other" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "ancestry_vision", new[] { "normal", "low-light-vision", "dark-vision" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "attribute_values", new[] { "free", "str", "dex", "con", "int", "wis", "cha" }); @@ -36,14 +36,14 @@ namespace Pf2eModel.Migrations NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "entity_rarity", new[] { "common", "uncommon", "rare", "unique" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "entity_type", new[] { "unknown", "trait", "action", "ancestry", "archetype", "background", "backpack", "campaign_feature", "class", "condition", "deity", "feat", "heritage", "spell", "language" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "feat_action_type", new[] { "passive", "action", "reaction", "free" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "feat_category", new[] { "ancestryfeature", "classfeature", "calling", "class", "skill", "general", "ancestry", "bonus", "deityboon", "curse", "pfsboon", "campaign_feature" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "feat_category", new[] { "uncategorized", "ancestry-feature", "class-feature", "calling", "class", "skill", "general", "ancestry", "bonus", "deityboon", "curse", "pfsboon", "campaign-feature" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "size", new[] { "tiny", "small", "medium", "large" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "source_category", new[] { "rulebook", "adventure-path", "lost-omens", "adventures", "comics", "blog-posts", "society" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "spell_area_type", new[] { "burst", "emanation", "cone", "line", "square", "cube", "cylinder" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "spell_damage_category", new[] { "persistent", "splash" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "spell_damage_kinds", new[] { "damage", "healing", "any" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "training_stage", new[] { "untrained", "trained", "expert", "master", "legendary" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "trait_type", new[] { "regular", "tradition" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "trait_type", new[] { "regular", "class", "tradition" }); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("DeityTraining", b => @@ -622,7 +622,7 @@ namespace Pf2eModel.Migrations .HasColumnName("id") .HasColumnOrder(1); - b.Property("DedicationFeatId") + b.Property("DedicationFeatId") .HasColumnType("integer") .HasColumnName("dedication_feat_id") .HasColumnOrder(3); @@ -638,13 +638,32 @@ namespace Pf2eModel.Migrations .HasColumnOrder(2); b.HasKey("Id") - .HasName("pk_archetype"); + .HasName("pk_archetypes"); b.HasIndex("DedicationFeatId") .IsUnique() - .HasDatabaseName("ix_archetype_dedication_feat_id"); + .HasDatabaseName("ix_archetypes_dedication_feat_id"); - b.ToTable("archetype", (string)null); + b.ToTable("archetypes", (string)null); + }); + + modelBuilder.Entity("Pf2eModel.Model.Structure.ArchetypeRelation.ArchetypeFeats", b => + { + b.Property("ArchetypeId") + .HasColumnType("integer") + .HasColumnName("archetype_id"); + + b.Property("FeatId") + .HasColumnType("integer") + .HasColumnName("feat_id"); + + b.HasKey("ArchetypeId", "FeatId") + .HasName("pk_archetype_feats"); + + b.HasIndex("FeatId") + .HasDatabaseName("ix_archetype_feats_feat_id"); + + b.ToTable("archetype_feats", (string)null); }); modelBuilder.Entity("Pf2eModel.Model.Structure.Background", b => @@ -1091,11 +1110,6 @@ namespace Pf2eModel.Migrations .HasColumnName("actions") .HasColumnOrder(5); - b.Property("ArchetypeId") - .HasColumnType("integer") - .HasColumnName("archetype_id") - .HasColumnOrder(10); - b.Property("Category") .HasColumnType("action_category") .HasColumnName("category") @@ -1104,7 +1118,7 @@ namespace Pf2eModel.Migrations b.Property("Extra") .HasColumnType("text") .HasColumnName("extra") - .HasColumnOrder(11); + .HasColumnOrder(10); b.Property("IsFreeAction") .HasColumnType("boolean") @@ -1134,9 +1148,6 @@ namespace Pf2eModel.Migrations b.HasKey("Id") .HasName("pk_feats"); - b.HasIndex("ArchetypeId") - .HasDatabaseName("ix_feats_archetype_id"); - b.ToTable("feats", (string)null); }); @@ -1675,21 +1686,37 @@ namespace Pf2eModel.Migrations .WithOne() .HasForeignKey("Pf2eModel.Model.Structure.Archetype", "DedicationFeatId") .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_archetype_feats_dedication_feat_id"); + .HasConstraintName("fk_archetypes_feats_dedication_feat_id"); b.HasOne("Pf2eModel.Model.Base.Entity", "Entity") .WithOne() .HasForeignKey("Pf2eModel.Model.Structure.Archetype", "Id") .OnDelete(DeleteBehavior.Cascade) .IsRequired() - .HasConstraintName("fk_archetype_entities_id"); + .HasConstraintName("fk_archetypes_entities_id"); b.Navigation("DedicationFeat"); b.Navigation("Entity"); }); + modelBuilder.Entity("Pf2eModel.Model.Structure.ArchetypeRelation.ArchetypeFeats", b => + { + b.HasOne("Pf2eModel.Model.Structure.Archetype", null) + .WithMany() + .HasForeignKey("ArchetypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_archetype_feats_archetypes_archetype_id"); + + b.HasOne("Pf2eModel.Model.Structure.Feat", null) + .WithMany() + .HasForeignKey("FeatId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_archetype_feats_feats_feat_id"); + }); + modelBuilder.Entity("Pf2eModel.Model.Structure.Background", b => { b.HasOne("Pf2eModel.Model.Base.Entity", "Entity") @@ -1903,13 +1930,6 @@ namespace Pf2eModel.Migrations modelBuilder.Entity("Pf2eModel.Model.Structure.Feat", b => { - b.HasOne("Pf2eModel.Model.Structure.Archetype", "Archetype") - .WithMany("Feats") - .HasForeignKey("ArchetypeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_feats_archetype_archetype_id"); - b.HasOne("Pf2eModel.Model.Base.Entity", "Entity") .WithOne() .HasForeignKey("Pf2eModel.Model.Structure.Feat", "Id") @@ -1917,8 +1937,6 @@ namespace Pf2eModel.Migrations .IsRequired() .HasConstraintName("fk_feats_entities_id"); - b.Navigation("Archetype"); - b.Navigation("Entity"); }); @@ -2071,11 +2089,6 @@ namespace Pf2eModel.Migrations b.Navigation("Heritages"); }); - modelBuilder.Entity("Pf2eModel.Model.Structure.Archetype", b => - { - b.Navigation("Feats"); - }); - modelBuilder.Entity("Pf2eModel.Model.Structure.Background", b => { b.Navigation("BackgroundBoosts"); diff --git a/Pf2eModel/Migrations/20250420145024_1.cs b/Pf2eModel/Migrations/20250421123520_1.cs similarity index 96% rename from Pf2eModel/Migrations/20250420145024_1.cs rename to Pf2eModel/Migrations/20250421123520_1.cs index 09ec62f..878bb35 100644 --- a/Pf2eModel/Migrations/20250420145024_1.cs +++ b/Pf2eModel/Migrations/20250421123520_1.cs @@ -14,7 +14,7 @@ namespace Pf2eModel.Migrations protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.AlterDatabase() - .Annotation("Npgsql:Enum:action_category", "unknown,offensive,defensive,interaction,familiar,army_tactic,army_war_action,kingdom_activity,kingdom_feat,kingdom_feature") + .Annotation("Npgsql:Enum:action_category", "unknown,archetype,class-feature,class-feat,offensive,defensive,interaction,familiar,army_tactic,army_war_action,kingdom_activity,kingdom_feat,kingdom_feature") .Annotation("Npgsql:Enum:alias_type", "legacy,english,legacy_english,hobby,other") .Annotation("Npgsql:Enum:ancestry_vision", "normal,low-light-vision,dark-vision") .Annotation("Npgsql:Enum:attribute_values", "free,str,dex,con,int,wis,cha") @@ -26,14 +26,14 @@ namespace Pf2eModel.Migrations .Annotation("Npgsql:Enum:entity_rarity", "common,uncommon,rare,unique") .Annotation("Npgsql:Enum:entity_type", "unknown,trait,action,ancestry,archetype,background,backpack,campaign_feature,class,condition,deity,feat,heritage,spell,language") .Annotation("Npgsql:Enum:feat_action_type", "passive,action,reaction,free") - .Annotation("Npgsql:Enum:feat_category", "ancestryfeature,classfeature,calling,class,skill,general,ancestry,bonus,deityboon,curse,pfsboon,campaign_feature") + .Annotation("Npgsql:Enum:feat_category", "uncategorized,ancestry-feature,class-feature,calling,class,skill,general,ancestry,bonus,deityboon,curse,pfsboon,campaign-feature") .Annotation("Npgsql:Enum:size", "tiny,small,medium,large") .Annotation("Npgsql:Enum:source_category", "rulebook,adventure-path,lost-omens,adventures,comics,blog-posts,society") .Annotation("Npgsql:Enum:spell_area_type", "burst,emanation,cone,line,square,cube,cylinder") .Annotation("Npgsql:Enum:spell_damage_category", "persistent,splash") .Annotation("Npgsql:Enum:spell_damage_kinds", "damage,healing,any") .Annotation("Npgsql:Enum:training_stage", "untrained,trained,expert,master,legendary") - .Annotation("Npgsql:Enum:trait_type", "regular,tradition"); + .Annotation("Npgsql:Enum:trait_type", "regular,class,tradition"); migrationBuilder.CreateTable( name: "entities", @@ -269,6 +269,31 @@ namespace Pf2eModel.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "feats", + columns: table => new + { + id = table.Column(type: "integer", nullable: false), + category = table.Column(type: "action_category", nullable: false), + level = table.Column(type: "integer", nullable: false), + actions = table.Column(type: "integer", nullable: true), + 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), + extra = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_feats", x => x.id); + table.ForeignKey( + name: "fk_feats_entities_id", + column: x => x.id, + principalTable: "entities", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "languages", columns: table => new @@ -729,6 +754,52 @@ namespace Pf2eModel.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "archetypes", + columns: table => new + { + id = table.Column(type: "integer", nullable: false), + level = table.Column(type: "integer", nullable: false), + dedication_feat_id = table.Column(type: "integer", nullable: true), + extra = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_archetypes", x => x.id); + table.ForeignKey( + name: "fk_archetypes_entities_id", + column: x => x.id, + principalTable: "entities", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_archetypes_feats_dedication_feat_id", + column: x => x.dedication_feat_id, + principalTable: "feats", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "feat_prerequisites", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + feat_id = table.Column(type: "integer", nullable: false), + value = table.Column(type: "character varying(255)", maxLength: 255, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_feat_prerequisites", x => x.id); + table.ForeignKey( + name: "fk_feat_prerequisites_feats_feat_id", + column: x => x.feat_id, + principalTable: "feats", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "ancestry_languages", columns: table => new @@ -894,71 +965,23 @@ namespace Pf2eModel.Migrations }); migrationBuilder.CreateTable( - name: "archetype", + name: "archetype_feats", columns: table => new { - id = table.Column(type: "integer", nullable: false), - level = table.Column(type: "integer", nullable: false), - dedication_feat_id = table.Column(type: "integer", nullable: false), - extra = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_archetype", x => x.id); - table.ForeignKey( - name: "fk_archetype_entities_id", - column: x => x.id, - principalTable: "entities", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "feats", - columns: table => new - { - id = table.Column(type: "integer", nullable: false), - category = table.Column(type: "action_category", nullable: false), - level = table.Column(type: "integer", nullable: false), - actions = table.Column(type: "integer", nullable: true), - 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), archetype_id = table.Column(type: "integer", nullable: false), - extra = table.Column(type: "text", nullable: true) + feat_id = table.Column(type: "integer", nullable: false) }, constraints: table => { - table.PrimaryKey("pk_feats", x => x.id); + table.PrimaryKey("pk_archetype_feats", x => new { x.archetype_id, x.feat_id }); table.ForeignKey( - name: "fk_feats_archetype_archetype_id", + name: "fk_archetype_feats_archetypes_archetype_id", column: x => x.archetype_id, - principalTable: "archetype", + principalTable: "archetypes", principalColumn: "id", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "fk_feats_entities_id", - column: x => x.id, - principalTable: "entities", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "feat_prerequisites", - columns: table => new - { - id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - feat_id = table.Column(type: "integer", nullable: false), - value = table.Column(type: "character varying(255)", maxLength: 255, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("pk_feat_prerequisites", x => x.id); - table.ForeignKey( - name: "fk_feat_prerequisites_feats_feat_id", + name: "fk_archetype_feats_feats_feat_id", column: x => x.feat_id, principalTable: "feats", principalColumn: "id", @@ -981,8 +1004,13 @@ namespace Pf2eModel.Migrations column: "language_id"); migrationBuilder.CreateIndex( - name: "ix_archetype_dedication_feat_id", - table: "archetype", + name: "ix_archetype_feats_feat_id", + table: "archetype_feats", + column: "feat_id"); + + migrationBuilder.CreateIndex( + name: "ix_archetypes_dedication_feat_id", + table: "archetypes", column: "dedication_feat_id", unique: true); @@ -1081,11 +1109,6 @@ namespace Pf2eModel.Migrations table: "feat_prerequisites", column: "feat_id"); - migrationBuilder.CreateIndex( - name: "ix_feats_archetype_id", - table: "feats", - column: "archetype_id"); - migrationBuilder.CreateIndex( name: "ix_heritages_ancestry_id", table: "heritages", @@ -1110,31 +1133,11 @@ namespace Pf2eModel.Migrations name: "ix_spell_defenses_spell_id", table: "spell_defenses", column: "spell_id"); - - migrationBuilder.AddForeignKey( - name: "fk_archetype_feats_dedication_feat_id", - table: "archetype", - column: "dedication_feat_id", - principalTable: "feats", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); } /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropForeignKey( - name: "fk_archetype_entities_id", - table: "archetype"); - - migrationBuilder.DropForeignKey( - name: "fk_feats_entities_id", - table: "feats"); - - migrationBuilder.DropForeignKey( - name: "fk_archetype_feats_dedication_feat_id", - table: "archetype"); - migrationBuilder.DropTable( name: "actions"); @@ -1147,6 +1150,9 @@ namespace Pf2eModel.Migrations migrationBuilder.DropTable( name: "ancestry_languages"); + migrationBuilder.DropTable( + name: "archetype_feats"); + migrationBuilder.DropTable( name: "background_boosts"); @@ -1225,6 +1231,9 @@ namespace Pf2eModel.Migrations migrationBuilder.DropTable( name: "languages"); + migrationBuilder.DropTable( + name: "archetypes"); + migrationBuilder.DropTable( name: "backgrounds"); @@ -1255,14 +1264,11 @@ namespace Pf2eModel.Migrations migrationBuilder.DropTable( name: "spells"); - migrationBuilder.DropTable( - name: "entities"); - migrationBuilder.DropTable( name: "feats"); migrationBuilder.DropTable( - name: "archetype"); + name: "entities"); } } } diff --git a/Pf2eModel/Migrations/Pf2eDbContextModelSnapshot.cs b/Pf2eModel/Migrations/Pf2eDbContextModelSnapshot.cs index 789fd1a..5cc4f9e 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[] { "unknown", "offensive", "defensive", "interaction", "familiar", "army_tactic", "army_war_action", "kingdom_activity", "kingdom_feat", "kingdom_feature" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "action_category", new[] { "unknown", "archetype", "class-feature", "class-feat", "offensive", "defensive", "interaction", "familiar", "army_tactic", "army_war_action", "kingdom_activity", "kingdom_feat", "kingdom_feature" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "alias_type", new[] { "legacy", "english", "legacy_english", "hobby", "other" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "ancestry_vision", new[] { "normal", "low-light-vision", "dark-vision" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "attribute_values", new[] { "free", "str", "dex", "con", "int", "wis", "cha" }); @@ -33,14 +33,14 @@ namespace Pf2eModel.Migrations NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "entity_rarity", new[] { "common", "uncommon", "rare", "unique" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "entity_type", new[] { "unknown", "trait", "action", "ancestry", "archetype", "background", "backpack", "campaign_feature", "class", "condition", "deity", "feat", "heritage", "spell", "language" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "feat_action_type", new[] { "passive", "action", "reaction", "free" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "feat_category", new[] { "ancestryfeature", "classfeature", "calling", "class", "skill", "general", "ancestry", "bonus", "deityboon", "curse", "pfsboon", "campaign_feature" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "feat_category", new[] { "uncategorized", "ancestry-feature", "class-feature", "calling", "class", "skill", "general", "ancestry", "bonus", "deityboon", "curse", "pfsboon", "campaign-feature" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "size", new[] { "tiny", "small", "medium", "large" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "source_category", new[] { "rulebook", "adventure-path", "lost-omens", "adventures", "comics", "blog-posts", "society" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "spell_area_type", new[] { "burst", "emanation", "cone", "line", "square", "cube", "cylinder" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "spell_damage_category", new[] { "persistent", "splash" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "spell_damage_kinds", new[] { "damage", "healing", "any" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "training_stage", new[] { "untrained", "trained", "expert", "master", "legendary" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "trait_type", new[] { "regular", "tradition" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "trait_type", new[] { "regular", "class", "tradition" }); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("DeityTraining", b => @@ -619,7 +619,7 @@ namespace Pf2eModel.Migrations .HasColumnName("id") .HasColumnOrder(1); - b.Property("DedicationFeatId") + b.Property("DedicationFeatId") .HasColumnType("integer") .HasColumnName("dedication_feat_id") .HasColumnOrder(3); @@ -635,13 +635,32 @@ namespace Pf2eModel.Migrations .HasColumnOrder(2); b.HasKey("Id") - .HasName("pk_archetype"); + .HasName("pk_archetypes"); b.HasIndex("DedicationFeatId") .IsUnique() - .HasDatabaseName("ix_archetype_dedication_feat_id"); + .HasDatabaseName("ix_archetypes_dedication_feat_id"); - b.ToTable("archetype", (string)null); + b.ToTable("archetypes", (string)null); + }); + + modelBuilder.Entity("Pf2eModel.Model.Structure.ArchetypeRelation.ArchetypeFeats", b => + { + b.Property("ArchetypeId") + .HasColumnType("integer") + .HasColumnName("archetype_id"); + + b.Property("FeatId") + .HasColumnType("integer") + .HasColumnName("feat_id"); + + b.HasKey("ArchetypeId", "FeatId") + .HasName("pk_archetype_feats"); + + b.HasIndex("FeatId") + .HasDatabaseName("ix_archetype_feats_feat_id"); + + b.ToTable("archetype_feats", (string)null); }); modelBuilder.Entity("Pf2eModel.Model.Structure.Background", b => @@ -1088,11 +1107,6 @@ namespace Pf2eModel.Migrations .HasColumnName("actions") .HasColumnOrder(5); - b.Property("ArchetypeId") - .HasColumnType("integer") - .HasColumnName("archetype_id") - .HasColumnOrder(10); - b.Property("Category") .HasColumnType("action_category") .HasColumnName("category") @@ -1101,7 +1115,7 @@ namespace Pf2eModel.Migrations b.Property("Extra") .HasColumnType("text") .HasColumnName("extra") - .HasColumnOrder(11); + .HasColumnOrder(10); b.Property("IsFreeAction") .HasColumnType("boolean") @@ -1131,9 +1145,6 @@ namespace Pf2eModel.Migrations b.HasKey("Id") .HasName("pk_feats"); - b.HasIndex("ArchetypeId") - .HasDatabaseName("ix_feats_archetype_id"); - b.ToTable("feats", (string)null); }); @@ -1672,21 +1683,37 @@ namespace Pf2eModel.Migrations .WithOne() .HasForeignKey("Pf2eModel.Model.Structure.Archetype", "DedicationFeatId") .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_archetype_feats_dedication_feat_id"); + .HasConstraintName("fk_archetypes_feats_dedication_feat_id"); b.HasOne("Pf2eModel.Model.Base.Entity", "Entity") .WithOne() .HasForeignKey("Pf2eModel.Model.Structure.Archetype", "Id") .OnDelete(DeleteBehavior.Cascade) .IsRequired() - .HasConstraintName("fk_archetype_entities_id"); + .HasConstraintName("fk_archetypes_entities_id"); b.Navigation("DedicationFeat"); b.Navigation("Entity"); }); + modelBuilder.Entity("Pf2eModel.Model.Structure.ArchetypeRelation.ArchetypeFeats", b => + { + b.HasOne("Pf2eModel.Model.Structure.Archetype", null) + .WithMany() + .HasForeignKey("ArchetypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_archetype_feats_archetypes_archetype_id"); + + b.HasOne("Pf2eModel.Model.Structure.Feat", null) + .WithMany() + .HasForeignKey("FeatId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_archetype_feats_feats_feat_id"); + }); + modelBuilder.Entity("Pf2eModel.Model.Structure.Background", b => { b.HasOne("Pf2eModel.Model.Base.Entity", "Entity") @@ -1900,13 +1927,6 @@ namespace Pf2eModel.Migrations modelBuilder.Entity("Pf2eModel.Model.Structure.Feat", b => { - b.HasOne("Pf2eModel.Model.Structure.Archetype", "Archetype") - .WithMany("Feats") - .HasForeignKey("ArchetypeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_feats_archetype_archetype_id"); - b.HasOne("Pf2eModel.Model.Base.Entity", "Entity") .WithOne() .HasForeignKey("Pf2eModel.Model.Structure.Feat", "Id") @@ -1914,8 +1934,6 @@ namespace Pf2eModel.Migrations .IsRequired() .HasConstraintName("fk_feats_entities_id"); - b.Navigation("Archetype"); - b.Navigation("Entity"); }); @@ -2068,11 +2086,6 @@ namespace Pf2eModel.Migrations b.Navigation("Heritages"); }); - modelBuilder.Entity("Pf2eModel.Model.Structure.Archetype", b => - { - b.Navigation("Feats"); - }); - modelBuilder.Entity("Pf2eModel.Model.Structure.Background", b => { b.Navigation("BackgroundBoosts"); diff --git a/Pf2eModel/Model/Enum/ActionCategory.cs b/Pf2eModel/Model/Enum/ActionCategory.cs index 60a5bf3..e80f946 100644 --- a/Pf2eModel/Model/Enum/ActionCategory.cs +++ b/Pf2eModel/Model/Enum/ActionCategory.cs @@ -6,6 +6,19 @@ public enum ActionCategory { Unknown, + [PgName("archetype")] + Archetype, + + [PgName("class-feature")] + ClassFeature, + + [PgName("class-feat")] + ClassFeat, + + + + + [PgName("offensive")] Offensive, diff --git a/Pf2eModel/Model/Enum/FeatCategory.cs b/Pf2eModel/Model/Enum/FeatCategory.cs index 3923e82..eea9e0b 100644 --- a/Pf2eModel/Model/Enum/FeatCategory.cs +++ b/Pf2eModel/Model/Enum/FeatCategory.cs @@ -4,11 +4,14 @@ namespace Pf2eModel.Model.Enum; public enum FeatCategory { - [PgName("ancestryfeature")] - Ancestryfeature, + [PgName("uncategorized")] + Uncategorized, - [PgName("classfeature")] - Classfeature, + [PgName("ancestry-feature")] + AncestryFeature, + + [PgName("class-feature")] + ClassFeature, [PgName("calling")] Calling, @@ -37,6 +40,6 @@ public enum FeatCategory [PgName("pfsboon")] Pfsboon, - [PgName("campaign_feature")] + [PgName("campaign-feature")] CampaignFeature, } \ No newline at end of file diff --git a/Pf2eModel/Model/Enum/TraitType.cs b/Pf2eModel/Model/Enum/TraitType.cs index 0d71477..fc9432d 100644 --- a/Pf2eModel/Model/Enum/TraitType.cs +++ b/Pf2eModel/Model/Enum/TraitType.cs @@ -7,6 +7,9 @@ public enum TraitType [PgName("regular")] Regular, + [PgName("class")] + Class, + [PgName("tradition")] Tradition } diff --git a/Pf2eModel/Model/Structure/Archetype.cs b/Pf2eModel/Model/Structure/Archetype.cs index 90a61aa..39fde77 100644 --- a/Pf2eModel/Model/Structure/Archetype.cs +++ b/Pf2eModel/Model/Structure/Archetype.cs @@ -1,4 +1,5 @@ using Pf2eModel.Model.Base; +using Pf2eModel.Model.Enum; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -9,6 +10,7 @@ using System.Threading.Tasks; namespace Pf2eModel.Model.Structure; +[EntityOfType(EntityType.Archetype)] public class Archetype : IEntity { [Key] @@ -21,7 +23,7 @@ public class Archetype : IEntity public int Level { get; set; } [Column(Order = 3)] - public int DedicationFeatId { get; set; } + public int? DedicationFeatId { get; set; } = null; [Column(Order = 4)] public string? Extra { get; set; } diff --git a/Pf2eModel/Model/Structure/ArchetypeRelation/ArchetypeFeats.cs b/Pf2eModel/Model/Structure/ArchetypeRelation/ArchetypeFeats.cs new file mode 100644 index 0000000..6410d0c --- /dev/null +++ b/Pf2eModel/Model/Structure/ArchetypeRelation/ArchetypeFeats.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pf2eModel.Model.Structure.ArchetypeRelation; + +[PrimaryKey(nameof(ArchetypeId), nameof(FeatId))] +internal class ArchetypeFeats +{ + public int ArchetypeId { get; set; } + + public int FeatId { get; set; } +} diff --git a/Pf2eModel/Model/Structure/Feat.cs b/Pf2eModel/Model/Structure/Feat.cs index e6f9059..043fe92 100644 --- a/Pf2eModel/Model/Structure/Feat.cs +++ b/Pf2eModel/Model/Structure/Feat.cs @@ -37,13 +37,11 @@ public partial class Feat : IEntity [Column(Order = 9)] public bool IsPassive { get; set; } = false; - [Column(Order = 10)] - public int ArchetypeId { get; set; } - [Column(Order = 11)] + [Column(Order = 10)] public string? Extra { get; set; } - public Archetype Archetype { get; set; } = null!; + public virtual ICollection Archetypes { get; set; } = []; public virtual ICollection FeatPrerequisites { get; set; } = []; } diff --git a/Pf2eModel/Pf2eDbContext.cs b/Pf2eModel/Pf2eDbContext.cs index 21034cf..94e0bd5 100644 --- a/Pf2eModel/Pf2eDbContext.cs +++ b/Pf2eModel/Pf2eDbContext.cs @@ -34,6 +34,8 @@ public partial class Pf2eDbContext : DbContext public virtual DbSet Ancestries { get; set; } + public virtual DbSet Archetypes { get; set; } + public virtual DbSet AncestryBoosts { get; set; } public virtual DbSet AncestryItems { get; set; } diff --git a/Pf2eModel/Pf2eDbContextModel.cs b/Pf2eModel/Pf2eDbContextModel.cs index f7f5a04..af0329b 100644 --- a/Pf2eModel/Pf2eDbContextModel.cs +++ b/Pf2eModel/Pf2eDbContextModel.cs @@ -9,6 +9,7 @@ using Pf2eModel.Model.Common; using Pf2eModel.Model.Enum; using Pf2eModel.Model.Structure; using Pf2eModel.Model.Structure.AncestryRelation; +using Pf2eModel.Model.Structure.ArchetypeRelation; using Pf2eModel.Model.Structure.BackgroundRelation; using Pf2eModel.Model.Structure.ClassRelation; using Pf2eModel.Model.Structure.DeityRelation; @@ -179,9 +180,11 @@ public partial class Pf2eDbContext .HasForeignKey(a => a.DedicationFeatId) .OnDelete(DeleteBehavior.Cascade); - entity.HasMany(a => a.Feats).WithOne(f => f.Archetype) - .HasForeignKey(f => f.ArchetypeId) - .OnDelete(DeleteBehavior.Cascade); + entity.HasMany(a => a.Feats).WithMany(f => f.Archetypes) + .UsingEntity( + l => l.HasOne().WithMany().HasForeignKey(af => af.FeatId), + r => r.HasOne().WithMany().HasForeignKey(af => af.ArchetypeId) + ); }); // Background diff --git a/Pf2eViewer/EntityConverter.cs b/Pf2eViewer/EntityConverter.cs index bf16cfe..397dc0f 100644 --- a/Pf2eViewer/EntityConverter.cs +++ b/Pf2eViewer/EntityConverter.cs @@ -39,12 +39,12 @@ internal class EntityConverter : JsonConverter public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { Dictionary dictionary = DictionarySerialization(value!); - + /* if (value.GetType() != typeof(Entity)) { dictionary.Remove("Entity"); } - + */ switch (value) { case Entity entity: @@ -61,6 +61,7 @@ internal class EntityConverter : JsonConverter foreach (KeyValuePair keyValuePair in dictionary) { writer.WritePropertyName(keyValuePair.Key, true); + serializer.Serialize(writer, keyValuePair.Value); } diff --git a/Pf2eViewer/MainViewForm.cs b/Pf2eViewer/MainViewForm.cs index 28f2f58..ae10144 100644 --- a/Pf2eViewer/MainViewForm.cs +++ b/Pf2eViewer/MainViewForm.cs @@ -175,7 +175,8 @@ public partial class MainViewForm : Form Converters = [ new EntityConverter(), new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() }, - ] + ], + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, }; string result = JsonConvert.SerializeObject(entity, settings); @@ -195,6 +196,14 @@ public partial class MainViewForm : Form .Include(a => a.AncestryBoosts) .FirstOrDefault(e => e.Id == entity.Id); + case EntityType.Archetype: + return Context.Archetypes + .Include(a => a.DedicationFeat) + .ThenInclude(f => f.Entity) + .Include(a => a.Feats) + .ThenInclude(f => f.Entity) + .FirstOrDefault(a => a.Id == entity.Id); + case EntityType.Background: return Context.Backgrounds .Include(b => b.BackgroundBoosts) @@ -211,6 +220,12 @@ public partial class MainViewForm : Form .Include(c => c.ClassProgressions) .FirstOrDefault(c => c.Id == entity.Id); + case EntityType.Feat: + return Context.Feats + .Include(f => f.Archetypes) + .ThenInclude(a => a.Entity) + .FirstOrDefault(f => f.Id == entity.Id); + default: Type type = EntityOfTypeAttribute.Resolve(entity); return (IEntity?) Context.Find(type, entity.Id); diff --git a/README.md b/README.md index 8f3b046..d5264e2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Pf2e Data Screapper +# Pf2e Data Scrapper Программа обработки данных для игры Pathfinder 2e для создания БД для дальнейшего использования на сайте локализации Pf2e. @@ -70,75 +70,85 @@ schema.AddValue(data); // Добавление данных ### Общее - [x] action.yaml - [x] ancestry.yaml -- [ ] apparition.yaml -- [ ] arcane-school.yaml -- [ ] arcane-thesis.yaml -- [ ] archetype.yaml -- [ ] article.yaml -- [ ] background.yaml -- [ ] bloodline.yaml -- [ ] category-page.yaml -- [ ] cause.yaml -- [ ] class-feature.yaml +- [x] archetype.yaml +- [x] background.yaml - [ ] class-kit.yaml - [ ] class-sample.yaml -- [ ] class.yaml +- [x] class.yaml - [ ] condition.yaml -- [ ] conscious-mind.yaml - [ ] creature-ability.yaml - [ ] curse.yaml -- [ ] deity-category.yaml -- [ ] deity.yaml - [ ] deviant-ability-classification.yaml - [ ] disease.yaml -- [ ] doctrine.yaml -- [ ] domain.yaml -- [ ] druidic-order.yaml -- [ ] eidolon.yaml -- [ ] element.yaml -- [ ] epithet.yaml -- [x] feat.yaml -- [ ] hazard.yaml -- [ ] hellknight-order.yaml - [ ] heritage.yaml -- [ ] hunters-edge.yaml -- [ ] hybrid-study.yaml -- [ ] ikon.yaml -- [ ] implement.yaml -- [ ] innovation.yaml -- [ ] instinct.yaml - [ ] kingdom-event.yaml - [ ] kingdom-structure.yaml - [x] language.yaml -- [ ] lesson.yaml -- [ ] methodology.yaml -- [ ] muse.yaml -- [ ] mystery.yaml - [ ] mythic-calling.yaml -- [ ] patron.yaml - [ ] plane.yaml -- [ ] practice.yaml -- [ ] racket.yaml - [ ] relic.yaml -- [ ] research-field.yaml - [ ] ritual.yaml -- [ ] rules.yaml - [ ] sidebar.yaml - [ ] skill-general-action.yaml - [x] skill.yaml - [x] source.yaml - [ ] spell.yaml -- [ ] style.yaml -- [ ] subconscious-mind.yaml -- [ ] tenet.yaml - [ ] tradition.yaml - [x] trait.yaml - [ ] warfare-army.yaml - [ ] warfare-tactic.yaml -- [ ] way.yaml - [ ] weapon-sub.yaml - [ ] weather-hazard.yaml +**Тексты** +- [ ] article.yaml +- [ ] category-page.yaml +- [ ] rules.yaml + +**Боги** +- [ ] deity.yaml +- [ ] deity-category.yaml +- [ ] domain.yaml + +**Фиты** +- [x] feat.yaml +- [ ] class-feature.yaml + +**Подклассы** +- [ ] research-field.yaml (Alchemist) +- [ ] apparition.yaml (Animist) +- [ ] practice.yaml (Animist) +- [ ] instinct.yaml (Barbarian) +- [ ] muse.yaml (Bard) +- [ ] cause.yaml (Champion) +- [ ] tenet.yaml (Champion) +- [ ] doctrine.yaml (Cleric) +- [ ] druidic-order.yaml (Druid) +- [ ] methodology.yaml (Investigator) +- [ ] element.yaml (Kineticist) +- [ ] hybrid-study.yaml (Magus) +- [ ] mystery.yaml (Oracle) +- [ ] conscious-mind.yaml (Psychic) +- [ ] subconscious-mind.yaml (Psychic) +- [ ] hunters-edge.yaml (Ranger) +- [ ] racket.yaml (Rogue) +- [ ] bloodline.yaml (Sorcerer) +- [ ] style.yaml (Swashbuckler) +- [ ] implement.yaml (Thaumaturge) +- [ ] lesson.yaml (Witch) +- [ ] patron.yaml (Witch) +- [ ] arcane-school.yaml (Wizard) +- [ ] arcane-thesis.yaml (Wizard) +- [ ] way.yaml (Gunslinger) +- [ ] innovation.yaml (Innovator) +- [ ] ikon.yaml (Exemplar) +- [ ] epithet.yaml (Exemplar) + +- [ ] hellknight-order.yaml +- [ ] eidolon.yaml + + + ### Бестиарий Готово **0** из 10 @@ -169,6 +179,7 @@ schema.AddValue(data); // Добавление данных - [ ] siege-weapon.yaml - [ ] vehicle.yaml - [ ] weapon.yaml +- [ ] hazard.yaml