Compare commits
3
Commits
311a14a39d
...
06d154eccc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06d154eccc | ||
|
|
76167f1b24 | ||
|
|
9d0683a23f |
+7
-1
@@ -4,6 +4,11 @@ root = true
|
|||||||
# Файлы C#
|
# Файлы C#
|
||||||
[*.cs]
|
[*.cs]
|
||||||
|
|
||||||
|
#### Resharper ####
|
||||||
|
|
||||||
|
resharper_member_can_be_private_global_highlighting = none
|
||||||
|
|
||||||
|
|
||||||
#### Основные параметры EditorConfig ####
|
#### Основные параметры EditorConfig ####
|
||||||
|
|
||||||
# Отступы и интервалы
|
# Отступы и интервалы
|
||||||
@@ -264,4 +269,5 @@ dotnet_style_namespace_match_folder = true:suggestion
|
|||||||
dotnet_code_quality_unused_parameters = all:suggestion
|
dotnet_code_quality_unused_parameters = all:suggestion
|
||||||
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||||
tab_width = 4
|
tab_width = 4
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
dotnet_diagnostic.CA1822.severity = none
|
||||||
@@ -10,6 +10,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pf2eDataScrapper", "Pf2eDat
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Элементы решения", "Элементы решения", "{754FC069-D67B-A9D7-50A1-8D1CA196D8F1}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Элементы решения", "Элементы решения", "{754FC069-D67B-A9D7-50A1-8D1CA196D8F1}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
.editorconfig = .editorconfig
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
@@ -5,21 +5,17 @@ namespace Pf2eDataScrapper.Importers;
|
|||||||
|
|
||||||
public class DatabaseHelper
|
public class DatabaseHelper
|
||||||
{
|
{
|
||||||
public Pf2eDbContext Context = new();
|
public readonly Pf2eDbContext Context = new();
|
||||||
|
|
||||||
public SlugHelper Slugger = new();
|
public readonly SlugHelper Slugger = new();
|
||||||
|
|
||||||
private int _id = 0;
|
private int _id;
|
||||||
|
|
||||||
public int NextEntityId
|
public int NextEntityId => ++_id;
|
||||||
{
|
|
||||||
get => ++_id;
|
|
||||||
set => _id = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DatabaseHelper()
|
private DatabaseHelper()
|
||||||
{
|
{
|
||||||
NextEntityId = Context.Entities.Any() ? Context.Entities.Max(e => e.Id) : 0;
|
_id = Context.Entities.Any() ? Context.Entities.Max(e => e.Id) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GenerateSlug(string name)
|
public string GenerateSlug(string name)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ internal class AonprdLoader(AonprdImporter importer)
|
|||||||
|
|
||||||
foreach (KeyValuePair<string, JToken?> kvp in indexJson)
|
foreach (KeyValuePair<string, JToken?> kvp in indexJson)
|
||||||
{
|
{
|
||||||
string file = kvp.Key.ToString();
|
string file = kvp.Key;
|
||||||
JArray items = (JArray)kvp.Value!;
|
JArray items = (JArray)kvp.Value!;
|
||||||
|
|
||||||
foreach (JToken item in items)
|
foreach (JToken item in items)
|
||||||
@@ -40,7 +40,7 @@ internal class AonprdLoader(AonprdImporter importer)
|
|||||||
|
|
||||||
public IEnumerable<LoaderEntry> Entries(string[] types)
|
public IEnumerable<LoaderEntry> Entries(string[] types)
|
||||||
{
|
{
|
||||||
foreach (string? file in Compendium.Files(types))
|
foreach (string file in Compendium.Files(types))
|
||||||
{
|
{
|
||||||
using StreamReader fileReader = new(Path.Combine(Importer.Dir, $"{file}.json"));
|
using StreamReader fileReader = new(Path.Combine(Importer.Dir, $"{file}.json"));
|
||||||
JArray array = JArray.Parse(fileReader.ReadToEnd());
|
JArray array = JArray.Parse(fileReader.ReadToEnd());
|
||||||
|
|||||||
+57
-42
@@ -1,13 +1,13 @@
|
|||||||
using Konsole;
|
using Konsole;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
||||||
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
||||||
using static Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.AbstractProcessor;
|
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||||
|
|
||||||
internal class AonprdDataBuilder(AonprdLoader loader)
|
internal class AonprdDataBuilder(AonprdLoader loader)
|
||||||
{
|
{
|
||||||
public Pf2eDatabase Database = Pf2eDatabase.Instance;
|
public readonly Pf2eDatabase Database = Pf2eDatabase.Instance;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Загрузчик данных.
|
/// Загрузчик данных.
|
||||||
@@ -19,7 +19,7 @@ internal class AonprdDataBuilder(AonprdLoader loader)
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public AonprdCompendium Compendium => Loader.Compendium;
|
public AonprdCompendium Compendium => Loader.Compendium;
|
||||||
|
|
||||||
public AonprdProcessorCollection Processors = new();
|
public readonly AonprdProcessorCollection Processors = new();
|
||||||
|
|
||||||
public void TruncateTables()
|
public void TruncateTables()
|
||||||
{
|
{
|
||||||
@@ -30,64 +30,79 @@ internal class AonprdDataBuilder(AonprdLoader loader)
|
|||||||
Console.WriteLine("Truncation completed!");
|
Console.WriteLine("Truncation completed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Build()
|
protected ConcurrentWriter Window = null!;
|
||||||
|
|
||||||
|
protected Window Output = null!;
|
||||||
|
|
||||||
|
protected ProgressBar ProcessProgressBar = null!;
|
||||||
|
|
||||||
|
protected ProgressBar SubProcessProgressBar = null!;
|
||||||
|
|
||||||
|
protected void ConfigureWindow()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Building data...");
|
Window = new Window(0, 0, Console.WindowWidth, Console.WindowHeight).Concurrent();
|
||||||
|
|
||||||
ConcurrentWriter window = new Window(
|
IConsole bars = Window.OpenBox(
|
||||||
0,
|
|
||||||
0,
|
|
||||||
Console.WindowWidth,
|
|
||||||
Console.WindowHeight
|
|
||||||
).Concurrent();
|
|
||||||
|
|
||||||
IConsole bars = window.OpenBox(
|
|
||||||
"Progress",
|
"Progress",
|
||||||
Console.WindowWidth,
|
Console.WindowWidth,
|
||||||
4,
|
4,
|
||||||
new BoxStyle { Body = Colors.WhiteOnBlack }
|
new() { Body = Colors.WhiteOnBlack }
|
||||||
);
|
);
|
||||||
|
|
||||||
Window output = new(0, 4, Console.WindowWidth, Console.WindowHeight - 4, window);
|
Output = new(0, 4, Console.WindowWidth, Console.WindowHeight - 4, Window);
|
||||||
|
|
||||||
ProgressBar bar1 = new(bars, Processors.Items.Count, 15);
|
ProcessProgressBar = new(bars, Processors.Items.Count, 15);
|
||||||
ProgressBar bar2 = new(bars, 1, 15);
|
|
||||||
int i = 0;
|
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();
|
||||||
|
|
||||||
foreach (AonprdProcessorCollection.ProcessorItem item in Processors.Iterate())
|
foreach (AonprdProcessorCollection.ProcessorItem item in Processors.Iterate())
|
||||||
{
|
{
|
||||||
bar1.Refresh(i++, $"{item.Attribute.Name}");
|
ProcessProgressBar.Next(item.Attribute.Name);
|
||||||
|
|
||||||
bar2.Max = Compendium.Count([item.Attribute.Type]);
|
if (item.Attribute.Type is null)
|
||||||
int j = 0;
|
{
|
||||||
|
RunProcessor(item, []);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SubProcessProgressBar.Max = Compendium.Count([item.Attribute.Type]);
|
||||||
|
|
||||||
foreach (AonprdLoader.LoaderEntry entry in Loader.Entries(item.Attribute.Type))
|
foreach (AonprdLoader.LoaderEntry entry in Loader.Entries(item.Attribute.Type))
|
||||||
{
|
{
|
||||||
bar2.Refresh(j++, $"{entry.Id}");
|
SubProcessProgressBar.Next($"{entry.Id}");
|
||||||
|
RunProcessor(item, entry.Json);
|
||||||
AonprdProcessorInput input = new(entry.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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bar2.Refresh(j, "Processor completed");
|
SubProcessProgressBar.Next("Ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
bar1.Refresh(i, "Done!");
|
ProcessProgressBar.Next("Done!");
|
||||||
|
|
||||||
window.Clear();
|
Window.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -1,11 +1,11 @@
|
|||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public class AonprdProcessorAttribute(string name, string type, string[] dependencies) : Attribute
|
public class AonprdProcessorAttribute(string name, string? type, string[] dependencies) : Attribute
|
||||||
{
|
{
|
||||||
public readonly string Name = name;
|
public readonly string Name = name;
|
||||||
|
|
||||||
public readonly string Type = type;
|
public readonly string? Type = type;
|
||||||
|
|
||||||
public readonly IEnumerable<string> Dependencies = dependencies;
|
public readonly IEnumerable<string> Dependencies = dependencies;
|
||||||
|
|
||||||
+5
-4
@@ -1,6 +1,7 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||||
|
|
||||||
internal class AonprdProcessorCollection
|
internal class AonprdProcessorCollection
|
||||||
{
|
{
|
||||||
@@ -41,13 +42,13 @@ internal class AonprdProcessorCollection
|
|||||||
);
|
);
|
||||||
if (collision is not null)
|
if (collision is not null)
|
||||||
{
|
{
|
||||||
throw new Exception(
|
throw new(
|
||||||
$"Multiply attributes 'AonprdProcessor' have same name '{attribute.Name}'."
|
$"Multiply attributes 'AonprdProcessor' have same name '{attribute.Name}'."
|
||||||
+ $" They are added to classes: '{type.FullName}' and '{collision.Constructor.DeclaringType!.FullName}'"
|
+ $" They are added to classes: '{type.FullName}' and '{collision.Constructor.DeclaringType!.FullName}'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Items.Add(new ProcessorItem(attribute, constructor));
|
Items.Add(new(attribute, constructor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +66,7 @@ internal class AonprdProcessorCollection
|
|||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<int> dependencyPriorities = item.Attribute.Dependencies.Select(d =>
|
IEnumerable<int> dependencyPriorities = item.Attribute.Dependencies.Select(d =>
|
||||||
priorities.TryGetValue(d, out int value) ? value : -1
|
priorities.GetValueOrDefault(d, -1)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (dependencyPriorities.Any(p => p == -1))
|
if (dependencyPriorities.Any(p => p == -1))
|
||||||
+6
-5
@@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
||||||
|
|
||||||
@@ -84,10 +85,10 @@ internal class AonprdProcessorInput(JObject input) : ProcessorInput(input)
|
|||||||
|
|
||||||
public class ActionStruct
|
public class ActionStruct
|
||||||
{
|
{
|
||||||
public int Actions = 0;
|
public int Actions;
|
||||||
public int MaxActions = 0;
|
public int MaxActions;
|
||||||
public bool IsPassive = false;
|
public bool IsPassive;
|
||||||
public bool IsReaction = false;
|
public bool IsReaction;
|
||||||
public bool IsFreeAction = false;
|
public bool IsFreeAction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
using Pf2eModel.Model.Base.Targets;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||||
|
|
||||||
|
internal class AonprdBuilderGlobals
|
||||||
|
{
|
||||||
|
public ExternalTarget AonprdTarget = null!;
|
||||||
|
|
||||||
|
private AonprdBuilderGlobals() { }
|
||||||
|
|
||||||
|
public static AonprdBuilderGlobals Instance = new AonprdBuilderGlobals();
|
||||||
|
}
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||||
|
|
||||||
public static class AonprdEnumResolver
|
public static class AonprdEnumResolver
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||||
|
|
||||||
|
internal partial class StringHelper
|
||||||
|
{
|
||||||
|
private StringHelper() { }
|
||||||
|
|
||||||
|
public string ResolveSource(string input)
|
||||||
|
{
|
||||||
|
Match match = SourceSuffixRegex().Match(input);
|
||||||
|
return match.Captures.Count > 0 ? match.Captures[0].Value : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StringHelper Instance { get; } = new();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^\[.*?\]\(.*?\)\s+(.*)$")]
|
||||||
|
private static partial Regex SourceSuffixRegex();
|
||||||
|
}
|
||||||
+223
@@ -0,0 +1,223 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
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.Aonprd.DataBuilder.Processors;
|
||||||
|
|
||||||
|
internal abstract class AbstractEntityProcessor(AonprdProcessorInput input)
|
||||||
|
: AbstractProcessor(input)
|
||||||
|
{
|
||||||
|
public Entity Entity { get; } = new();
|
||||||
|
|
||||||
|
public abstract EntityType Type { get; }
|
||||||
|
|
||||||
|
public abstract IEntity Object { get; }
|
||||||
|
|
||||||
|
public abstract void Add();
|
||||||
|
|
||||||
|
public override void Process()
|
||||||
|
{
|
||||||
|
if (Input.GetOptional<JArray>("remaster_id") is not null)
|
||||||
|
{
|
||||||
|
string id = Input.GetRequired<string>("id");
|
||||||
|
string name = Input.GetRequired<string>("name");
|
||||||
|
|
||||||
|
ProcessLegacy(id, name);
|
||||||
|
throw new LegacyItemException(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddEntity();
|
||||||
|
AddAlias();
|
||||||
|
AddSource();
|
||||||
|
AddExternal();
|
||||||
|
AddTraits();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Save()
|
||||||
|
{
|
||||||
|
Add();
|
||||||
|
Context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string AddedDescription(string path) =>
|
||||||
|
$"\r\n\r\n========== [{path}] ==========\r\n\r\n{Input.GetOptional<string>(path) ?? ""}";
|
||||||
|
|
||||||
|
protected string AddedDescription(string[] paths) =>
|
||||||
|
string.Join("", paths.Select(AddedDescription));
|
||||||
|
|
||||||
|
protected virtual string GetDescription() => Input.GetRequired<string>("markdown");
|
||||||
|
|
||||||
|
protected virtual void AddEntity()
|
||||||
|
{
|
||||||
|
Entity.Id = Helper.NextEntityId;
|
||||||
|
Entity.Type = Type;
|
||||||
|
Entity.Name[LocaleType.English] = Input.GetRequired<string>("name");
|
||||||
|
Entity.Img = "";
|
||||||
|
Entity.Description = GetDescription();
|
||||||
|
Entity.Rarity = Input.EnumOptional("rarity", EntityRarity.Common);
|
||||||
|
Entity.Slug = Helper.GenerateSlug(Entity.Name[LocaleType.English]);
|
||||||
|
Entity.IsTranslated = false;
|
||||||
|
Entity.IsChecked = false;
|
||||||
|
|
||||||
|
Object.Entity = Entity;
|
||||||
|
Object.Id = Entity.Id;
|
||||||
|
|
||||||
|
Context.Entities.Add(Entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void AddAlias()
|
||||||
|
{
|
||||||
|
JArray? legacyIdArray = Input.GetOptional<JArray>("legacy_id");
|
||||||
|
|
||||||
|
if (legacyIdArray is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string legacyId = legacyIdArray[0].ToString();
|
||||||
|
|
||||||
|
if (LegacyAliases.TryGetValue(legacyId, out string? legacyName))
|
||||||
|
{
|
||||||
|
// if (legacyName != Entity.Name[LocaleType.English])
|
||||||
|
Entity.Name[LocaleType.LegacyEnglish] = legacyName;
|
||||||
|
|
||||||
|
LegacyAliases.Remove(legacyId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RemasterWithoutLegacy.Add(legacyId, Entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void AddSource()
|
||||||
|
{
|
||||||
|
string name = Input.GetRequired<string>("source[0]");
|
||||||
|
|
||||||
|
Source? source = Context.Sources.FirstOrDefault(s => s.Name == name);
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
source = new()
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
Category = Input.EnumRequired<SourceCategory>("primary_source_category"),
|
||||||
|
ReleaseDate = DateOnly.Parse(Input.GetRequired<string>("release_date")),
|
||||||
|
};
|
||||||
|
|
||||||
|
Context.Sources.Add(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntitySource entitySource = new()
|
||||||
|
{
|
||||||
|
Entity = Entity,
|
||||||
|
Source = source,
|
||||||
|
Suffix = StringHelper.ResolveSource(Input.GetRequired<string>("source_markdown")),
|
||||||
|
IsRemaster = Input.GetOptional<JArray>("legacy_id") is not null,
|
||||||
|
};
|
||||||
|
|
||||||
|
Context.EntitySources.Add(entitySource);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void AddExternal()
|
||||||
|
{
|
||||||
|
EntityExternal external = new()
|
||||||
|
{
|
||||||
|
Entity = Entity,
|
||||||
|
Target = Globals.AonprdTarget,
|
||||||
|
Suffix = Input.GetRequired<string>("url"),
|
||||||
|
Md5 = Md5(Input.Input.ToString()),
|
||||||
|
};
|
||||||
|
|
||||||
|
Context.EntityExternals.Add(external);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void AddTraits()
|
||||||
|
{
|
||||||
|
JToken? traitsJson = Input.Input.SelectToken("trait");
|
||||||
|
|
||||||
|
if (traitsJson?.Type != JTokenType.Array)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<string> names = traitsJson.ToArray().Select(jToken => jToken.ToString());
|
||||||
|
List<Entity> traitEntities = Context
|
||||||
|
.Traits.Select(t => t.Entity)
|
||||||
|
// ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall
|
||||||
|
.Where(e => Pf2eDbContext.LocaleSearchArray(e.Name, names))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
List<Trait> traits = Context
|
||||||
|
.Traits.Include(t => t.Entity)
|
||||||
|
.Where(t => traitEntities.Contains(t.Entity))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (string name in names)
|
||||||
|
{
|
||||||
|
if (!traits.Any(t => t.Entity.Name.Contains(name)))
|
||||||
|
{
|
||||||
|
throw new Exception($"Trait '{name}' is not found!!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Trait trait in traits)
|
||||||
|
{
|
||||||
|
Entity.Traits.Add(trait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ProcessLegacy(string id, string name)
|
||||||
|
{
|
||||||
|
if (RemasterWithoutLegacy.TryGetValue(id, out Entity? remastered))
|
||||||
|
{
|
||||||
|
// if (remastered.ToString() != name)
|
||||||
|
remastered.Name[LocaleType.LegacyEnglish] = name;
|
||||||
|
|
||||||
|
RemasterWithoutLegacy.Remove(id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LegacyAliases.Add(id, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GenerateExtra(params string[] args)
|
||||||
|
{
|
||||||
|
Dictionary<string, object?> data = [];
|
||||||
|
|
||||||
|
foreach (string key in args)
|
||||||
|
{
|
||||||
|
data.Add(key, Input.Input.SelectToken(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return JsonConvert.SerializeObject(data, new JsonSerializerSettings());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Md5(string input, bool isLowercase = false)
|
||||||
|
{
|
||||||
|
using MD5 md5 = MD5.Create();
|
||||||
|
byte[] byteHash = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
|
||||||
|
string hash = BitConverter.ToString(byteHash).Replace("-", "");
|
||||||
|
return isLowercase ? hash.ToLower() : hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static readonly Dictionary<string, string> LegacyAliases = [];
|
||||||
|
|
||||||
|
protected static readonly Dictionary<string, Entity> RemasterWithoutLegacy = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LegacyItemException(string name)
|
||||||
|
: Exception($"Item '{name}' is linked with newer version, skipping.") { }
|
||||||
|
|
||||||
|
public class SkipItemException(string name, string reason)
|
||||||
|
: Exception($"Item '{name}' is skipped, reason: {reason}.") { }
|
||||||
+9
-236
@@ -1,248 +1,21 @@
|
|||||||
using System.Security.Cryptography;
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Pf2eModel;
|
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.Aonprd.DataBuilder.Processors;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
||||||
|
|
||||||
internal abstract partial class AbstractProcessor(AonprdProcessorInput input)
|
internal abstract class AbstractProcessor(AonprdProcessorInput input)
|
||||||
{
|
{
|
||||||
protected DatabaseHelper Helper = DatabaseHelper.Instance;
|
protected readonly DatabaseHelper Helper = DatabaseHelper.Instance;
|
||||||
|
|
||||||
|
protected readonly StringHelper StringHelper = StringHelper.Instance;
|
||||||
|
|
||||||
|
protected readonly AonprdBuilderGlobals Globals = AonprdBuilderGlobals.Instance;
|
||||||
|
|
||||||
public readonly Pf2eDbContext Context = DatabaseHelper.DbContext;
|
public readonly Pf2eDbContext Context = DatabaseHelper.DbContext;
|
||||||
|
|
||||||
public readonly AonprdProcessorInput Input = input;
|
public readonly AonprdProcessorInput Input = input;
|
||||||
|
|
||||||
public Entity Entity { get; set; } = new();
|
public abstract void Process();
|
||||||
|
|
||||||
public abstract EntityType Type { get; }
|
public abstract void Save();
|
||||||
|
|
||||||
public abstract IEntity Object { get; }
|
|
||||||
|
|
||||||
protected abstract void Add();
|
|
||||||
|
|
||||||
public virtual void Process()
|
|
||||||
{
|
|
||||||
if (Input.GetOptional<JArray>("remaster_id") is not null)
|
|
||||||
{
|
|
||||||
string id = Input.GetRequired<string>("id");
|
|
||||||
string name = Input.GetRequired<string>("name");
|
|
||||||
|
|
||||||
ProcessLegacy(id, name);
|
|
||||||
throw new LegacyItemException(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddEntity();
|
|
||||||
AddAlias();
|
|
||||||
AddSource();
|
|
||||||
AddExternal();
|
|
||||||
AddTraits();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Save()
|
|
||||||
{
|
|
||||||
Add();
|
|
||||||
Context.SaveChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected string AddedDescription(string path) =>
|
|
||||||
$"\r\n\r\n========== [{path}] ==========\r\n\r\n{Input.GetOptional<string>(path) ?? ""}";
|
|
||||||
|
|
||||||
protected string AddedDescription(string[] paths) =>
|
|
||||||
string.Join("", paths.Select(AddedDescription));
|
|
||||||
|
|
||||||
protected virtual string GetDescription() => Input.GetRequired<string>("markdown");
|
|
||||||
|
|
||||||
protected virtual void AddEntity()
|
|
||||||
{
|
|
||||||
Entity.Id = Helper.NextEntityId;
|
|
||||||
Entity.Type = Type;
|
|
||||||
Entity.Name[LocaleType.English] = Input.GetRequired<string>("name");
|
|
||||||
Entity.Img = "";
|
|
||||||
Entity.Description = GetDescription();
|
|
||||||
Entity.Rarity = Input.EnumOptional<EntityRarity>("rarity", EntityRarity.Common);
|
|
||||||
Entity.Slug = Helper.GenerateSlug(Entity.Name[LocaleType.English]);
|
|
||||||
Entity.IsTranslated = false;
|
|
||||||
Entity.IsChecked = false;
|
|
||||||
|
|
||||||
Object.Entity = Entity;
|
|
||||||
Object.Id = Entity.Id;
|
|
||||||
|
|
||||||
Context.Entities.Add(Entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void AddAlias()
|
|
||||||
{
|
|
||||||
JArray? legacyIdArray = Input.GetOptional<JArray>("legacy_id");
|
|
||||||
|
|
||||||
if (legacyIdArray is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string legacyId = legacyIdArray[0].ToString();
|
|
||||||
|
|
||||||
if (LegacyAliases.TryGetValue(legacyId, out string? legacyName))
|
|
||||||
{
|
|
||||||
// if (legacyName != Entity.Name[LocaleType.English])
|
|
||||||
Entity.Name[LocaleType.LegacyEnglish] = legacyName;
|
|
||||||
|
|
||||||
LegacyAliases.Remove(legacyId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RemasterWithoutLegacy.Add(legacyId, Entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void AddSource()
|
|
||||||
{
|
|
||||||
string name = Input.GetRequired<string>("source[0]");
|
|
||||||
|
|
||||||
Source? source = Context.Sources.FirstOrDefault(s => s.Name == name);
|
|
||||||
|
|
||||||
if (source == null)
|
|
||||||
{
|
|
||||||
source = new()
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
Category = Input.EnumRequired<SourceCategory>("primary_source_category"),
|
|
||||||
ReleaseDate = DateOnly.Parse(Input.GetRequired<string>("release_date")),
|
|
||||||
};
|
|
||||||
|
|
||||||
Context.Sources.Add(source);
|
|
||||||
}
|
|
||||||
string sourceMarkdown = Input.GetRequired<string>("source_markdown");
|
|
||||||
Match match = SourceSuffixRegex().Match(sourceMarkdown);
|
|
||||||
|
|
||||||
EntitySource entitySource = new()
|
|
||||||
{
|
|
||||||
Entity = Entity,
|
|
||||||
Source = source,
|
|
||||||
Suffix = ((match?.Captures.Count > 0) ? match?.Captures[0]?.Value : "") ?? "",
|
|
||||||
IsRemaster = Input.GetOptional<JArray>("legacy_id") is not null,
|
|
||||||
};
|
|
||||||
|
|
||||||
Context.EntitySources.Add(entitySource);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void AddExternal()
|
|
||||||
{
|
|
||||||
if (AonprdTarget is null)
|
|
||||||
{
|
|
||||||
AonprdTarget = Context.ExternalTargets.FirstOrDefault(t =>
|
|
||||||
t.Name == AonprdImporter.SourceName
|
|
||||||
);
|
|
||||||
|
|
||||||
AonprdTarget ??= new()
|
|
||||||
{
|
|
||||||
Name = AonprdImporter.SourceName,
|
|
||||||
Icon = "http://www.google.com/s2/favicons?domain=2e.aonprd.com",
|
|
||||||
Prefix = "https://2e.aonprd.com",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityExternal external = new()
|
|
||||||
{
|
|
||||||
Entity = Entity,
|
|
||||||
Target = AonprdTarget,
|
|
||||||
Suffix = Input.GetRequired<string>("url"),
|
|
||||||
Md5 = Md5(Input.Input.ToString()),
|
|
||||||
};
|
|
||||||
Context.EntityExternals.Add(external);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void AddTraits()
|
|
||||||
{
|
|
||||||
JToken? traitsJson = Input.Input.SelectToken("trait");
|
|
||||||
|
|
||||||
if (traitsJson?.Type != JTokenType.Array)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerable<string> names = traitsJson.ToArray().Select(jToken => jToken.ToString());
|
|
||||||
List<Entity> traitEntities = Context
|
|
||||||
.Traits.Select(t => t.Entity)
|
|
||||||
.Where(e => Pf2eDbContext.LocaleSearchArray(e.Name, names))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
List<Trait> traits = Context
|
|
||||||
.Traits.Include(t => t.Entity)
|
|
||||||
.Where(t => traitEntities.Contains(t.Entity))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
foreach (string name in names)
|
|
||||||
{
|
|
||||||
if (!traits.Any(t => t.Entity.Name.Contains(name)))
|
|
||||||
{
|
|
||||||
throw new Exception($"Trait '{name}' is not found!!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Trait trait in traits)
|
|
||||||
{
|
|
||||||
Entity.Traits.Add(trait);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void ProcessLegacy(string id, string name)
|
|
||||||
{
|
|
||||||
if (RemasterWithoutLegacy.TryGetValue(id, out Entity? remastered))
|
|
||||||
{
|
|
||||||
// if (remastered.ToString() != name)
|
|
||||||
remastered.Name[LocaleType.LegacyEnglish] = name;
|
|
||||||
|
|
||||||
RemasterWithoutLegacy.Remove(id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LegacyAliases.Add(id, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GenerateExtra(params string[] args)
|
|
||||||
{
|
|
||||||
Dictionary<string, object?> data = [];
|
|
||||||
|
|
||||||
foreach (string key in args)
|
|
||||||
{
|
|
||||||
data.Add(key, Input.Input.SelectToken(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
return JsonConvert.SerializeObject(data, new JsonSerializerSettings() { });
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Md5(string input, bool isLowercase = false)
|
|
||||||
{
|
|
||||||
using MD5 md5 = MD5.Create();
|
|
||||||
byte[] byteHash = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
|
|
||||||
string hash = BitConverter.ToString(byteHash).Replace("-", "");
|
|
||||||
return isLowercase ? hash.ToLower() : hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static ExternalTarget? AonprdTarget = null;
|
|
||||||
|
|
||||||
protected static Dictionary<string, string> LegacyAliases = [];
|
|
||||||
|
|
||||||
protected static Dictionary<string, Entity> RemasterWithoutLegacy = [];
|
|
||||||
|
|
||||||
[GeneratedRegex(@"^\[.*?\]\(.*?\)\s+(.*)$")]
|
|
||||||
private static partial Regex SourceSuffixRegex();
|
|
||||||
|
|
||||||
public class LegacyItemException(string name)
|
|
||||||
: Exception($"Item '{name}' is linked with newer version, skipping.") { }
|
|
||||||
|
|
||||||
public class SkipItemException(string name, string reason)
|
|
||||||
: Exception($"Item '{name}' is skipped, reason: {reason}.") { }
|
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-48
@@ -1,10 +1,4 @@
|
|||||||
using System;
|
using Pf2eModel;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Pf2eModel;
|
|
||||||
using Pf2eModel.Model;
|
|
||||||
using Pf2eModel.Model.Base;
|
using Pf2eModel.Model.Base;
|
||||||
using Pf2eModel.Model.Common.I18n;
|
using Pf2eModel.Model.Common.I18n;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
@@ -13,7 +7,7 @@ using Pf2eModel.Model.Structure;
|
|||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
|
||||||
|
|
||||||
internal abstract class AbstractSubclassProcessor(AonprdProcessorInput input)
|
internal abstract class AbstractSubclassProcessor(AonprdProcessorInput input)
|
||||||
: AbstractProcessor(input)
|
: AbstractEntityProcessor(input)
|
||||||
{
|
{
|
||||||
public override EntityType Type => EntityType.Subclass;
|
public override EntityType Type => EntityType.Subclass;
|
||||||
|
|
||||||
@@ -23,7 +17,7 @@ internal abstract class AbstractSubclassProcessor(AonprdProcessorInput input)
|
|||||||
|
|
||||||
public abstract string GroupName { get; }
|
public abstract string GroupName { get; }
|
||||||
|
|
||||||
protected override void Add() => Context.Subclasses.Add(Object);
|
public override void Add() => Context.Subclasses.Add(Object);
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
@@ -37,51 +31,40 @@ internal abstract class AbstractSubclassProcessor(AonprdProcessorInput input)
|
|||||||
public SubclassGroup GetGroup()
|
public SubclassGroup GetGroup()
|
||||||
{
|
{
|
||||||
SubclassGroup? group = Context.SubclassGroups.FirstOrDefault(g =>
|
SubclassGroup? group = Context.SubclassGroups.FirstOrDefault(g =>
|
||||||
|
// ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall
|
||||||
Pf2eDbContext.LocaleSearch(g.Entity.Name, GroupName)
|
Pf2eDbContext.LocaleSearch(g.Entity.Name, GroupName)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (group is null)
|
if (group is not null)
|
||||||
{
|
{
|
||||||
Class? cl =
|
return group;
|
||||||
(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,
|
|
||||||
};
|
|
||||||
|
|
||||||
groupEntity.Name[LocaleType.English] = GroupName;
|
|
||||||
groupEntity.Slug = Helper.GenerateSlug(GroupName);
|
|
||||||
Context.Entities.Add(groupEntity);
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Entity.Id = Helper.NextEntityId;
|
|
||||||
Entity.Type = Type;
|
|
||||||
Entity.Name[LocaleType.English] = Input.GetRequired<string>("name");
|
|
||||||
Entity.Img = "";
|
|
||||||
Entity.Description = GetDescription();
|
|
||||||
Entity.Rarity = Input.EnumOptional<EntityRarity>("rarity", EntityRarity.Common);
|
|
||||||
Entity.Slug = Helper.GenerateSlug(Entity.Name[LocaleType.English]);
|
|
||||||
Entity.IsTranslated = false;
|
|
||||||
Entity.IsChecked = false;
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
group = new SubclassGroup() { Entity = groupEntity, Class = cl };
|
|
||||||
Context.SubclassGroups.Add(group);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Class? cl = ClassName is not null
|
||||||
|
? Context.Classes.FirstOrDefault(c =>
|
||||||
|
// ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall
|
||||||
|
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;
|
return group;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
using Pf2eModel.Model.Base.Targets;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common;
|
||||||
|
|
||||||
|
[AonprdProcessor("external", null, [])]
|
||||||
|
internal class ExternalProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
||||||
|
{
|
||||||
|
public ExternalTarget AonprdTarget = null!;
|
||||||
|
|
||||||
|
public override void Process()
|
||||||
|
{
|
||||||
|
AonprdTarget = new()
|
||||||
|
{
|
||||||
|
Name = AonprdImporter.SourceName,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-13
@@ -1,29 +1,25 @@
|
|||||||
using Pf2eModel.Model;
|
using Pf2eModel.Model.Base.Source;
|
||||||
using Pf2eModel.Model.Base.Source;
|
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common;
|
||||||
|
|
||||||
[AonprdProcessor("source", new string[] { })]
|
[AonprdProcessor("source", [])]
|
||||||
internal class SourceProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
internal class SourceProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
||||||
{
|
{
|
||||||
public override EntityType Type => EntityType.Unknown;
|
protected Source Source = null!;
|
||||||
|
|
||||||
public override IEntity? Object => null;
|
|
||||||
|
|
||||||
protected override void Add() { }
|
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
// base.Process();
|
Source = new()
|
||||||
|
|
||||||
Source source = new()
|
|
||||||
{
|
{
|
||||||
Name = Input.GetRequired<string>("name"),
|
Name = Input.GetRequired<string>("name"),
|
||||||
Category = Input.EnumRequired<SourceCategory>("primary_source_category"),
|
Category = Input.EnumRequired<SourceCategory>("primary_source_category"),
|
||||||
ReleaseDate = DateOnly.Parse(Input.GetRequired<string>("release_date")),
|
ReleaseDate = DateOnly.Parse(Input.GetRequired<string>("release_date")),
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Context.Sources.Add(source);
|
public override void Save()
|
||||||
|
{
|
||||||
|
Context.Sources.Add(Source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
using Pf2eModel.Model.Common;
|
||||||
|
using Pf2eModel.Model.Enum;
|
||||||
|
|
||||||
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Common;
|
||||||
|
|
||||||
|
[AonprdProcessor("skill", [])]
|
||||||
|
internal class TrainingProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
||||||
|
{
|
||||||
|
public Training Training = null!;
|
||||||
|
|
||||||
|
public override void Process()
|
||||||
|
{
|
||||||
|
Training = new() { Name = Input.GetRequired<string>("name"), Type = TrainingType.Skill };
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Save()
|
||||||
|
{
|
||||||
|
Context.Trainings.Add(Training);
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-7
@@ -1,9 +1,4 @@
|
|||||||
using System;
|
using Pf2eModel.Model.Structure;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Pf2eModel.Model.Structure;
|
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Subclasses;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Subclasses;
|
||||||
|
|
||||||
@@ -12,7 +7,7 @@ internal class ApparitionProcessor(AonprdProcessorInput input) : AbstractSubclas
|
|||||||
{
|
{
|
||||||
public override Subclass Object { get; } = new();
|
public override Subclass Object { get; } = new();
|
||||||
|
|
||||||
public override string? ClassName => "Animist";
|
public override string ClassName => "Animist";
|
||||||
|
|
||||||
public override string GroupName => "Apparition";
|
public override string GroupName => "Apparition";
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -3,13 +3,13 @@
|
|||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||||
|
|
||||||
[AonprdProcessor("action")]
|
[AonprdProcessor("action")]
|
||||||
internal class ActionProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
internal class ActionProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||||
{
|
{
|
||||||
public override EntityType Type => EntityType.Action;
|
public override EntityType Type => EntityType.Action;
|
||||||
|
|
||||||
public override Pf2eModel.Model.Structure.Action Object { get; } = new();
|
public override Pf2eModel.Model.Structure.Action Object { get; } = new();
|
||||||
|
|
||||||
protected override void Add() => Context.Actions.Add(Object);
|
public override void Add() => Context.Actions.Add(Object);
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
@@ -24,7 +24,7 @@ internal class ActionProcessor(AonprdProcessorInput input) : AbstractProcessor(i
|
|||||||
Object.IsFreeAction = action.IsFreeAction;
|
Object.IsFreeAction = action.IsFreeAction;
|
||||||
Object.IsPassive = action.IsPassive;
|
Object.IsPassive = action.IsPassive;
|
||||||
Object.IsReaction = action.IsReaction;
|
Object.IsReaction = action.IsReaction;
|
||||||
;
|
|
||||||
Object.Extra = GenerateExtra("school");
|
Object.Extra = GenerateExtra("school");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-14
@@ -1,19 +1,17 @@
|
|||||||
using LinqToDB;
|
using Newtonsoft.Json.Linq;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
using Pf2eModel.Model.Structure;
|
using Pf2eModel.Model.Structure;
|
||||||
using Pf2eModel.Model.Structure.AncestryRelation;
|
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||||
|
|
||||||
[AonprdProcessor("ancestry", ["trait", "language"])]
|
[AonprdProcessor("ancestry", ["trait", "language"])]
|
||||||
internal class AncestryProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
internal class AncestryProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||||
{
|
{
|
||||||
public override EntityType Type => EntityType.Ancestry;
|
public override EntityType Type => EntityType.Ancestry;
|
||||||
|
|
||||||
public override Ancestry Object { get; } = new();
|
public override Ancestry Object { get; } = new();
|
||||||
|
|
||||||
protected override void Add() => Context.Ancestries.Add(Object);
|
public override void Add() => Context.Ancestries.Add(Object);
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
@@ -36,7 +34,7 @@ internal class AncestryProcessor(AonprdProcessorInput input) : AbstractProcessor
|
|||||||
|
|
||||||
Object.Speed = Convert.ToInt32(Input.GetOptional<int>("speed.land"));
|
Object.Speed = Convert.ToInt32(Input.GetOptional<int>("speed.land"));
|
||||||
|
|
||||||
Object.Vision = Input.EnumOptional<AncestryVision>("vision", AncestryVision.Normal);
|
Object.Vision = Input.EnumOptional("vision", AncestryVision.Normal);
|
||||||
|
|
||||||
AddBoosts("attribute", true);
|
AddBoosts("attribute", true);
|
||||||
AddBoosts("attribute_flaw", false);
|
AddBoosts("attribute_flaw", false);
|
||||||
@@ -59,14 +57,14 @@ internal class AncestryProcessor(AonprdProcessorInput input) : AbstractProcessor
|
|||||||
|
|
||||||
foreach (string boost in boosts)
|
foreach (string boost in boosts)
|
||||||
{
|
{
|
||||||
AncestryBoost ancestryBoost = new()
|
Context.AncestryBoosts.Add(
|
||||||
{
|
new()
|
||||||
Ancestry = Object,
|
{
|
||||||
Boost = isBoost,
|
Ancestry = Object,
|
||||||
Value = Input.Enum<AttributeValues>(boost),
|
Boost = isBoost,
|
||||||
};
|
Value = Input.Enum<AttributeValues>(boost),
|
||||||
|
}
|
||||||
Context.AncestryBoosts.Add(ancestryBoost);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -4,13 +4,13 @@ using Pf2eModel.Model.Structure;
|
|||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||||
|
|
||||||
[AonprdProcessor("archetype")]
|
[AonprdProcessor("archetype")]
|
||||||
internal class ArchetypeProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
internal class ArchetypeProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||||
{
|
{
|
||||||
public override EntityType Type => EntityType.Archetype;
|
public override EntityType Type => EntityType.Archetype;
|
||||||
|
|
||||||
public override Archetype Object { get; } = new();
|
public override Archetype Object { get; } = new();
|
||||||
|
|
||||||
protected override void Add() => Context.Archetypes.Add(Object);
|
public override void Add() => Context.Archetypes.Add(Object);
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-2
@@ -6,13 +6,13 @@ using Pf2eModel.Model.Structure.BackgroundRelation;
|
|||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||||
|
|
||||||
[AonprdProcessor("background")]
|
[AonprdProcessor("background")]
|
||||||
internal class BackgroundProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
internal class BackgroundProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||||
{
|
{
|
||||||
public override EntityType Type => EntityType.Background;
|
public override EntityType Type => EntityType.Background;
|
||||||
|
|
||||||
public override Background Object { get; } = new();
|
public override Background Object { get; } = new();
|
||||||
|
|
||||||
protected override void Add() => Context.Backgrounds.Add(Object);
|
public override void Add() => Context.Backgrounds.Add(Object);
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-5
@@ -1,6 +1,4 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using LinqToDB;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Pf2eModel.Model.Common;
|
using Pf2eModel.Model.Common;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
@@ -10,13 +8,13 @@ using Pf2eModel.Model.Structure.ClassRelation;
|
|||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||||
|
|
||||||
[AonprdProcessor("class", ["trait", "source", "skill"])]
|
[AonprdProcessor("class", ["trait", "source", "skill"])]
|
||||||
internal class ClassProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
internal class ClassProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||||
{
|
{
|
||||||
public override EntityType Type => EntityType.Class;
|
public override EntityType Type => EntityType.Class;
|
||||||
|
|
||||||
public override Class Object { get; } = new();
|
public override Class Object { get; } = new();
|
||||||
|
|
||||||
protected override void Add() => Context.Classes.Add(Object);
|
public override void Add() => Context.Classes.Add(Object);
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
@@ -156,7 +154,6 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractProcessor(in
|
|||||||
.Where(s => s != "")
|
.Where(s => s != "")
|
||||||
.Select(s => string.Concat(s[0].ToString().ToUpper(), s.AsSpan(1)))
|
.Select(s => string.Concat(s[0].ToString().ToUpper(), s.AsSpan(1)))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ICollection<ClassTraining> GetSaveTrainings()
|
protected ICollection<ClassTraining> GetSaveTrainings()
|
||||||
|
|||||||
+4
-3
@@ -6,13 +6,13 @@ using Pf2eModel.Model.Structure;
|
|||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||||
|
|
||||||
// [AonprdProcessor("feat", ["trait", "source", "archetype"])]
|
// [AonprdProcessor("feat", ["trait", "source", "archetype"])]
|
||||||
internal class FeatProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
internal class FeatProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||||
{
|
{
|
||||||
public override EntityType Type => EntityType.Feat;
|
public override EntityType Type => EntityType.Feat;
|
||||||
|
|
||||||
public override Feat Object { get; } = new();
|
public override Feat Object { get; } = new();
|
||||||
|
|
||||||
protected override void Add() => Context.Feats.Add(Object);
|
public override void Add() => Context.Feats.Add(Object);
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
@@ -47,6 +47,7 @@ internal class FeatProcessor(AonprdProcessorInput input) : AbstractProcessor(inp
|
|||||||
Input.GetOptional<JArray>("archetype")?.Select(t => t.ToString()).ToArray() ?? [];
|
Input.GetOptional<JArray>("archetype")?.Select(t => t.ToString()).ToArray() ?? [];
|
||||||
|
|
||||||
Archetype[] archetypes = Context
|
Archetype[] archetypes = Context
|
||||||
|
// ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall
|
||||||
.Archetypes.Where(a => Pf2eDbContext.LocaleSearchArray(a.Entity.Name, archetypeStrings))
|
.Archetypes.Where(a => Pf2eDbContext.LocaleSearchArray(a.Entity.Name, archetypeStrings))
|
||||||
// .Where(a => archetypeStrings.Contains(a.Entity.Name.ToString()))
|
// .Where(a => archetypeStrings.Contains(a.Entity.Name.ToString()))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@@ -56,7 +57,7 @@ internal class FeatProcessor(AonprdProcessorInput input) : AbstractProcessor(inp
|
|||||||
Object.Category = ActionCategory.Archetype;
|
Object.Category = ActionCategory.Archetype;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Archetype? archetype in archetypes)
|
foreach (Archetype archetype in archetypes)
|
||||||
{
|
{
|
||||||
Object.Archetypes.Add(archetype);
|
Object.Archetypes.Add(archetype);
|
||||||
|
|
||||||
|
|||||||
+2
-7
@@ -4,16 +4,11 @@ using Pf2eModel.Model.Structure;
|
|||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||||
|
|
||||||
[AonprdProcessor("language")]
|
[AonprdProcessor("language")]
|
||||||
internal class LanguageProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
internal class LanguageProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||||
{
|
{
|
||||||
public override EntityType Type => EntityType.Language;
|
public override EntityType Type => EntityType.Language;
|
||||||
|
|
||||||
public override Language Object { get; } = new();
|
public override Language Object { get; } = new();
|
||||||
|
|
||||||
protected override void Add() => Context.Languages.Add(Object);
|
public override void Add() => Context.Languages.Add(Object);
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
base.Process();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
-28
@@ -1,28 +0,0 @@
|
|||||||
using Pf2eModel.Model;
|
|
||||||
using Pf2eModel.Model.Common;
|
|
||||||
using Pf2eModel.Model.Enum;
|
|
||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
|
||||||
|
|
||||||
[AonprdProcessor("skill", new string[] { })]
|
|
||||||
internal class TrainingProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
|
||||||
{
|
|
||||||
public override EntityType Type => EntityType.Unknown;
|
|
||||||
|
|
||||||
public override IEntity? Object => null;
|
|
||||||
|
|
||||||
protected override void Add() { }
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
// base.Process();
|
|
||||||
|
|
||||||
Training training = new()
|
|
||||||
{
|
|
||||||
Name = Input.GetRequired<string>("name"),
|
|
||||||
Type = TrainingType.Skill,
|
|
||||||
};
|
|
||||||
|
|
||||||
Context.Trainings.Add(training);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+3
-3
@@ -3,14 +3,14 @@ using Pf2eModel.Model.Structure;
|
|||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
|
||||||
|
|
||||||
[AonprdProcessor("trait", new string[] { })]
|
[AonprdProcessor("trait", ["external"])]
|
||||||
internal class TraitProcessor(AonprdProcessorInput input) : AbstractProcessor(input)
|
internal class TraitProcessor(AonprdProcessorInput input) : AbstractEntityProcessor(input)
|
||||||
{
|
{
|
||||||
public override EntityType Type => EntityType.Trait;
|
public override EntityType Type => EntityType.Trait;
|
||||||
|
|
||||||
public override Trait Object { get; } = new();
|
public override Trait Object { get; } = new();
|
||||||
|
|
||||||
protected override void Add() => Context.Traits.Add(Object);
|
public override void Add() => Context.Traits.Add(Object);
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ internal class CompendiumFolder
|
|||||||
if (json.TryGetValue("_id", out JToken? id))
|
if (json.TryGetValue("_id", out JToken? id))
|
||||||
{
|
{
|
||||||
// Вложенная папка через _folders.json
|
// Вложенная папка через _folders.json
|
||||||
Id = id!.ToString();
|
Id = id.ToString();
|
||||||
Name = json["name"]!.ToString();
|
Name = json["name"]!.ToString();
|
||||||
Path = null;
|
Path = null;
|
||||||
IsContained = true;
|
IsContained = true;
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ internal class CompendiumLoader(Pf2EFoundryImporter importer)
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Счётчик папок
|
/// Счётчик папок
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int _folderCount = 0;
|
private int _folderCount;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Общее количество элементов в компендиуме
|
/// Общее количество элементов в компендиуме
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int ItemCount { get; protected set; } = 0;
|
public int ItemCount { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обработка папок компендиума в поле `packFolders`.
|
/// Обработка папок компендиума в поле `packFolders`.
|
||||||
@@ -48,7 +48,7 @@ internal class CompendiumLoader(Pf2EFoundryImporter importer)
|
|||||||
|
|
||||||
if (obj.TryGetValue("packs", out JToken? packs))
|
if (obj.TryGetValue("packs", out JToken? packs))
|
||||||
{
|
{
|
||||||
foreach (JToken jToken in packs!)
|
foreach (JToken jToken in packs)
|
||||||
{
|
{
|
||||||
string packId = jToken.ToString();
|
string packId = jToken.ToString();
|
||||||
CompendiumFolder? child = Collection.GetById(packId);
|
CompendiumFolder? child = Collection.GetById(packId);
|
||||||
@@ -62,7 +62,7 @@ internal class CompendiumLoader(Pf2EFoundryImporter importer)
|
|||||||
|
|
||||||
if (obj.TryGetValue("folders", out JToken? innerFolders))
|
if (obj.TryGetValue("folders", out JToken? innerFolders))
|
||||||
{
|
{
|
||||||
ProcessPackFolders((JArray)innerFolders!, folder);
|
ProcessPackFolders((JArray)innerFolders, folder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ internal class CompendiumLoader(Pf2EFoundryImporter importer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Поиск _folders.json
|
// Поиск _folders.json
|
||||||
foreach (CompendiumFolder? parent in Collection.ToList())
|
foreach (CompendiumFolder parent in Collection.ToList())
|
||||||
{
|
{
|
||||||
if (parent.Path is null)
|
if (parent.Path is null)
|
||||||
{
|
{
|
||||||
|
|||||||
+8
-7
@@ -1,5 +1,6 @@
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Pf2eModel;
|
using Pf2eModel;
|
||||||
using Pf2eModel.Model;
|
using Pf2eModel.Model;
|
||||||
@@ -39,10 +40,7 @@ internal abstract class AbstractProcessor(ProcessorInput input)
|
|||||||
Entity.IsChecked = false;
|
Entity.IsChecked = false;
|
||||||
|
|
||||||
Entity.Slug = Helper.GenerateSlug(Entity.Name[LocaleType.English]);
|
Entity.Slug = Helper.GenerateSlug(Entity.Name[LocaleType.English]);
|
||||||
Entity.Rarity = Input.EnumOptional<EntityRarity>(
|
Entity.Rarity = Input.EnumOptional("system.traits.rarity", EntityRarity.Common);
|
||||||
"system.traits.rarity",
|
|
||||||
EntityRarity.Common
|
|
||||||
);
|
|
||||||
|
|
||||||
Object.Id = Entity.Id;
|
Object.Id = Entity.Id;
|
||||||
|
|
||||||
@@ -140,16 +138,19 @@ internal abstract class AbstractProcessor(ProcessorInput input)
|
|||||||
protected IEnumerable<Trait> GetTraits(IEnumerable<string> names)
|
protected IEnumerable<Trait> GetTraits(IEnumerable<string> names)
|
||||||
{
|
{
|
||||||
List<Trait> result = Context
|
List<Trait> result = Context
|
||||||
.Traits.Where(t => names.Contains(t.Entity.ToString()))
|
.Traits.Include(t => t.Entity)
|
||||||
|
.ThenInclude(e => e.Name)
|
||||||
|
// ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall
|
||||||
|
.Where(t => Pf2eDbContext.LocaleSearchArray(t.Entity.Name, names))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
/*
|
||||||
foreach (string name in names)
|
foreach (string name in names)
|
||||||
{
|
{
|
||||||
if (result.Any(t => t.Entity.Name.Contains(name)))
|
if (result.Any(t => t.Entity.Name.Contains(name)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Trait trait = new()
|
Trait trait = new()
|
||||||
{
|
{
|
||||||
Name = name,
|
Name = name,
|
||||||
@@ -159,8 +160,8 @@ internal abstract class AbstractProcessor(ProcessorInput input)
|
|||||||
};
|
};
|
||||||
Context.Traits.Add(trait);
|
Context.Traits.Add(trait);
|
||||||
result.Add(trait);
|
result.Add(trait);
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ internal class ConditionProcessor(ProcessorInput input) : AbstractProcessor(inpu
|
|||||||
};
|
};
|
||||||
|
|
||||||
Object.Extra = extra.ToString(Newtonsoft.Json.Formatting.None);
|
Object.Extra = extra.ToString(Newtonsoft.Json.Formatting.None);
|
||||||
Object.Group = Input.EnumOptional<ConditionGroup>("system.group", ConditionGroup.Unknown);
|
Object.Group = Input.EnumOptional("system.group", ConditionGroup.Unknown);
|
||||||
|
|
||||||
Context.Conditions.Add(Object);
|
Context.Conditions.Add(Object);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
namespace Pf2eDataScrapper.Importers.Repositories;
|
namespace Pf2eDataScrapper.Importers.Repositories;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Загрузчик данных из git-репозиториев
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="repositoryDirPath"></param>
|
|
||||||
internal class GitRepository(AbstractImporter importer, string url)
|
internal class GitRepository(AbstractImporter importer, string url)
|
||||||
: AbstractImporterRepository(importer)
|
: AbstractImporterRepository(importer)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ internal class SchemaNode
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Отображаемое имя элемента.
|
/// Отображаемое имя элемента.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name = "";
|
public readonly string Name = "";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Путь к элементу.
|
/// Путь к элементу.
|
||||||
@@ -21,12 +21,12 @@ internal class SchemaNode
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Родительский элемент.
|
/// Родительский элемент.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SchemaNode? Parent = null;
|
public readonly SchemaNode? Parent;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Указание, является ли элемент корневым.
|
/// Указание, является ли элемент корневым.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Root = false;
|
public readonly bool Root;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Корневой элемент схемы данных.
|
/// Корневой элемент схемы данных.
|
||||||
@@ -36,12 +36,12 @@ internal class SchemaNode
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Типы данных, использующиеся в элементе.
|
/// Типы данных, использующиеся в элементе.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<AbstractSchemaType> Types = [];
|
public readonly List<AbstractSchemaType> Types = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Указание, может ли этот элемент отсутсвовать в структуре данных.
|
/// Указание, может ли этот элемент отсутсвовать в структуре данных.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsNullable = false;
|
public bool IsNullable;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Объект для определения типа поля в схеме данных.
|
/// Объект для определения типа поля в схеме данных.
|
||||||
@@ -51,7 +51,7 @@ internal class SchemaNode
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Количество значений, добавленных в тип.
|
/// Количество значений, добавленных в тип.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Values { get; protected set; } = 0;
|
public int Values { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Указание, является ли тип элемента простым.
|
/// Указание, является ли тип элемента простым.
|
||||||
@@ -93,13 +93,10 @@ internal class SchemaNode
|
|||||||
|
|
||||||
Values++;
|
Values++;
|
||||||
|
|
||||||
foreach (AbstractSchemaType type in Types)
|
foreach (AbstractSchemaType type in Types.Where(type => type.IsCompatibleValue(value)))
|
||||||
{
|
{
|
||||||
if (type.IsCompatibleValue(value))
|
type.AddValue(value);
|
||||||
{
|
return;
|
||||||
type.AddValue(value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractSchemaType newType = Resolver.Resolve(this, value);
|
AbstractSchemaType newType = Resolver.Resolve(this, value);
|
||||||
@@ -161,7 +158,7 @@ internal class SchemaNode
|
|||||||
|
|
||||||
foreach (AbstractSchemaType type in Types)
|
foreach (AbstractSchemaType type in Types)
|
||||||
{
|
{
|
||||||
types.Add(Indent(type?.ToString() ?? ""));
|
types.Add(Indent(type.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return FormatYaml(result, new() { ["types"] = "- " + string.Join("\r\n- ", types) });
|
return FormatYaml(result, new() { ["types"] = "- " + string.Join("\r\n- ", types) });
|
||||||
@@ -223,19 +220,9 @@ internal class SchemaNode
|
|||||||
{
|
{
|
||||||
Dictionary<string, string> result = [];
|
Dictionary<string, string> result = [];
|
||||||
|
|
||||||
foreach (Dictionary<string, string> item in input)
|
foreach (KeyValuePair<string, string> kvp in input.SelectMany(item => item))
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<string, string> kvp in item)
|
result[kvp.Key] = kvp.Value;
|
||||||
{
|
|
||||||
if (result.ContainsKey(kvp.Key))
|
|
||||||
{
|
|
||||||
result[kvp.Key] = kvp.Value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.Add(kvp.Key, kvp.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
+12
-4
@@ -13,7 +13,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
namespace Pf2eModel.Migrations
|
namespace Pf2eModel.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(Pf2eDbContext))]
|
[DbContext(typeof(Pf2eDbContext))]
|
||||||
[Migration("20250425111349_1")]
|
[Migration("20250426125550_1")]
|
||||||
partial class _1
|
partial class _1
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -182,11 +182,18 @@ namespace Pf2eModel.Migrations
|
|||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("jsonb")
|
||||||
|
.HasColumnName("name")
|
||||||
|
.HasColumnOrder(2);
|
||||||
|
|
||||||
b.Property<string>("Slug")
|
b.Property<string>("Slug")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text")
|
.HasMaxLength(255)
|
||||||
|
.HasColumnType("character varying(255)")
|
||||||
.HasColumnName("slug")
|
.HasColumnName("slug")
|
||||||
.HasColumnOrder(2);
|
.HasColumnOrder(3);
|
||||||
|
|
||||||
b.HasKey("Id")
|
b.HasKey("Id")
|
||||||
.HasName("pk_keywords");
|
.HasName("pk_keywords");
|
||||||
@@ -1457,7 +1464,8 @@ namespace Pf2eModel.Migrations
|
|||||||
b.Property<string>("Extra")
|
b.Property<string>("Extra")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text")
|
.HasColumnType("text")
|
||||||
.HasColumnName("extra");
|
.HasColumnName("extra")
|
||||||
|
.HasColumnOrder(4);
|
||||||
|
|
||||||
b.Property<int>("GroupId")
|
b.Property<int>("GroupId")
|
||||||
.HasColumnType("integer")
|
.HasColumnType("integer")
|
||||||
@@ -91,7 +91,8 @@ namespace Pf2eModel.Migrations
|
|||||||
{
|
{
|
||||||
id = table.Column<int>(type: "integer", nullable: false)
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
slug = table.Column<string>(type: "text", nullable: false)
|
name = table.Column<string>(type: "jsonb", nullable: false),
|
||||||
|
slug = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false)
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
@@ -179,11 +179,18 @@ namespace Pf2eModel.Migrations
|
|||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("jsonb")
|
||||||
|
.HasColumnName("name")
|
||||||
|
.HasColumnOrder(2);
|
||||||
|
|
||||||
b.Property<string>("Slug")
|
b.Property<string>("Slug")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text")
|
.HasMaxLength(255)
|
||||||
|
.HasColumnType("character varying(255)")
|
||||||
.HasColumnName("slug")
|
.HasColumnName("slug")
|
||||||
.HasColumnOrder(2);
|
.HasColumnOrder(3);
|
||||||
|
|
||||||
b.HasKey("Id")
|
b.HasKey("Id")
|
||||||
.HasName("pk_keywords");
|
.HasName("pk_keywords");
|
||||||
@@ -1454,7 +1461,8 @@ namespace Pf2eModel.Migrations
|
|||||||
b.Property<string>("Extra")
|
b.Property<string>("Extra")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text")
|
.HasColumnType("text")
|
||||||
.HasColumnName("extra");
|
.HasColumnName("extra")
|
||||||
|
.HasColumnOrder(4);
|
||||||
|
|
||||||
b.Property<int>("GroupId")
|
b.Property<int>("GroupId")
|
||||||
.HasColumnType("integer")
|
.HasColumnType("integer")
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ namespace Pf2eModel.Model.Base;
|
|||||||
|
|
||||||
public class Entity
|
public class Entity
|
||||||
{
|
{
|
||||||
[System.ComponentModel.DataAnnotations.Key]
|
[Key]
|
||||||
[Column(Order = 1)]
|
[Column(Order = 1)]
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
[Column(Order = 2)]
|
[Column(Order = 2)]
|
||||||
[Comment("Отображаемое имя")]
|
[Comment("Отображаемое имя")]
|
||||||
public LocaleString Name { get; set; } = new();
|
public LocaleString Name { get; set; } = [];
|
||||||
|
|
||||||
[Column(Order = 3)]
|
[Column(Order = 3)]
|
||||||
[Comment("Тип объекта")]
|
[Comment("Тип объекта")]
|
||||||
@@ -36,6 +36,7 @@ public class Entity
|
|||||||
|
|
||||||
[Column(Order = 6)]
|
[Column(Order = 6)]
|
||||||
[Comment("Текстовое описание объекта")]
|
[Comment("Текстовое описание объекта")]
|
||||||
|
// ReSharper disable once EntityFramework.ModelValidation.UnlimitedStringLength
|
||||||
public string Description { get; set; } = null!;
|
public string Description { get; set; } = null!;
|
||||||
|
|
||||||
[Column(Order = 7)]
|
[Column(Order = 7)]
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Pf2eModel.Model.Common.I18n;
|
||||||
|
|
||||||
namespace Pf2eModel.Model.Base.Keywords;
|
namespace Pf2eModel.Model.Base.Keywords;
|
||||||
|
|
||||||
public partial class Keyword
|
public class Keyword
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
@@ -11,10 +12,14 @@ public partial class Keyword
|
|||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
[Column(Order = 2)]
|
[Column(Order = 2)]
|
||||||
|
public LocaleString Name = [];
|
||||||
|
|
||||||
|
[Column(Order = 3)]
|
||||||
|
[MaxLength(Pf2eDbContext.NameLength)]
|
||||||
public string Slug { get; set; } = null!;
|
public string Slug { get; set; } = null!;
|
||||||
|
|
||||||
[Newtonsoft.Json.JsonIgnore]
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
public virtual ICollection<Entity> Entities { get; set; } = [];
|
public ICollection<Entity> Entities { get; set; } = [];
|
||||||
|
|
||||||
public virtual ICollection<KeywordAlias> Aliases { get; set; } = [];
|
public ICollection<KeywordAlias> Aliases { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Base.Keywords;
|
namespace Pf2eModel.Model.Base.Keywords;
|
||||||
|
|
||||||
public partial class KeywordAlias
|
public class KeywordAlias
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
@@ -18,5 +18,5 @@ public partial class KeywordAlias
|
|||||||
public string Value { get; set; } = null!;
|
public string Value { get; set; } = null!;
|
||||||
|
|
||||||
[Newtonsoft.Json.JsonIgnore]
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
public virtual Keyword Keyword { get; set; } = null!;
|
public Keyword Keyword { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
namespace Pf2eModel.Model.Base.Source;
|
namespace Pf2eModel.Model.Base.Source;
|
||||||
|
|
||||||
[PrimaryKey(nameof(EntityId), nameof(SourceId))]
|
[PrimaryKey(nameof(EntityId), nameof(SourceId))]
|
||||||
public partial class EntitySource
|
public class EntitySource
|
||||||
{
|
{
|
||||||
[Column(Order = 1)]
|
[Column(Order = 1)]
|
||||||
public int EntityId { get; set; }
|
public int EntityId { get; set; }
|
||||||
@@ -23,7 +23,7 @@ public partial class EntitySource
|
|||||||
public bool IsRemaster { get; set; }
|
public bool IsRemaster { get; set; }
|
||||||
|
|
||||||
[Newtonsoft.Json.JsonIgnore]
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
public virtual Entity Entity { get; set; } = null!;
|
public Entity Entity { get; set; } = null!;
|
||||||
|
|
||||||
public virtual Source Source { get; set; } = null!;
|
public Source Source { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Base.Source;
|
namespace Pf2eModel.Model.Base.Source;
|
||||||
|
|
||||||
public partial class Source
|
public class Source
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
namespace Pf2eModel.Model.Base.Targets;
|
namespace Pf2eModel.Model.Base.Targets;
|
||||||
|
|
||||||
[PrimaryKey(nameof(EntityId), nameof(TargetId))]
|
[PrimaryKey(nameof(EntityId), nameof(TargetId))]
|
||||||
public partial class EntityExternal
|
public class EntityExternal
|
||||||
{
|
{
|
||||||
[Column(Order = 0)]
|
[Column(Order = 0)]
|
||||||
public int EntityId { get; set; }
|
public int EntityId { get; set; }
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Base.Targets;
|
namespace Pf2eModel.Model.Base.Targets;
|
||||||
|
|
||||||
public partial class ExternalTarget
|
public class ExternalTarget
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
@@ -24,5 +24,5 @@ public partial class ExternalTarget
|
|||||||
|
|
||||||
[Column(Order = 4)]
|
[Column(Order = 4)]
|
||||||
[Newtonsoft.Json.JsonIgnore]
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
public virtual ICollection<EntityExternal> EntityExternals { get; set; } = [];
|
public ICollection<EntityExternal> EntityExternals { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Common;
|
namespace Pf2eModel.Model.Common;
|
||||||
|
|
||||||
public partial class Frequency
|
public class Frequency
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
|||||||
@@ -18,17 +18,19 @@ public static class LocaleExtension
|
|||||||
|
|
||||||
public static LocaleType GetTypeByString(this string localeType)
|
public static LocaleType GetTypeByString(this string localeType)
|
||||||
{
|
{
|
||||||
foreach (System.Reflection.FieldInfo field in typeof(LocaleType).GetFields())
|
foreach (FieldInfo field in typeof(LocaleType).GetFields())
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))
|
Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))
|
||||||
is DescriptionAttribute descriptionAttribute
|
is not DescriptionAttribute descriptionAttribute
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (descriptionAttribute.Description == localeType)
|
continue;
|
||||||
{
|
}
|
||||||
return (LocaleType)field.GetValue(null)!;
|
|
||||||
}
|
if (descriptionAttribute.Description == localeType)
|
||||||
|
{
|
||||||
|
return (LocaleType)field.GetValue(null)!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ public class LocaleString : ICollection<LocaleItem>
|
|||||||
|
|
||||||
foreach (KeyValuePair<string, JToken?> item in json)
|
foreach (KeyValuePair<string, JToken?> item in json)
|
||||||
{
|
{
|
||||||
result[item.Key] = item.ToString();
|
result[item.Key] = item.Value?.ToString() ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Common;
|
namespace Pf2eModel.Model.Common;
|
||||||
|
|
||||||
public partial class Training
|
public class Training
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
[EntityOfType(EntityType.Action)]
|
[EntityOfType(EntityType.Action)]
|
||||||
public partial class Action : IEntity
|
public class Action : IEntity
|
||||||
{
|
{
|
||||||
[System.ComponentModel.DataAnnotations.Key]
|
[System.ComponentModel.DataAnnotations.Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
@@ -28,6 +28,7 @@ public partial class Action : IEntity
|
|||||||
public bool IsPassive { get; set; } = false;
|
public bool IsPassive { get; set; } = false;
|
||||||
|
|
||||||
[Column(Order = 6)]
|
[Column(Order = 6)]
|
||||||
|
// ReSharper disable once EntityFramework.ModelValidation.UnlimitedStringLength
|
||||||
public string? Extra { get; set; }
|
public string? Extra { get; set; }
|
||||||
|
|
||||||
public Entity Entity { get; set; } = null!;
|
public Entity Entity { get; set; } = null!;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using Pf2eModel.Model.Structure.AncestryRelation;
|
|||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
[EntityOfType(EntityType.Ancestry)]
|
[EntityOfType(EntityType.Ancestry)]
|
||||||
public partial class Ancestry : IEntity
|
public class Ancestry : IEntity
|
||||||
{
|
{
|
||||||
[System.ComponentModel.DataAnnotations.Key]
|
[System.ComponentModel.DataAnnotations.Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
@@ -27,11 +27,11 @@ public partial class Ancestry : IEntity
|
|||||||
[Column(Order = 5)]
|
[Column(Order = 5)]
|
||||||
public AncestryVision Vision { get; set; } = AncestryVision.Normal;
|
public AncestryVision Vision { get; set; } = AncestryVision.Normal;
|
||||||
|
|
||||||
public virtual ICollection<AncestryBoost> AncestryBoosts { get; set; } = [];
|
public ICollection<AncestryBoost> AncestryBoosts { get; set; } = [];
|
||||||
|
|
||||||
public virtual ICollection<AncestryItem> AncestryItems { get; set; } = [];
|
public ICollection<AncestryItem> AncestryItems { get; set; } = [];
|
||||||
|
|
||||||
public virtual ICollection<AncestryLanguage> AncestryLanguages { get; set; } = [];
|
public ICollection<AncestryLanguage> AncestryLanguages { get; set; } = [];
|
||||||
|
|
||||||
public virtual ICollection<Heritage> Heritages { get; set; } = [];
|
public ICollection<Heritage> Heritages { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Newtonsoft.Json;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.AncestryRelation;
|
namespace Pf2eModel.Model.Structure.AncestryRelation;
|
||||||
|
|
||||||
public partial class AncestryBoost
|
public class AncestryBoost
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
@@ -21,5 +21,5 @@ public partial class AncestryBoost
|
|||||||
public Enum.AttributeValues Value { get; set; }
|
public Enum.AttributeValues Value { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual Ancestry Ancestry { get; set; } = null!;
|
public Ancestry Ancestry { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Pf2eModel.Model.Base;
|
|||||||
namespace Pf2eModel.Model.Structure.AncestryRelation;
|
namespace Pf2eModel.Model.Structure.AncestryRelation;
|
||||||
|
|
||||||
[PrimaryKey(nameof(AncestryId), nameof(ItemId))]
|
[PrimaryKey(nameof(AncestryId), nameof(ItemId))]
|
||||||
public partial class AncestryItem
|
public class AncestryItem
|
||||||
{
|
{
|
||||||
[Column(Order = 1)]
|
[Column(Order = 1)]
|
||||||
public int AncestryId { get; set; }
|
public int AncestryId { get; set; }
|
||||||
@@ -16,7 +16,7 @@ public partial class AncestryItem
|
|||||||
[Column(Order = 3)]
|
[Column(Order = 3)]
|
||||||
public int Level { get; set; }
|
public int Level { get; set; }
|
||||||
|
|
||||||
public virtual Ancestry Ancestry { get; set; } = null!;
|
public Ancestry Ancestry { get; set; } = null!;
|
||||||
|
|
||||||
public virtual Entity Item { get; set; } = null!;
|
public Entity Item { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
namespace Pf2eModel.Model.Structure.AncestryRelation;
|
namespace Pf2eModel.Model.Structure.AncestryRelation;
|
||||||
|
|
||||||
[PrimaryKey(nameof(AncestryId), nameof(LanguageId))]
|
[PrimaryKey(nameof(AncestryId), nameof(LanguageId))]
|
||||||
public partial class AncestryLanguage
|
public class AncestryLanguage
|
||||||
{
|
{
|
||||||
[Column(Order = 1)]
|
[Column(Order = 1)]
|
||||||
public int AncestryId { get; set; }
|
public int AncestryId { get; set; }
|
||||||
@@ -15,7 +15,7 @@ public partial class AncestryLanguage
|
|||||||
[Column(Order = 3)]
|
[Column(Order = 3)]
|
||||||
public bool IsAdditional { get; set; }
|
public bool IsAdditional { get; set; }
|
||||||
|
|
||||||
public virtual Ancestry Ancestry { get; set; } = null!;
|
public Ancestry Ancestry { get; set; } = null!;
|
||||||
|
|
||||||
public virtual Language Language { get; set; } = null!;
|
public Language Language { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,10 @@ public class Archetype : IEntity
|
|||||||
public int? DedicationFeatId { get; set; } = null;
|
public int? DedicationFeatId { get; set; } = null;
|
||||||
|
|
||||||
[Column(Order = 4)]
|
[Column(Order = 4)]
|
||||||
|
// ReSharper disable once EntityFramework.ModelValidation.UnlimitedStringLength
|
||||||
public string? Extra { get; set; }
|
public string? Extra { get; set; }
|
||||||
|
|
||||||
public Feat DedicationFeat { get; set; } = null!;
|
public Feat DedicationFeat { get; set; } = null!;
|
||||||
|
|
||||||
public virtual ICollection<Feat> Feats { get; set; } = [];
|
public ICollection<Feat> Feats { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using Pf2eModel.Model.Structure.BackgroundRelation;
|
|||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
[EntityOfType(EntityType.Background)]
|
[EntityOfType(EntityType.Background)]
|
||||||
public partial class Background : IEntity
|
public class Background : IEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
@@ -16,9 +16,9 @@ public partial class Background : IEntity
|
|||||||
|
|
||||||
public Entity Entity { get; set; } = null!;
|
public Entity Entity { get; set; } = null!;
|
||||||
|
|
||||||
public virtual ICollection<BackgroundBoost> BackgroundBoosts { get; set; } = [];
|
public ICollection<BackgroundBoost> BackgroundBoosts { get; set; } = [];
|
||||||
|
|
||||||
public virtual ICollection<BackgroundItem> BackgroundItems { get; set; } = [];
|
public ICollection<BackgroundItem> BackgroundItems { get; set; } = [];
|
||||||
|
|
||||||
public virtual ICollection<BackgroundTraining> BackgroundSkills { get; set; } = [];
|
public ICollection<BackgroundTraining> BackgroundSkills { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.BackgroundRelation;
|
namespace Pf2eModel.Model.Structure.BackgroundRelation;
|
||||||
|
|
||||||
public partial class BackgroundBoost
|
public class BackgroundBoost
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
@@ -19,5 +19,5 @@ public partial class BackgroundBoost
|
|||||||
public AttributeValues Attribute { get; set; }
|
public AttributeValues Attribute { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual Background Background { get; set; } = null!;
|
public Background Background { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using Pf2eModel.Model.Base;
|
|||||||
namespace Pf2eModel.Model.Structure.BackgroundRelation;
|
namespace Pf2eModel.Model.Structure.BackgroundRelation;
|
||||||
|
|
||||||
[PrimaryKey(nameof(BackgroundId), nameof(EntityId))]
|
[PrimaryKey(nameof(BackgroundId), nameof(EntityId))]
|
||||||
public partial class BackgroundItem
|
public class BackgroundItem
|
||||||
{
|
{
|
||||||
[Column(Order = 1)]
|
[Column(Order = 1)]
|
||||||
public int BackgroundId { get; set; }
|
public int BackgroundId { get; set; }
|
||||||
@@ -18,7 +18,7 @@ public partial class BackgroundItem
|
|||||||
public int? Level { get; set; }
|
public int? Level { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual Background Background { get; set; } = null!;
|
public Background Background { get; set; } = null!;
|
||||||
|
|
||||||
public virtual Entity Entity { get; set; } = null!;
|
public Entity Entity { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.BackgroundRelation;
|
namespace Pf2eModel.Model.Structure.BackgroundRelation;
|
||||||
|
|
||||||
public partial class BackgroundTraining
|
public class BackgroundTraining
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
@@ -23,7 +23,7 @@ public partial class BackgroundTraining
|
|||||||
public TrainingStage Level { get; set; }
|
public TrainingStage Level { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual Background Background { get; set; } = null!;
|
public Background Background { get; set; } = null!;
|
||||||
|
|
||||||
public virtual Training Training { get; set; } = null!;
|
public Training Training { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using Pf2eModel.Model.Structure.ClassRelation;
|
|||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
[EntityOfType(EntityType.Class)]
|
[EntityOfType(EntityType.Class)]
|
||||||
public partial class Class : IEntity
|
public class Class : IEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[Column(Order = 1)]
|
[Column(Order = 1)]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.ClassRelation;
|
namespace Pf2eModel.Model.Structure.ClassRelation;
|
||||||
|
|
||||||
public partial class ClassKeyAbility
|
public class ClassKeyAbility
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
@@ -19,5 +19,5 @@ public partial class ClassKeyAbility
|
|||||||
public AttributeValues Value { get; set; }
|
public AttributeValues Value { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual Class Class { get; set; } = null!;
|
public Class Class { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.ClassRelation;
|
namespace Pf2eModel.Model.Structure.ClassRelation;
|
||||||
|
|
||||||
public partial class ClassProgression
|
public class ClassProgression
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
@@ -26,7 +26,7 @@ public partial class ClassProgression
|
|||||||
public int? EntityId { get; set; }
|
public int? EntityId { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual Class Class { get; set; } = null!;
|
public Class Class { get; set; } = null!;
|
||||||
|
|
||||||
public virtual Entity? Entity { get; set; }
|
public Entity? Entity { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.ClassRelation;
|
namespace Pf2eModel.Model.Structure.ClassRelation;
|
||||||
|
|
||||||
public partial class ClassTraining
|
public class ClassTraining
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
@@ -27,7 +27,7 @@ public partial class ClassTraining
|
|||||||
public TrainingStage Stage { get; set; }
|
public TrainingStage Stage { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual Class Class { get; set; } = null!;
|
public Class Class { get; set; } = null!;
|
||||||
|
|
||||||
public virtual Training? Training { get; set; }
|
public Training? Training { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
[EntityOfType(EntityType.Condition)]
|
[EntityOfType(EntityType.Condition)]
|
||||||
public partial class Condition : IEntity
|
public class Condition : IEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
@@ -19,5 +19,6 @@ public partial class Condition : IEntity
|
|||||||
public ConditionGroup? Group { get; set; }
|
public ConditionGroup? Group { get; set; }
|
||||||
|
|
||||||
[Column(Order = 3)]
|
[Column(Order = 3)]
|
||||||
|
// ReSharper disable once EntityFramework.ModelValidation.UnlimitedStringLength
|
||||||
public string? Extra { get; set; }
|
public string? Extra { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using Pf2eModel.Model.Structure.DeityRelation;
|
|||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
[EntityOfType(EntityType.Deity)]
|
[EntityOfType(EntityType.Deity)]
|
||||||
public partial class Deity : IEntity
|
public class Deity : IEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
@@ -29,14 +29,13 @@ public partial class Deity : IEntity
|
|||||||
[Column(Order = 5)]
|
[Column(Order = 5)]
|
||||||
public bool SanctificationMust { get; set; }
|
public bool SanctificationMust { get; set; }
|
||||||
|
|
||||||
public virtual ICollection<DeityAttribute> DeityAttributes { get; set; } =
|
public ICollection<DeityAttribute> DeityAttributes { get; set; } = new List<DeityAttribute>();
|
||||||
new List<DeityAttribute>();
|
|
||||||
|
|
||||||
public virtual ICollection<DeityDomain> DeityDomains { get; set; } = new List<DeityDomain>();
|
public ICollection<DeityDomain> DeityDomains { get; set; } = new List<DeityDomain>();
|
||||||
|
|
||||||
public virtual ICollection<DeitySpell> DeitySpells { get; set; } = new List<DeitySpell>();
|
public ICollection<DeitySpell> DeitySpells { get; set; } = new List<DeitySpell>();
|
||||||
|
|
||||||
public virtual ICollection<DeityWeapon> DeityWeapons { get; set; } = new List<DeityWeapon>();
|
public ICollection<DeityWeapon> DeityWeapons { get; set; } = new List<DeityWeapon>();
|
||||||
|
|
||||||
public virtual ICollection<Training> Skills { get; set; } = new List<Training>();
|
public ICollection<Training> Skills { get; set; } = new List<Training>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
namespace Pf2eModel.Model.Structure.DeityRelation;
|
namespace Pf2eModel.Model.Structure.DeityRelation;
|
||||||
|
|
||||||
[PrimaryKey(nameof(DeityId), nameof(Attribute))]
|
[PrimaryKey(nameof(DeityId), nameof(Attribute))]
|
||||||
public partial class DeityAttribute
|
public class DeityAttribute
|
||||||
{
|
{
|
||||||
[Column(Order = 1)]
|
[Column(Order = 1)]
|
||||||
public int DeityId { get; set; }
|
public int DeityId { get; set; }
|
||||||
@@ -13,5 +13,5 @@ public partial class DeityAttribute
|
|||||||
[Column(Order = 2)]
|
[Column(Order = 2)]
|
||||||
public AttributeValues Attribute { get; set; }
|
public AttributeValues Attribute { get; set; }
|
||||||
|
|
||||||
public virtual Deity Deity { get; set; } = null!;
|
public Deity Deity { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.DeityRelation;
|
namespace Pf2eModel.Model.Structure.DeityRelation;
|
||||||
|
|
||||||
public partial class DeityDomain
|
public class DeityDomain
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.DeityRelation;
|
namespace Pf2eModel.Model.Structure.DeityRelation;
|
||||||
|
|
||||||
public partial class DeitySpell
|
public class DeitySpell
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.DeityRelation;
|
namespace Pf2eModel.Model.Structure.DeityRelation;
|
||||||
|
|
||||||
public partial class DeityWeapon
|
public class DeityWeapon
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using Pf2eModel.Model.Structure.FeatRelation;
|
|||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
[EntityOfType(EntityType.Feat)]
|
[EntityOfType(EntityType.Feat)]
|
||||||
public partial class Feat : IEntity
|
public class Feat : IEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
@@ -38,9 +38,10 @@ public partial class Feat : IEntity
|
|||||||
public bool IsPassive { get; set; } = false;
|
public bool IsPassive { get; set; } = false;
|
||||||
|
|
||||||
[Column(Order = 10)]
|
[Column(Order = 10)]
|
||||||
|
// ReSharper disable once EntityFramework.ModelValidation.UnlimitedStringLength
|
||||||
public string? Extra { get; set; }
|
public string? Extra { get; set; }
|
||||||
|
|
||||||
public virtual ICollection<Archetype> Archetypes { get; set; } = [];
|
public ICollection<Archetype> Archetypes { get; set; } = [];
|
||||||
|
|
||||||
public virtual ICollection<FeatPrerequisite> FeatPrerequisites { get; set; } = [];
|
public ICollection<FeatPrerequisite> FeatPrerequisites { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.FeatRelation;
|
namespace Pf2eModel.Model.Structure.FeatRelation;
|
||||||
|
|
||||||
public partial class FeatPrerequisite
|
public class FeatPrerequisite
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
[EntityOfType(EntityType.Heritage)]
|
[EntityOfType(EntityType.Heritage)]
|
||||||
public partial class Heritage : IEntity
|
public class Heritage : IEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
[EntityOfType(EntityType.Language)]
|
[EntityOfType(EntityType.Language)]
|
||||||
public partial class Language : IEntity
|
public class Language : IEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using Pf2eModel.Model.Structure.SpellRelation;
|
|||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
[EntityOfType(EntityType.Spell)]
|
[EntityOfType(EntityType.Spell)]
|
||||||
public partial class Spell : IEntity
|
public class Spell : IEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.SpellRelation;
|
namespace Pf2eModel.Model.Structure.SpellRelation;
|
||||||
|
|
||||||
public partial class SpellArea
|
public class SpellArea
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.SpellRelation;
|
namespace Pf2eModel.Model.Structure.SpellRelation;
|
||||||
|
|
||||||
public partial class SpellDamage
|
public class SpellDamage
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.SpellRelation;
|
namespace Pf2eModel.Model.Structure.SpellRelation;
|
||||||
|
|
||||||
public partial class SpellDefense
|
public class SpellDefense
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
|
|
||||||
namespace Pf2eModel.Model.Structure.SpellRelation;
|
namespace Pf2eModel.Model.Structure.SpellRelation;
|
||||||
|
|
||||||
public partial class SpellRitual
|
public class SpellRitual
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ public class Subclass : IEntity
|
|||||||
public SubclassGroup Group { get; set; } = null!;
|
public SubclassGroup Group { get; set; } = null!;
|
||||||
|
|
||||||
[Column(Order = 3)]
|
[Column(Order = 3)]
|
||||||
public LocaleString Additional { get; set; } = new();
|
public LocaleString Additional { get; set; } = [];
|
||||||
|
|
||||||
|
[Column(Order = 4)]
|
||||||
|
// ReSharper disable once EntityFramework.ModelValidation.UnlimitedStringLength
|
||||||
public string Extra { get; set; } = "{}";
|
public string Extra { get; set; } = "{}";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
using System;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Pf2eModel.Model.Base;
|
using Pf2eModel.Model.Base;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
using Pf2eModel.Model.Structure.ClassRelation;
|
|
||||||
|
|
||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
@@ -25,5 +19,5 @@ public class SubclassGroup : IEntity
|
|||||||
|
|
||||||
public Class? Class { get; set; } = null!;
|
public Class? Class { get; set; } = null!;
|
||||||
|
|
||||||
public virtual ICollection<Subclass> Subclasses { get; set; } = [];
|
public ICollection<Subclass> Subclasses { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using Pf2eModel.Model.Enum;
|
|||||||
namespace Pf2eModel.Model.Structure;
|
namespace Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
[EntityOfType(EntityType.Trait)]
|
[EntityOfType(EntityType.Trait)]
|
||||||
public partial class Trait : IEntity
|
public class Trait : IEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
[DatabaseGenerated(DatabaseGeneratedOption.None)]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Linq.Expressions;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
@@ -21,6 +22,7 @@ using Pf2eModel.Model.Structure.SpellRelation;
|
|||||||
|
|
||||||
namespace Pf2eModel;
|
namespace Pf2eModel;
|
||||||
|
|
||||||
|
[SuppressMessage("ReSharper", "UnusedParameter.Local")]
|
||||||
public partial class Pf2eDbContext
|
public partial class Pf2eDbContext
|
||||||
{
|
{
|
||||||
public const int NameLength = 255;
|
public const int NameLength = 255;
|
||||||
@@ -39,11 +41,7 @@ public partial class Pf2eDbContext
|
|||||||
private void BindEntity<T>(EntityTypeBuilder<T> entity)
|
private void BindEntity<T>(EntityTypeBuilder<T> entity)
|
||||||
where T : class, IEntity
|
where T : class, IEntity
|
||||||
{
|
{
|
||||||
entity
|
entity.HasOne(e => e.Entity).WithOne().HasForeignKey<T>(e => e.Id).IsRequired();
|
||||||
.HasOne(entity => entity.Entity)
|
|
||||||
.WithOne()
|
|
||||||
.HasForeignKey<T>(entity => entity.Id)
|
|
||||||
.IsRequired();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BindLocaleString<T>(
|
private void BindLocaleString<T>(
|
||||||
@@ -144,6 +142,8 @@ public partial class Pf2eDbContext
|
|||||||
// Keywords
|
// Keywords
|
||||||
modelBuilder.Entity<Keyword>(entity =>
|
modelBuilder.Entity<Keyword>(entity =>
|
||||||
{
|
{
|
||||||
|
BindLocaleString(entity, k => k.Name);
|
||||||
|
|
||||||
entity
|
entity
|
||||||
.HasMany(e => e.Aliases)
|
.HasMany(e => e.Aliases)
|
||||||
.WithOne(e => e.Keyword)
|
.WithOne(e => e.Keyword)
|
||||||
@@ -483,9 +483,11 @@ public partial class Pf2eDbContext
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
public static bool LocaleSearch(LocaleString data, string search_value) =>
|
public static bool LocaleSearch(LocaleString data, string search_value) =>
|
||||||
throw new InvalidOperationException("Only for LINQ translation");
|
throw new InvalidOperationException("Only for LINQ translation");
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
public static bool LocaleSearchArray(LocaleString data, IEnumerable<string> search_values) =>
|
public static bool LocaleSearchArray(LocaleString data, IEnumerable<string> search_values) =>
|
||||||
throw new InvalidOperationException("Only for LINQ translation");
|
throw new InvalidOperationException("Only for LINQ translation");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Pf2eModel;
|
||||||
|
using Pf2eModel.Model;
|
||||||
|
using Pf2eModel.Model.Base;
|
||||||
|
using Pf2eModel.Model.Common.I18n;
|
||||||
|
using Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
|
namespace Pf2eViewer.Converters;
|
||||||
|
|
||||||
|
internal class EntityConverter : JsonConverter
|
||||||
|
{
|
||||||
|
private readonly Pf2eDbContext _context = new();
|
||||||
|
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(Entity) || objectType.IsAssignableTo(typeof(IEntity));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<string, object?> DictionarySerialization(object source)
|
||||||
|
{
|
||||||
|
Dictionary<string, object?> dictionary = [];
|
||||||
|
|
||||||
|
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
|
||||||
|
{
|
||||||
|
if (property.Attributes.OfType<JsonIgnoreAttribute>().Any())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
object? v = property.GetValue(source);
|
||||||
|
dictionary.Add(property.Name, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, object?> dictionary = DictionarySerialization(value);
|
||||||
|
|
||||||
|
if (value.GetType() != typeof(Entity))
|
||||||
|
{
|
||||||
|
dictionary.Remove("Entity");
|
||||||
|
|
||||||
|
Processor? processor = _processors.FirstOrDefault(p => p.Type == value.GetType());
|
||||||
|
|
||||||
|
processor?.Process(dictionary, (IEntity)value, this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dictionary.Remove("Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer.Serialize(writer, dictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract class Processor
|
||||||
|
{
|
||||||
|
public abstract Type Type { get; }
|
||||||
|
|
||||||
|
public abstract void Process(
|
||||||
|
Dictionary<string, object?> dictionary,
|
||||||
|
IEntity entity,
|
||||||
|
EntityConverter converter
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Processor<T>(Action<Dictionary<string, object?>, T, EntityConverter> method)
|
||||||
|
: Processor
|
||||||
|
where T : IEntity
|
||||||
|
{
|
||||||
|
public override Type Type { get; } = typeof(T);
|
||||||
|
|
||||||
|
public override void Process(
|
||||||
|
Dictionary<string, object?> dictionary,
|
||||||
|
IEntity entity,
|
||||||
|
EntityConverter converter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
method.Invoke(dictionary, (T)entity, converter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ICollection<Processor> _processors =
|
||||||
|
[
|
||||||
|
new Processor<Trait>(
|
||||||
|
(dictionary, trait, converter) =>
|
||||||
|
{
|
||||||
|
LocaleString name =
|
||||||
|
// ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract
|
||||||
|
trait.Entity?.Name
|
||||||
|
?? converter
|
||||||
|
._context.Entities.Where(e => e.Id == trait.Id)
|
||||||
|
.Select(e => e.Name)
|
||||||
|
.FirstOrDefault()!;
|
||||||
|
|
||||||
|
dictionary.Remove("Entity");
|
||||||
|
dictionary.Remove("Entities");
|
||||||
|
dictionary.Add("Name", name.ToString());
|
||||||
|
}
|
||||||
|
),
|
||||||
|
new Processor<Subclass>(
|
||||||
|
(dictionary, _, _) =>
|
||||||
|
{
|
||||||
|
dictionary.Remove("Group");
|
||||||
|
}
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
public override bool CanRead => false;
|
||||||
|
|
||||||
|
public override object ReadJson(
|
||||||
|
JsonReader reader,
|
||||||
|
Type objectType,
|
||||||
|
object? existingValue,
|
||||||
|
JsonSerializer serializer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException(
|
||||||
|
"Unnecessary because CanRead is false. The type will skip the converter."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Pf2eModel.Model.Common.I18n;
|
||||||
|
|
||||||
|
namespace Pf2eViewer.Converters;
|
||||||
|
|
||||||
|
public class LocaleStringConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(LocaleString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
JObject result = new();
|
||||||
|
|
||||||
|
LocaleString str = (LocaleString)value!;
|
||||||
|
|
||||||
|
foreach (LocaleItem item in str)
|
||||||
|
{
|
||||||
|
result.Add(item.Locale.GetTypeString(), item.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.WriteTo(writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead => false;
|
||||||
|
|
||||||
|
public override object ReadJson(
|
||||||
|
JsonReader reader,
|
||||||
|
Type objectType,
|
||||||
|
object? existingValue,
|
||||||
|
JsonSerializer serializer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException(
|
||||||
|
"Unnecessary because CanRead is false. The type will skip the converter."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
namespace Pf2eViewer;
|
||||||
|
|
||||||
|
internal sealed class CoreBindingNavigator : BindingNavigator
|
||||||
|
{
|
||||||
|
public CoreBindingNavigator()
|
||||||
|
{
|
||||||
|
AddStandardItems();
|
||||||
|
|
||||||
|
if (DeleteItem != null)
|
||||||
|
{
|
||||||
|
DeleteItem.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AddNewItem != null)
|
||||||
|
{
|
||||||
|
AddNewItem.Visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
+110
@@ -0,0 +1,110 @@
|
|||||||
|
namespace Pf2eViewer;
|
||||||
|
|
||||||
|
partial class DatabaseViewerControl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Обязательная переменная конструктора.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Освободить все используемые ресурсы.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Код, автоматически созданный конструктором компонентов
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Требуемый метод для поддержки конструктора — не изменяйте
|
||||||
|
/// содержимое этого метода с помощью редактора кода.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
components = new System.ComponentModel.Container();
|
||||||
|
BindingNavigator = new CoreBindingNavigator();
|
||||||
|
SearchTextBox = new TextBox();
|
||||||
|
DataGridView = new DataGridView();
|
||||||
|
DbBindingSource = new BindingSource(components);
|
||||||
|
PagesBindingSource = new BindingSource(components);
|
||||||
|
( BindingNavigator).BeginInit();
|
||||||
|
((System.ComponentModel.ISupportInitialize) DataGridView).BeginInit();
|
||||||
|
((System.ComponentModel.ISupportInitialize) DbBindingSource).BeginInit();
|
||||||
|
((System.ComponentModel.ISupportInitialize) PagesBindingSource).BeginInit();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// BindingNavigator
|
||||||
|
//
|
||||||
|
BindingNavigator.AddNewItem = null;
|
||||||
|
BindingNavigator.DeleteItem = null;
|
||||||
|
BindingNavigator.ImeMode = ImeMode.NoControl;
|
||||||
|
BindingNavigator.LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow;
|
||||||
|
BindingNavigator.Location = new Point(0, 0);
|
||||||
|
BindingNavigator.Name = "BindingNavigator";
|
||||||
|
BindingNavigator.Size = new Size(345, 25);
|
||||||
|
BindingNavigator.Stretch = true;
|
||||||
|
BindingNavigator.TabIndex = 1;
|
||||||
|
BindingNavigator.Text = "coreBindingNavigator1";
|
||||||
|
BindingNavigator.RefreshItems += BindingNavigator_RefreshItems;
|
||||||
|
//
|
||||||
|
// SearchTextBox
|
||||||
|
//
|
||||||
|
SearchTextBox.Dock = DockStyle.Top;
|
||||||
|
SearchTextBox.Location = new Point(0, 25);
|
||||||
|
SearchTextBox.Name = "SearchTextBox";
|
||||||
|
SearchTextBox.PlaceholderText = "Поиск";
|
||||||
|
SearchTextBox.Size = new Size(345, 23);
|
||||||
|
SearchTextBox.TabIndex = 3;
|
||||||
|
//
|
||||||
|
// DataGridView
|
||||||
|
//
|
||||||
|
DataGridView.AllowUserToAddRows = false;
|
||||||
|
DataGridView.AllowUserToDeleteRows = false;
|
||||||
|
DataGridView.AutoGenerateColumns = false;
|
||||||
|
DataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader;
|
||||||
|
DataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders;
|
||||||
|
DataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||||
|
DataGridView.DataSource = DbBindingSource;
|
||||||
|
DataGridView.Dock = DockStyle.Fill;
|
||||||
|
DataGridView.Location = new Point(0, 48);
|
||||||
|
DataGridView.MultiSelect = false;
|
||||||
|
DataGridView.Name = "DataGridView";
|
||||||
|
DataGridView.ReadOnly = true;
|
||||||
|
DataGridView.RowHeadersVisible = false;
|
||||||
|
DataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||||
|
DataGridView.Size = new Size(345, 345);
|
||||||
|
DataGridView.TabIndex = 4;
|
||||||
|
DataGridView.RowStateChanged += DataGridView_RowStateChanged;
|
||||||
|
//
|
||||||
|
// DatabaseViewerControl
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||||
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
|
Controls.Add(DataGridView);
|
||||||
|
Controls.Add(SearchTextBox);
|
||||||
|
Controls.Add(BindingNavigator);
|
||||||
|
Name = "DatabaseViewerControl";
|
||||||
|
Size = new Size(345, 393);
|
||||||
|
Load += DatabaseViewerControl_Load;
|
||||||
|
( BindingNavigator).EndInit();
|
||||||
|
((System.ComponentModel.ISupportInitialize) DataGridView).EndInit();
|
||||||
|
((System.ComponentModel.ISupportInitialize) DbBindingSource).EndInit();
|
||||||
|
((System.ComponentModel.ISupportInitialize) PagesBindingSource).EndInit();
|
||||||
|
ResumeLayout(false);
|
||||||
|
PerformLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
private CoreBindingNavigator BindingNavigator;
|
||||||
|
private TextBox SearchTextBox;
|
||||||
|
private DataGridView DataGridView;
|
||||||
|
private BindingSource DbBindingSource;
|
||||||
|
private BindingSource PagesBindingSource;
|
||||||
|
}
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
using Pf2eModel;
|
||||||
|
using Pf2eModel.Model.Base;
|
||||||
|
using Pf2eModel.Model.Common.I18n;
|
||||||
|
using Pf2eModel.Model.Enum;
|
||||||
|
|
||||||
|
namespace Pf2eViewer;
|
||||||
|
|
||||||
|
public partial class DatabaseViewerControl : UserControl
|
||||||
|
{
|
||||||
|
public readonly Pf2eDbContext Context = new();
|
||||||
|
|
||||||
|
private int _perPage = 30;
|
||||||
|
|
||||||
|
private int _page = 1;
|
||||||
|
|
||||||
|
private EntityType _type;
|
||||||
|
|
||||||
|
public int PerPage
|
||||||
|
{
|
||||||
|
get => _perPage;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_perPage = value;
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Page
|
||||||
|
{
|
||||||
|
get => _page;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_page = value;
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count { get; private set; }
|
||||||
|
|
||||||
|
public int MaxPage => Convert.ToInt32(Math.Ceiling(1.0 * Count / PerPage));
|
||||||
|
|
||||||
|
public EntityView CurrentEntity { get; private set; } = null!;
|
||||||
|
|
||||||
|
public EntityType Type
|
||||||
|
{
|
||||||
|
get => _type;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_type = value;
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool _updating = false;
|
||||||
|
|
||||||
|
public DatabaseViewerControl()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
BindingNavigator.BindingSource = DbBindingSource;
|
||||||
|
DataGridView.AutoGenerateColumns = true;
|
||||||
|
DataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DatabaseViewerControl_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindingNavigator_RefreshItems(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (_updating)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Page = (int)(BindingNavigator?.BindingSource?.Current ?? 1);
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateView()
|
||||||
|
{
|
||||||
|
_updating = true;
|
||||||
|
|
||||||
|
IQueryable<Entity> query = Context.Entities.Where(e =>
|
||||||
|
e.Type == Type
|
||||||
|
&& (
|
||||||
|
// ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall
|
||||||
|
SearchTextBox.Text == ""
|
||||||
|
|| Pf2eDbContext.LocaleSearch(e.Name, SearchTextBox.Text)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Count = query.Count();
|
||||||
|
|
||||||
|
PagesBindingSource.DataSource = Enumerable.Range(1, MaxPage).ToList();
|
||||||
|
BindingNavigator.BindingSource = PagesBindingSource;
|
||||||
|
|
||||||
|
DbBindingSource.DataSource = query
|
||||||
|
.Skip((Page - 1) * PerPage)
|
||||||
|
.Take(PerPage)
|
||||||
|
.Select(e => new EntityGridRow(e))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (DataGridView.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
DataGridView.Rows[0].Selected = true;
|
||||||
|
}
|
||||||
|
DataGridView.Update();
|
||||||
|
|
||||||
|
_updating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DataGridView_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataGridView.SelectedRows.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityGridRow data = (EntityGridRow)DataGridView.SelectedRows[0].DataBoundItem;
|
||||||
|
CurrentEntity = new(Context, Type, data.Id);
|
||||||
|
|
||||||
|
EntityChange?.Invoke(CurrentEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void EntityChangeHandler(EntityView newEntity);
|
||||||
|
|
||||||
|
public event EntityChangeHandler? EntityChange;
|
||||||
|
|
||||||
|
internal class EntityGridRow(Entity e)
|
||||||
|
{
|
||||||
|
public int Id { get; set; } = e.Id;
|
||||||
|
|
||||||
|
public string Name { get; set; } = e.Name[LocaleType.English];
|
||||||
|
|
||||||
|
public EntityRarity Rarity { get; set; } = e.Rarity;
|
||||||
|
|
||||||
|
private readonly Entity _e = e;
|
||||||
|
|
||||||
|
public Entity GetEntity() => _e;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="DbBindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="PagesBindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>163, 17</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
using System.ComponentModel;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Pf2eModel;
|
|
||||||
using Pf2eModel.Model;
|
|
||||||
using Pf2eModel.Model.Base;
|
|
||||||
using Pf2eModel.Model.Common.I18n;
|
|
||||||
using Pf2eModel.Model.Structure;
|
|
||||||
|
|
||||||
namespace Pf2eViewer;
|
|
||||||
|
|
||||||
internal class EntityConverter : JsonConverter
|
|
||||||
{
|
|
||||||
private readonly Pf2eDbContext _context = new();
|
|
||||||
|
|
||||||
public override bool CanConvert(Type objectType)
|
|
||||||
{
|
|
||||||
return objectType == typeof(Entity) || objectType.IsAssignableTo(typeof(IEntity));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dictionary<string, object?> DictionarySerialization(object source)
|
|
||||||
{
|
|
||||||
Dictionary<string, object?> dictionary = [];
|
|
||||||
|
|
||||||
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
|
|
||||||
{
|
|
||||||
if (property.Attributes.OfType<JsonIgnoreAttribute>().Any())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
object? v = property.GetValue(source);
|
|
||||||
dictionary.Add(property.Name, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dictionary;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
Dictionary<string, object?> dictionary = DictionarySerialization(value!);
|
|
||||||
/*
|
|
||||||
if (value.GetType() != typeof(Entity))
|
|
||||||
{
|
|
||||||
dictionary.Remove("Entity");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case Entity entity:
|
|
||||||
ProcessEntity(dictionary, entity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Trait trait:
|
|
||||||
ProcessTrait(dictionary, trait);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.WriteStartObject();
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, object> keyValuePair in dictionary)
|
|
||||||
{
|
|
||||||
writer.WritePropertyName(keyValuePair.Key, true);
|
|
||||||
|
|
||||||
serializer.Serialize(writer, keyValuePair.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.WriteEndObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProcessTrait(Dictionary<string, object?> dictionary, Trait trait)
|
|
||||||
{
|
|
||||||
LocaleString name =
|
|
||||||
trait.Entity?.Name
|
|
||||||
?? _context.Entities.Where(e => e.Id == trait.Id).Select(e => e.Name).FirstOrDefault()!;
|
|
||||||
|
|
||||||
dictionary.Remove("Entity");
|
|
||||||
dictionary.Remove("Entities");
|
|
||||||
dictionary.Add("Name", name.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProcessEntity(Dictionary<string, object?> dictionary, Entity entity)
|
|
||||||
{
|
|
||||||
dictionary.Remove("Description");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanRead => false;
|
|
||||||
|
|
||||||
public override object? ReadJson(
|
|
||||||
JsonReader reader,
|
|
||||||
Type objectType,
|
|
||||||
object? existingValue,
|
|
||||||
JsonSerializer serializer
|
|
||||||
)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException(
|
|
||||||
"Unnecessary because CanRead is false. The type will skip the converter."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Pf2eModel;
|
||||||
|
using Pf2eModel.Model;
|
||||||
|
using Pf2eModel.Model.Base;
|
||||||
|
using Pf2eModel.Model.Enum;
|
||||||
|
using Pf2eModel.Model.Structure;
|
||||||
|
|
||||||
|
namespace Pf2eViewer;
|
||||||
|
|
||||||
|
public class EntityView
|
||||||
|
{
|
||||||
|
public Entity? Entity;
|
||||||
|
public IEntity? SubEntity;
|
||||||
|
|
||||||
|
public EntityView(Pf2eDbContext context, EntityType type, int id)
|
||||||
|
{
|
||||||
|
Getter? getter = _getters.FirstOrDefault(g => g.Type == type);
|
||||||
|
|
||||||
|
Entity fullEntity =
|
||||||
|
context
|
||||||
|
.Entities.Where(e => e.Id == id && e.Type == type)
|
||||||
|
.Include(e => e.Sources)
|
||||||
|
.ThenInclude(s => s.Source)
|
||||||
|
.Include(e => e.Keywords)
|
||||||
|
.Include(e => e.Externals)
|
||||||
|
.ThenInclude(x => x.Target)
|
||||||
|
.Include(e => e.Traits)
|
||||||
|
.ThenInclude(t => t.Entity)
|
||||||
|
.FirstOrDefault() ?? throw new Exception("Entity is null");
|
||||||
|
|
||||||
|
IEntity? subEntity =
|
||||||
|
(getter != null)
|
||||||
|
? getter.Get(id, context)
|
||||||
|
: (IEntity?)context.Find(EntityOfTypeAttribute.Resolve(fullEntity), id);
|
||||||
|
|
||||||
|
Entity = fullEntity;
|
||||||
|
SubEntity = subEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ICollection<Getter> _getters =
|
||||||
|
[
|
||||||
|
new Getter<Ancestry>(
|
||||||
|
EntityType.Ancestry,
|
||||||
|
context => context.Ancestries.Include(a => a.AncestryBoosts)
|
||||||
|
),
|
||||||
|
new Getter<Archetype>(
|
||||||
|
EntityType.Archetype,
|
||||||
|
context =>
|
||||||
|
context
|
||||||
|
.Archetypes.Include(a => a.DedicationFeat)
|
||||||
|
.ThenInclude(f => f.Entity)
|
||||||
|
.Include(a => a.Feats)
|
||||||
|
.ThenInclude(f => f.Entity)
|
||||||
|
),
|
||||||
|
new Getter<Background>(
|
||||||
|
EntityType.Background,
|
||||||
|
context =>
|
||||||
|
context
|
||||||
|
.Backgrounds.Include(b => b.BackgroundBoosts)
|
||||||
|
.Include(b => b.BackgroundSkills)
|
||||||
|
.ThenInclude(t => t.Training)
|
||||||
|
.Include(b => b.BackgroundItems)
|
||||||
|
),
|
||||||
|
new Getter<Class>(
|
||||||
|
EntityType.Class,
|
||||||
|
context =>
|
||||||
|
context
|
||||||
|
.Classes.Include(c => c.ClassKeyAbilities)
|
||||||
|
.Include(c => c.ClassTrainings)
|
||||||
|
.ThenInclude(t => t.Training)
|
||||||
|
.Include(c => c.ClassProgressions)
|
||||||
|
),
|
||||||
|
new Getter<Feat>(
|
||||||
|
EntityType.Feat,
|
||||||
|
context =>
|
||||||
|
context.Feats.Include(f => f.Archetypes).ThenInclude(a => a.Entity).AsQueryable()
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
private abstract class Getter(EntityType type)
|
||||||
|
{
|
||||||
|
public readonly EntityType Type = type;
|
||||||
|
|
||||||
|
public abstract IEntity? Get(int id, Pf2eDbContext context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Getter<T>(EntityType type, Func<Pf2eDbContext, IQueryable<T>> method)
|
||||||
|
: Getter(type)
|
||||||
|
where T : IEntity
|
||||||
|
{
|
||||||
|
public override IEntity? Get(int id, Pf2eDbContext context)
|
||||||
|
{
|
||||||
|
return method.Invoke(context).FirstOrDefault(c => c.Id == id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+26
-127
@@ -31,16 +31,9 @@ partial class MainViewForm
|
|||||||
RootSplitContainer = new SplitContainer();
|
RootSplitContainer = new SplitContainer();
|
||||||
InnerSplitContainer = new SplitContainer();
|
InnerSplitContainer = new SplitContainer();
|
||||||
TypesListBox = new ListBox();
|
TypesListBox = new ListBox();
|
||||||
EntityGridView = new DataGridView();
|
DatabaseViewer = new DatabaseViewerControl();
|
||||||
PaginationPagel = new Panel();
|
|
||||||
PageTextBox = new TextBox();
|
|
||||||
PaginationLabel = new TextBox();
|
|
||||||
LastPageButton = new Button();
|
|
||||||
NextPageButton = new Button();
|
|
||||||
PrevPageButton = new Button();
|
|
||||||
FirstPageButton = new Button();
|
|
||||||
ResultSplitContainer = new SplitContainer();
|
ResultSplitContainer = new SplitContainer();
|
||||||
EntityTreeView = new TreeView();
|
JsonWebView = new Microsoft.Web.WebView2.WinForms.WebView2();
|
||||||
DescriptionTextBox = new TextBox();
|
DescriptionTextBox = new TextBox();
|
||||||
((System.ComponentModel.ISupportInitialize) RootSplitContainer).BeginInit();
|
((System.ComponentModel.ISupportInitialize) RootSplitContainer).BeginInit();
|
||||||
RootSplitContainer.Panel1.SuspendLayout();
|
RootSplitContainer.Panel1.SuspendLayout();
|
||||||
@@ -50,12 +43,11 @@ partial class MainViewForm
|
|||||||
InnerSplitContainer.Panel1.SuspendLayout();
|
InnerSplitContainer.Panel1.SuspendLayout();
|
||||||
InnerSplitContainer.Panel2.SuspendLayout();
|
InnerSplitContainer.Panel2.SuspendLayout();
|
||||||
InnerSplitContainer.SuspendLayout();
|
InnerSplitContainer.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize) EntityGridView).BeginInit();
|
|
||||||
PaginationPagel.SuspendLayout();
|
|
||||||
((System.ComponentModel.ISupportInitialize) ResultSplitContainer).BeginInit();
|
((System.ComponentModel.ISupportInitialize) ResultSplitContainer).BeginInit();
|
||||||
ResultSplitContainer.Panel1.SuspendLayout();
|
ResultSplitContainer.Panel1.SuspendLayout();
|
||||||
ResultSplitContainer.Panel2.SuspendLayout();
|
ResultSplitContainer.Panel2.SuspendLayout();
|
||||||
ResultSplitContainer.SuspendLayout();
|
ResultSplitContainer.SuspendLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize) JsonWebView).BeginInit();
|
||||||
SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// RootSplitContainer
|
// RootSplitContainer
|
||||||
@@ -90,8 +82,7 @@ partial class MainViewForm
|
|||||||
//
|
//
|
||||||
// InnerSplitContainer.Panel2
|
// InnerSplitContainer.Panel2
|
||||||
//
|
//
|
||||||
InnerSplitContainer.Panel2.Controls.Add(EntityGridView);
|
InnerSplitContainer.Panel2.Controls.Add(DatabaseViewer);
|
||||||
InnerSplitContainer.Panel2.Controls.Add(PaginationPagel);
|
|
||||||
InnerSplitContainer.Size = new Size(254, 688);
|
InnerSplitContainer.Size = new Size(254, 688);
|
||||||
InnerSplitContainer.SplitterDistance = 102;
|
InnerSplitContainer.SplitterDistance = 102;
|
||||||
InnerSplitContainer.TabIndex = 1;
|
InnerSplitContainer.TabIndex = 1;
|
||||||
@@ -107,102 +98,13 @@ partial class MainViewForm
|
|||||||
TypesListBox.TabIndex = 0;
|
TypesListBox.TabIndex = 0;
|
||||||
TypesListBox.SelectedIndexChanged += TypesListBox_SelectedIndexChanged;
|
TypesListBox.SelectedIndexChanged += TypesListBox_SelectedIndexChanged;
|
||||||
//
|
//
|
||||||
// EntityGridView
|
// EntityView
|
||||||
//
|
//
|
||||||
EntityGridView.AllowUserToAddRows = false;
|
DatabaseViewer.Dock = DockStyle.Fill;
|
||||||
EntityGridView.AllowUserToDeleteRows = false;
|
DatabaseViewer.Location = new Point(0, 0);
|
||||||
EntityGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
|
DatabaseViewer.Name = "DatabaseViewer";
|
||||||
EntityGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
DatabaseViewer.Size = new Size(254, 582);
|
||||||
EntityGridView.Dock = DockStyle.Fill;
|
DatabaseViewer.TabIndex = 0;
|
||||||
EntityGridView.Location = new Point(0, 53);
|
|
||||||
EntityGridView.MultiSelect = false;
|
|
||||||
EntityGridView.Name = "EntityGridView";
|
|
||||||
EntityGridView.ReadOnly = true;
|
|
||||||
EntityGridView.RowHeadersVisible = false;
|
|
||||||
EntityGridView.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders;
|
|
||||||
EntityGridView.ShowEditingIcon = false;
|
|
||||||
EntityGridView.Size = new Size(254, 529);
|
|
||||||
EntityGridView.TabIndex = 0;
|
|
||||||
EntityGridView.RowStateChanged += EntityGridView_RowStateChanged;
|
|
||||||
//
|
|
||||||
// PaginationPagel
|
|
||||||
//
|
|
||||||
PaginationPagel.Controls.Add(PageTextBox);
|
|
||||||
PaginationPagel.Controls.Add(PaginationLabel);
|
|
||||||
PaginationPagel.Controls.Add(LastPageButton);
|
|
||||||
PaginationPagel.Controls.Add(NextPageButton);
|
|
||||||
PaginationPagel.Controls.Add(PrevPageButton);
|
|
||||||
PaginationPagel.Controls.Add(FirstPageButton);
|
|
||||||
PaginationPagel.Dock = DockStyle.Top;
|
|
||||||
PaginationPagel.Location = new Point(0, 0);
|
|
||||||
PaginationPagel.Name = "PaginationPagel";
|
|
||||||
PaginationPagel.Size = new Size(254, 53);
|
|
||||||
PaginationPagel.TabIndex = 1;
|
|
||||||
//
|
|
||||||
// PageTextBox
|
|
||||||
//
|
|
||||||
PageTextBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
|
|
||||||
PageTextBox.Location = new Point(81, 4);
|
|
||||||
PageTextBox.Name = "PageTextBox";
|
|
||||||
PageTextBox.Size = new Size(92, 23);
|
|
||||||
PageTextBox.TabIndex = 8;
|
|
||||||
PageTextBox.Text = "1";
|
|
||||||
PageTextBox.TextAlign = HorizontalAlignment.Center;
|
|
||||||
PageTextBox.KeyPress += PageTextBox_KeyPress;
|
|
||||||
//
|
|
||||||
// PaginationLabel
|
|
||||||
//
|
|
||||||
PaginationLabel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
|
|
||||||
PaginationLabel.BorderStyle = BorderStyle.None;
|
|
||||||
PaginationLabel.Location = new Point(3, 31);
|
|
||||||
PaginationLabel.Name = "PaginationLabel";
|
|
||||||
PaginationLabel.ReadOnly = true;
|
|
||||||
PaginationLabel.Size = new Size(248, 16);
|
|
||||||
PaginationLabel.TabIndex = 7;
|
|
||||||
PaginationLabel.Text = "Всего";
|
|
||||||
PaginationLabel.TextAlign = HorizontalAlignment.Center;
|
|
||||||
//
|
|
||||||
// LastPageButton
|
|
||||||
//
|
|
||||||
LastPageButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
|
|
||||||
LastPageButton.Location = new Point(218, 3);
|
|
||||||
LastPageButton.Name = "LastPageButton";
|
|
||||||
LastPageButton.Size = new Size(33, 23);
|
|
||||||
LastPageButton.TabIndex = 3;
|
|
||||||
LastPageButton.Text = ">>";
|
|
||||||
LastPageButton.UseVisualStyleBackColor = true;
|
|
||||||
LastPageButton.Click += LastPageButton_Click;
|
|
||||||
//
|
|
||||||
// NextPageButton
|
|
||||||
//
|
|
||||||
NextPageButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
|
|
||||||
NextPageButton.Location = new Point(179, 3);
|
|
||||||
NextPageButton.Name = "NextPageButton";
|
|
||||||
NextPageButton.Size = new Size(33, 23);
|
|
||||||
NextPageButton.TabIndex = 2;
|
|
||||||
NextPageButton.Text = ">";
|
|
||||||
NextPageButton.UseVisualStyleBackColor = true;
|
|
||||||
NextPageButton.Click += NextPageButton_Click;
|
|
||||||
//
|
|
||||||
// PrevPageButton
|
|
||||||
//
|
|
||||||
PrevPageButton.Location = new Point(42, 3);
|
|
||||||
PrevPageButton.Name = "PrevPageButton";
|
|
||||||
PrevPageButton.Size = new Size(33, 23);
|
|
||||||
PrevPageButton.TabIndex = 1;
|
|
||||||
PrevPageButton.Text = "<";
|
|
||||||
PrevPageButton.UseVisualStyleBackColor = true;
|
|
||||||
PrevPageButton.Click += PrevPageButton_Click;
|
|
||||||
//
|
|
||||||
// FirstPageButton
|
|
||||||
//
|
|
||||||
FirstPageButton.Location = new Point(3, 3);
|
|
||||||
FirstPageButton.Name = "FirstPageButton";
|
|
||||||
FirstPageButton.Size = new Size(33, 23);
|
|
||||||
FirstPageButton.TabIndex = 0;
|
|
||||||
FirstPageButton.Text = "<<";
|
|
||||||
FirstPageButton.UseVisualStyleBackColor = true;
|
|
||||||
FirstPageButton.Click += FirstPageButton_Click;
|
|
||||||
//
|
//
|
||||||
// ResultSplitContainer
|
// ResultSplitContainer
|
||||||
//
|
//
|
||||||
@@ -212,7 +114,7 @@ partial class MainViewForm
|
|||||||
//
|
//
|
||||||
// ResultSplitContainer.Panel1
|
// ResultSplitContainer.Panel1
|
||||||
//
|
//
|
||||||
ResultSplitContainer.Panel1.Controls.Add(EntityTreeView);
|
ResultSplitContainer.Panel1.Controls.Add(JsonWebView);
|
||||||
//
|
//
|
||||||
// ResultSplitContainer.Panel2
|
// ResultSplitContainer.Panel2
|
||||||
//
|
//
|
||||||
@@ -221,13 +123,19 @@ partial class MainViewForm
|
|||||||
ResultSplitContainer.SplitterDistance = 467;
|
ResultSplitContainer.SplitterDistance = 467;
|
||||||
ResultSplitContainer.TabIndex = 1;
|
ResultSplitContainer.TabIndex = 1;
|
||||||
//
|
//
|
||||||
// EntityTreeView
|
// JsonWebView
|
||||||
//
|
//
|
||||||
EntityTreeView.Dock = DockStyle.Fill;
|
JsonWebView.AllowExternalDrop = true;
|
||||||
EntityTreeView.Location = new Point(0, 0);
|
JsonWebView.CreationProperties = null;
|
||||||
EntityTreeView.Name = "EntityTreeView";
|
JsonWebView.DefaultBackgroundColor = Color.White;
|
||||||
EntityTreeView.Size = new Size(467, 688);
|
JsonWebView.Dock = DockStyle.Fill;
|
||||||
EntityTreeView.TabIndex = 0;
|
JsonWebView.Location = new Point(0, 0);
|
||||||
|
JsonWebView.Name = "JsonWebView";
|
||||||
|
JsonWebView.Size = new Size(467, 688);
|
||||||
|
JsonWebView.TabIndex = 0;
|
||||||
|
JsonWebView.Visible = false;
|
||||||
|
JsonWebView.ZoomFactor = 1D;
|
||||||
|
JsonWebView.CoreWebView2InitializationCompleted += JsonWebView_CoreWebView2InitializationCompleted;
|
||||||
//
|
//
|
||||||
// DescriptionTextBox
|
// DescriptionTextBox
|
||||||
//
|
//
|
||||||
@@ -256,14 +164,12 @@ partial class MainViewForm
|
|||||||
InnerSplitContainer.Panel2.ResumeLayout(false);
|
InnerSplitContainer.Panel2.ResumeLayout(false);
|
||||||
((System.ComponentModel.ISupportInitialize) InnerSplitContainer).EndInit();
|
((System.ComponentModel.ISupportInitialize) InnerSplitContainer).EndInit();
|
||||||
InnerSplitContainer.ResumeLayout(false);
|
InnerSplitContainer.ResumeLayout(false);
|
||||||
((System.ComponentModel.ISupportInitialize) EntityGridView).EndInit();
|
|
||||||
PaginationPagel.ResumeLayout(false);
|
|
||||||
PaginationPagel.PerformLayout();
|
|
||||||
ResultSplitContainer.Panel1.ResumeLayout(false);
|
ResultSplitContainer.Panel1.ResumeLayout(false);
|
||||||
ResultSplitContainer.Panel2.ResumeLayout(false);
|
ResultSplitContainer.Panel2.ResumeLayout(false);
|
||||||
ResultSplitContainer.Panel2.PerformLayout();
|
ResultSplitContainer.Panel2.PerformLayout();
|
||||||
((System.ComponentModel.ISupportInitialize) ResultSplitContainer).EndInit();
|
((System.ComponentModel.ISupportInitialize) ResultSplitContainer).EndInit();
|
||||||
ResultSplitContainer.ResumeLayout(false);
|
ResultSplitContainer.ResumeLayout(false);
|
||||||
|
((System.ComponentModel.ISupportInitialize) JsonWebView).EndInit();
|
||||||
ResumeLayout(false);
|
ResumeLayout(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,15 +178,8 @@ partial class MainViewForm
|
|||||||
private SplitContainer RootSplitContainer;
|
private SplitContainer RootSplitContainer;
|
||||||
private SplitContainer InnerSplitContainer;
|
private SplitContainer InnerSplitContainer;
|
||||||
private ListBox TypesListBox;
|
private ListBox TypesListBox;
|
||||||
private DataGridView EntityGridView;
|
|
||||||
private TreeView EntityTreeView;
|
|
||||||
private SplitContainer ResultSplitContainer;
|
private SplitContainer ResultSplitContainer;
|
||||||
private TextBox DescriptionTextBox;
|
private TextBox DescriptionTextBox;
|
||||||
private Panel PaginationPagel;
|
private Microsoft.Web.WebView2.WinForms.WebView2 JsonWebView;
|
||||||
private Button LastPageButton;
|
private DatabaseViewerControl DatabaseViewer;
|
||||||
private Button NextPageButton;
|
|
||||||
private Button PrevPageButton;
|
|
||||||
private Button FirstPageButton;
|
|
||||||
private TextBox PageTextBox;
|
|
||||||
private TextBox PaginationLabel;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-249
@@ -1,13 +1,12 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Newtonsoft.Json.Serialization;
|
using Newtonsoft.Json.Serialization;
|
||||||
using Pf2eModel;
|
using Pf2eModel;
|
||||||
using Pf2eModel.Model;
|
using Pf2eModel.Model;
|
||||||
using Pf2eModel.Model.Base;
|
using Pf2eModel.Model.Base;
|
||||||
using Pf2eModel.Model.Common.I18n;
|
using Pf2eModel.Model.Common.I18n;
|
||||||
using Pf2eModel.Model.Enum;
|
using Pf2eModel.Model.Enum;
|
||||||
|
using Pf2eViewer.Converters;
|
||||||
|
|
||||||
namespace Pf2eViewer;
|
namespace Pf2eViewer;
|
||||||
|
|
||||||
@@ -15,12 +14,22 @@ public partial class MainViewForm : Form
|
|||||||
{
|
{
|
||||||
public Pf2eDbContext Context = new();
|
public Pf2eDbContext Context = new();
|
||||||
|
|
||||||
|
public readonly string JsonViewerHtml;
|
||||||
|
|
||||||
|
public readonly EntityView Viewer;
|
||||||
|
|
||||||
public MainViewForm()
|
public MainViewForm()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Reset();
|
|
||||||
|
|
||||||
EntityGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
_ = new DarkModeCS(this) { ColorMode = DarkModeCS.DisplayMode.SystemDefault };
|
||||||
|
|
||||||
|
using StreamReader reader = new("Resources/json-viewer.html");
|
||||||
|
JsonViewerHtml = reader.ReadToEnd();
|
||||||
|
|
||||||
|
DatabaseViewer.EntityChange += DatabaseViewer_EntityChange;
|
||||||
|
|
||||||
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
@@ -28,55 +37,41 @@ public partial class MainViewForm : Form
|
|||||||
Context.Dispose();
|
Context.Dispose();
|
||||||
Context = new();
|
Context = new();
|
||||||
|
|
||||||
TypesListBox.DataSource = Context.Entities.Select(e => e.Type).Distinct().ToList();
|
TypesListBox.DataSource = Context
|
||||||
|
.Entities.Select(e => e.Type)
|
||||||
|
.Distinct()
|
||||||
|
.OrderBy(t => t.ToString())
|
||||||
|
.ToList();
|
||||||
TypesListBox.SelectedIndex = 0;
|
TypesListBox.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public const int PerPage = 30;
|
private void ToggleFreeze(bool state)
|
||||||
|
|
||||||
public int Count;
|
|
||||||
|
|
||||||
public int Page
|
|
||||||
{
|
{
|
||||||
get => Convert.ToInt32(PageTextBox.Text);
|
// EntityGridView.Visible = state;
|
||||||
set
|
// JsonWebView.Visible = state;
|
||||||
{
|
|
||||||
PageTextBox.Text = value.ToString();
|
|
||||||
UpdateTreeView();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int MaxPage => Convert.ToInt32(Math.Ceiling(1.0 * Count / PerPage));
|
private void DatabaseViewer_EntityChange(EntityView newEntity)
|
||||||
|
|
||||||
private void UpdateTreeView()
|
|
||||||
{
|
{
|
||||||
EntityTreeView.Nodes.Clear();
|
JsonSerializerSettings settings = new()
|
||||||
EntityType type = (EntityType)TypesListBox.SelectedItem!;
|
|
||||||
|
|
||||||
Count = Context.Entities.Count(e => e.Type == type);
|
|
||||||
|
|
||||||
if (Page < 1 || Page > MaxPage)
|
|
||||||
{
|
{
|
||||||
Page = Math.Min(MaxPage, Math.Max(1, Page));
|
Converters =
|
||||||
return;
|
[
|
||||||
}
|
new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() },
|
||||||
|
new EntityConverter(),
|
||||||
|
new LocaleStringConverter(),
|
||||||
|
],
|
||||||
|
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
|
||||||
|
};
|
||||||
|
|
||||||
EntityGridView.DataSource = Context
|
string result = JsonConvert.SerializeObject(newEntity.Entity, settings);
|
||||||
.Entities.Where(e => e.Type == (EntityType)TypesListBox.SelectedItem)
|
string subResult = JsonConvert.SerializeObject(newEntity.SubEntity, settings);
|
||||||
.OrderBy(e => e.Id)
|
|
||||||
.Select(e => new EntityGridRow(e))
|
|
||||||
.Skip((Page - 1) * PerPage)
|
|
||||||
.Take(PerPage)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
EntityGridView.Rows[0].Selected = true;
|
string json = result[..^1] + $",\"SubEntity\":{subResult}}}";
|
||||||
|
|
||||||
PaginationLabel.Text = $"Всего: {Count} объектов, {MaxPage} страниц";
|
RenderJson(json);
|
||||||
|
|
||||||
FirstPageButton.Enabled = Page > 1;
|
DescriptionTextBox.Text = newEntity.Entity!.Description;
|
||||||
PrevPageButton.Enabled = Page > 1;
|
|
||||||
NextPageButton.Enabled = Page < MaxPage;
|
|
||||||
LastPageButton.Enabled = Page < MaxPage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TypesListBox_SelectedIndexChanged(object sender, EventArgs _)
|
private void TypesListBox_SelectedIndexChanged(object sender, EventArgs _)
|
||||||
@@ -86,223 +81,28 @@ public partial class MainViewForm : Form
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Page = 1;
|
DatabaseViewer.Type = (EntityType)TypesListBox.SelectedItem;
|
||||||
|
// Viewer.Page = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FirstPageButton_Click(object sender, EventArgs e)
|
public void RenderJson(string json)
|
||||||
{
|
{
|
||||||
Page = 1;
|
if (JsonWebView.CoreWebView2 == null)
|
||||||
}
|
|
||||||
|
|
||||||
private void PrevPageButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Page--;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NextPageButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Page++;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LastPageButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Page = MaxPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PageTextBox_KeyPress(object sender, KeyPressEventArgs e)
|
|
||||||
{
|
|
||||||
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
|
|
||||||
{
|
{
|
||||||
e.Handled = true;
|
JsonWebView.EnsureCoreWebView2Async();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.KeyChar == (char)Keys.Return)
|
string html = JsonViewerHtml.Replace("{JSON}", json);
|
||||||
{
|
JsonWebView.CoreWebView2.NavigateToString(html);
|
||||||
UpdateTreeView();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EntityGridView_RowStateChanged(
|
private void JsonWebView_CoreWebView2InitializationCompleted(
|
||||||
object sender,
|
object sender,
|
||||||
DataGridViewRowStateChangedEventArgs e
|
Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int rowsCount = EntityGridView.SelectedRows.Count;
|
JsonWebView.Visible = true;
|
||||||
if (rowsCount is 0 or > 1)
|
DatabaseViewer_EntityChange(DatabaseViewer.CurrentEntity);
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataGridViewRow row = EntityGridView.SelectedRows[0];
|
|
||||||
|
|
||||||
EntityGridRow data = (EntityGridRow)row.DataBoundItem;
|
|
||||||
|
|
||||||
ViewEntity(data.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ViewEntity(int id)
|
|
||||||
{
|
|
||||||
EntityTreeView.Nodes.Clear();
|
|
||||||
|
|
||||||
Entity? entity = Context
|
|
||||||
.Entities.Where(e => e.Id == id && e.Type == (EntityType)TypesListBox.SelectedItem!)
|
|
||||||
.Include(e => e.Sources)
|
|
||||||
.ThenInclude(s => s.Source)
|
|
||||||
.Include(e => e.Keywords)
|
|
||||||
.Include(e => e.Externals)
|
|
||||||
.ThenInclude(x => x.Target)
|
|
||||||
.Include(e => e.Traits)
|
|
||||||
.ThenInclude(t => t.Entity)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (entity == null)
|
|
||||||
{
|
|
||||||
DescriptionTextBox.Text = "Not found";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string json = SerializeEntity(entity);
|
|
||||||
|
|
||||||
JsonToTreeview(EntityTreeView, json, "Entity");
|
|
||||||
|
|
||||||
DescriptionTextBox.Text = entity.Description.Replace("\\r", "").Replace("\\n", "\\r\\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public string SerializeEntity(Entity entity)
|
|
||||||
{
|
|
||||||
JsonSerializerSettings settings = new()
|
|
||||||
{
|
|
||||||
Converters =
|
|
||||||
[
|
|
||||||
new EntityConverter(),
|
|
||||||
new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() },
|
|
||||||
],
|
|
||||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
|
|
||||||
};
|
|
||||||
|
|
||||||
string result = JsonConvert.SerializeObject(entity, settings);
|
|
||||||
|
|
||||||
Type type = EntityOfTypeAttribute.Resolve(entity);
|
|
||||||
string subResult = JsonConvert.SerializeObject(ResolveSubEntity(entity), settings);
|
|
||||||
|
|
||||||
return result[..^1] + $",\"SubEntity\":{subResult}}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEntity? ResolveSubEntity(Entity entity)
|
|
||||||
{
|
|
||||||
switch (entity.Type)
|
|
||||||
{
|
|
||||||
case EntityType.Ancestry:
|
|
||||||
return Context
|
|
||||||
.Ancestries.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)
|
|
||||||
.Include(b => b.BackgroundSkills)
|
|
||||||
.ThenInclude(t => t.Training)
|
|
||||||
.Include(b => b.BackgroundItems)
|
|
||||||
.FirstOrDefault(e => e.Id == entity.Id);
|
|
||||||
|
|
||||||
case EntityType.Class:
|
|
||||||
return Context
|
|
||||||
.Classes.Include(c => c.ClassKeyAbilities)
|
|
||||||
.Include(c => c.ClassTrainings)
|
|
||||||
.ThenInclude(t => t.Training)
|
|
||||||
.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void JsonToTreeview(TreeView treeView, string jsonString, string rootName)
|
|
||||||
{
|
|
||||||
object json = jsonString.StartsWith('[')
|
|
||||||
? JArray.Parse(jsonString)
|
|
||||||
: JObject.Parse(jsonString);
|
|
||||||
|
|
||||||
treeView.Nodes.Clear();
|
|
||||||
foreach (TreeNode node in Element2TreeNode(json, rootName).Nodes)
|
|
||||||
{
|
|
||||||
treeView.Nodes.Add(node);
|
|
||||||
}
|
|
||||||
treeView.ExpandAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TreeNode Element2TreeNode(object element, string text = "")
|
|
||||||
{
|
|
||||||
List<TreeNode> subNodes = [];
|
|
||||||
|
|
||||||
switch (element.GetType().Name)
|
|
||||||
{
|
|
||||||
case "JObject":
|
|
||||||
JObject jObject = (JObject)element;
|
|
||||||
foreach (KeyValuePair<string, JToken> token in jObject)
|
|
||||||
{
|
|
||||||
subNodes.Add(Element2TreeNode(token.Value, token.Key));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "JArray":
|
|
||||||
JArray jArray = (JArray)element;
|
|
||||||
int i = 0;
|
|
||||||
subNodes.AddRange(jArray.Select(token => Element2TreeNode(token, $"[{i++}]")));
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
text += ": []";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "JValue":
|
|
||||||
JValue jValue = (JValue)element;
|
|
||||||
text += $": ({jValue.Type}) {jValue}";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Exception(
|
|
||||||
"clsJSON2Treeview can't interpret object:" + element.GetType().Name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
TreeNode treeNode = new(text);
|
|
||||||
|
|
||||||
if (subNodes.Count > 0)
|
|
||||||
{
|
|
||||||
treeNode.Nodes.AddRange(
|
|
||||||
subNodes.OrderBy(node => node.Nodes.Count > 0 ? 1 : 0).ToArray()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return treeNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class EntityGridRow(Entity e)
|
|
||||||
{
|
|
||||||
public int Id { get; set; } = e.Id;
|
|
||||||
public string Name { get; set; } = e.Name[LocaleType.English];
|
|
||||||
public EntityRarity Rarity { get; set; } = e.Rarity;
|
|
||||||
|
|
||||||
private readonly Entity _e = e;
|
|
||||||
|
|
||||||
public Entity GetEntity() => _e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3179.45" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -15,4 +16,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Properties\" />
|
<Folder Include="Properties\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Resources\json-viewer.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>JSON Viewer</title>
|
||||||
|
<script src="https://pfau-software.de/json-viewer/dist/iife/index.js"></script>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<andypf-json-viewer indent="4"
|
||||||
|
expanded="true"
|
||||||
|
theme="classic-dark"
|
||||||
|
expand-icon-type="square"
|
||||||
|
show-data-types="false"
|
||||||
|
show-toolbar="false"
|
||||||
|
show-copy="false"
|
||||||
|
show-size="true">
|
||||||
|
{JSON}
|
||||||
|
</andypf-json-viewer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user