Работа над импортом заклинаний
This commit is contained in:
+18
@@ -52,8 +52,26 @@ internal class AonprdProcessorCollection
|
||||
}
|
||||
}
|
||||
|
||||
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<string, int> priorities = [];
|
||||
|
||||
while (priorities.Count < Items.Count)
|
||||
|
||||
@@ -60,6 +60,12 @@ internal class AonprdProcessorInput(JObject input) : ProcessorInput(input)
|
||||
result.MaxActions = 3;
|
||||
break;
|
||||
|
||||
case "Two Actions to 2 rounds":
|
||||
result.Actions = 2;
|
||||
result.MaxActions = 3;
|
||||
result.TwoRounds = true;
|
||||
break;
|
||||
|
||||
case "Reaction or One Action":
|
||||
result.IsReaction = true;
|
||||
result.Actions = result.MaxActions = 1;
|
||||
@@ -90,5 +96,6 @@ internal class AonprdProcessorInput(JObject input) : ProcessorInput(input)
|
||||
public bool IsPassive;
|
||||
public bool IsReaction;
|
||||
public bool IsFreeAction;
|
||||
public bool TwoRounds;
|
||||
}
|
||||
}
|
||||
|
||||
+27
@@ -33,6 +33,33 @@ public static class AonprdEnumResolver
|
||||
{ "other", AttributeValues.Free },
|
||||
}
|
||||
),
|
||||
new Solver<ActionEnum>(
|
||||
new()
|
||||
{
|
||||
{ "Single Action", ActionEnum.SingleAction },
|
||||
{ "Two Actions", ActionEnum.TwoActions },
|
||||
{ "Three Actions", ActionEnum.ThreeActions },
|
||||
{ "Reaction", ActionEnum.Reaction },
|
||||
{ "Free Action", ActionEnum.FreeAction },
|
||||
{ "Single Action to Three Actions", ActionEnum.SingleActionToThreeActions },
|
||||
{ "Single Action or more Actions", ActionEnum.SingleActionToThreeActions },
|
||||
{ "Single Action or Two Actions", ActionEnum.SingleActionToTwoActions },
|
||||
{ "Single Action to Two Actions", ActionEnum.SingleActionToTwoActions },
|
||||
{ "Two Actions or Three Actions", ActionEnum.TwoActionsToThreeActions },
|
||||
{ "Two Actions to 2 rounds", ActionEnum.TwoActionsToTwoRounds },
|
||||
{ "Reaction or One Action", ActionEnum.ReactionOrOneAction },
|
||||
{ "Reaction or Two Actions", ActionEnum.ReactionOrTwoAction },
|
||||
{ "Reaction or Three Actions", ActionEnum.ReactionOrThreeAction },
|
||||
{ "Free Action or One Action", ActionEnum.FreeActionOrOneAction },
|
||||
{ "1 Minute", ActionEnum.OneMinute },
|
||||
{ "1 minute", ActionEnum.OneMinute },
|
||||
{ "5 minutes", ActionEnum.FiveMinutes },
|
||||
{ "10 minutes", ActionEnum.TenMinutes },
|
||||
{ "30 minutes", ActionEnum.ThirtyMinutes },
|
||||
{ "1 hour", ActionEnum.OneHour },
|
||||
{ "<i>Nethys Note: No cast time was printed</i>", ActionEnum.Unknown },
|
||||
}
|
||||
),
|
||||
];
|
||||
|
||||
public static T Resolve<T>(string value)
|
||||
|
||||
@@ -6,6 +6,24 @@ internal partial class StringHelper
|
||||
{
|
||||
private StringHelper() { }
|
||||
|
||||
public List<MarkdownLink> ParseMarkdown(string input)
|
||||
{
|
||||
List<MarkdownLink> links = [];
|
||||
Match match = MarkdownRegex().Match(input);
|
||||
if (match.Captures.Count > 0)
|
||||
{
|
||||
links.Add(
|
||||
new()
|
||||
{
|
||||
Prefix = match.Groups[1].Value.Trim(),
|
||||
Text = match.Groups[2].Value.Trim(),
|
||||
Url = match.Groups[3].Value.Trim(),
|
||||
}
|
||||
);
|
||||
}
|
||||
return links;
|
||||
}
|
||||
|
||||
public string ResolveSource(string input)
|
||||
{
|
||||
Match match = SourceSuffixRegex().Match(input);
|
||||
@@ -16,4 +34,14 @@ internal partial class StringHelper
|
||||
|
||||
[GeneratedRegex(@"^\[.*?\]\(.*?\)\s+(.*)$")]
|
||||
private static partial Regex SourceSuffixRegex();
|
||||
|
||||
[GeneratedRegex(@"(.*?)\[(.*?)\]\((.*?)\)")]
|
||||
private static partial Regex MarkdownRegex();
|
||||
}
|
||||
|
||||
internal class MarkdownLink
|
||||
{
|
||||
public string Prefix { get; set; } = "";
|
||||
public string Text { get; set; } = "";
|
||||
public string Url { get; set; } = "";
|
||||
}
|
||||
|
||||
+7
-2
@@ -1,16 +1,21 @@
|
||||
using Pf2eModel.Model.Common;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common;
|
||||
|
||||
[AonprdProcessor("skill", [])]
|
||||
internal class TrainingProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
||||
internal class SkillProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
||||
{
|
||||
public Training Training = null!;
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
Training = new() { Name = Input.GetRequired<string>("name"), Type = TrainingType.Skill };
|
||||
Training = new()
|
||||
{
|
||||
Name = new() { { LocaleType.English, Input.GetRequired<string>("name") } },
|
||||
Type = TrainingType.Skill,
|
||||
};
|
||||
}
|
||||
|
||||
public override void Save()
|
||||
+57
-3
@@ -1,8 +1,15 @@
|
||||
using Pf2eModel.Model.Structure;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.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;
|
||||
|
||||
[AonprdProcessor("apparition", ["class"])]
|
||||
[AonprdProcessor("apparition", ["class", "spell", "trainings"])]
|
||||
internal class ApparitionProcessor(AonprdProcessorInput input) : AbstractSubclassProcessor(input)
|
||||
{
|
||||
public override Subclass Object { get; } = new();
|
||||
@@ -11,7 +18,54 @@ internal class ApparitionProcessor(AonprdProcessorInput input) : AbstractSubclas
|
||||
|
||||
public override string GroupName => "Apparition";
|
||||
|
||||
public override void ProcessObject() { }
|
||||
public override void ProcessObject()
|
||||
{
|
||||
// Spells
|
||||
string spellMd = Input.GetRequired<string>("spells_markdown");
|
||||
List<string> spellUrls = StringHelper.ParseMarkdown(spellMd).Select(l => l.Url).ToList();
|
||||
|
||||
List<int> spellIds = Context
|
||||
.EntityExternals.Where(x => spellUrls.Contains(x.Suffix))
|
||||
.Select(x => x.Entity.Id)
|
||||
.ToList();
|
||||
|
||||
List<Entity> spells = Context
|
||||
.Spells.Where(s => spellIds.Contains(s.Id))
|
||||
.Select(s => s.Entity)
|
||||
.ToList();
|
||||
|
||||
foreach (Entity spellEntity in spells)
|
||||
{
|
||||
Object.Entities.Add(spellEntity);
|
||||
}
|
||||
|
||||
// Trainings
|
||||
string trainingMd = Input.GetRequired<string>("skill_markdown");
|
||||
|
||||
List<string> trainingNames = trainingMd.Split(", ").ToList();
|
||||
List<Training> trainings = Context
|
||||
.Trainings.Where(t => Pf2eDbContext.LocaleSearchArray(t.Name, trainingNames))
|
||||
.ToList();
|
||||
|
||||
foreach (string name in trainingNames)
|
||||
{
|
||||
Training? training = trainings.FirstOrDefault(t => t.Name!.Contains(name));
|
||||
training ??= new()
|
||||
{
|
||||
Name = new() { { LocaleType.English, name } },
|
||||
Type = TrainingType.Lore,
|
||||
};
|
||||
|
||||
Object.Trainings.Add(
|
||||
new()
|
||||
{
|
||||
Subclass = Object,
|
||||
Training = training,
|
||||
Stage = TrainingStage.Trained,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected override string GetDescription() =>
|
||||
base.GetDescription()
|
||||
|
||||
+2
-11
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||
|
||||
[AonprdProcessor("action")]
|
||||
// [AonprdProcessor("action")]
|
||||
internal class ActionProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
{
|
||||
public override EntityType Type => EntityType.Action;
|
||||
@@ -29,16 +29,7 @@ internal class ActionProcessor(AonprdProcessorInput input) : AbstractEntityProce
|
||||
|
||||
base.Process();
|
||||
|
||||
AonprdProcessorInput.ActionStruct action = Input.ResolveActionString(
|
||||
Input.GetOptional<string>("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.Passive);
|
||||
Object.Extra = GenerateExtra("school");
|
||||
}
|
||||
|
||||
|
||||
+15
-8
@@ -1,6 +1,8 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Common;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
using Pf2eModel.Model.Structure.ClassRelation;
|
||||
@@ -82,13 +84,14 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractEntityProces
|
||||
|
||||
protected ICollection<ClassTraining> GetSkillTrainings()
|
||||
{
|
||||
string[] skillNames = Input
|
||||
List<string> skillNames = Input
|
||||
.GetRequired<JArray>("skill_proficiency")
|
||||
.Select(token => token.ToString())
|
||||
.ToArray();
|
||||
.ToList();
|
||||
|
||||
Training[] skills = Context.Trainings.Where(t => skillNames.Contains(t.Name)).ToArray();
|
||||
// Training[] skills = Context.Trainings.Where(t => Pf2eDbContext.LocaleSearchArray(t.Name, skillNames)).ToArray();
|
||||
Training[] skills = Context
|
||||
.Trainings.Where(t => Pf2eDbContext.LocaleSearchArray(t.Name, skillNames))
|
||||
.ToArray();
|
||||
|
||||
return skills
|
||||
.Select(skill => new ClassTraining()
|
||||
@@ -121,12 +124,16 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractEntityProces
|
||||
foreach (string part in parts)
|
||||
{
|
||||
Training? training = Context.Trainings.FirstOrDefault(t =>
|
||||
t.Name == part && t.Type == type
|
||||
Pf2eDbContext.LocaleSearch(t.Name, part) && t.Type == type
|
||||
);
|
||||
|
||||
if (training == null)
|
||||
{
|
||||
training = new Training() { Name = part, Type = type };
|
||||
training = new Training()
|
||||
{
|
||||
Name = new() { [LocaleType.English] = part },
|
||||
Type = type,
|
||||
};
|
||||
|
||||
Context.Trainings.Add(training);
|
||||
}
|
||||
@@ -160,7 +167,7 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractEntityProces
|
||||
{
|
||||
Dictionary<string, Training> result = Context
|
||||
.Trainings.Where(t => t.Type == TrainingType.Save)
|
||||
.ToDictionary(t => t.Name);
|
||||
.ToDictionary(t => t.Name[LocaleType.English]);
|
||||
|
||||
foreach (string name in new[] { "Will", "Fortitude", "Reflex", "Perception" })
|
||||
{
|
||||
@@ -171,7 +178,7 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractEntityProces
|
||||
|
||||
Training training = new()
|
||||
{
|
||||
Name = name,
|
||||
Name = new() { [LocaleType.English] = name },
|
||||
Type = (name == "Perception") ? TrainingType.Perception : TrainingType.Save,
|
||||
};
|
||||
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
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;
|
||||
|
||||
[AonprdProcessor("spell")]
|
||||
internal class SpellProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||
{
|
||||
public override EntityType Type => EntityType.Spell;
|
||||
|
||||
public override Spell Object { get; } = new();
|
||||
|
||||
public override void Add() => Context.Spells.Add(Object);
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
base.Process();
|
||||
|
||||
Object.Level = Input.GetRequired<int>("level");
|
||||
Object.Actions = Input.EnumOptional("actions", ActionEnum.Unknown);
|
||||
Object.IsFocus = Input.GetRequired<string>("spell_type") == "Focus";
|
||||
|
||||
switch (Input.GetRequired<string>("spell_type"))
|
||||
{
|
||||
case "Focus":
|
||||
Object.IsFocus = true;
|
||||
break;
|
||||
case "Cantrip":
|
||||
Object.Level = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (string areaType in Input.GetOptional<string[]>("area_type") ?? [])
|
||||
{
|
||||
Object.SpellAreas.Add(
|
||||
new()
|
||||
{
|
||||
Spell = Object,
|
||||
Type = Input.EnumRequired<SpellAreaType>(areaType),
|
||||
Value = 0,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected override string GetDescription() =>
|
||||
base.GetDescription()
|
||||
+ AddedDescription(
|
||||
[
|
||||
"area_raw",
|
||||
"bloodline_markdown",
|
||||
"deity_markdown",
|
||||
"domain_markdown",
|
||||
"lesson_markdown",
|
||||
"mystery_markdown",
|
||||
"requirement_markdown",
|
||||
"summary_markdown",
|
||||
"tradition_markdown",
|
||||
"patron_theme_markdown",
|
||||
"trigger_markdown",
|
||||
"saving_throw_markdown",
|
||||
"target_markdown",
|
||||
]
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user