Первая версия обработчиков
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Slugify;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder
|
||||
{
|
||||
internal abstract class AbstractEntityProcessor(JObject input) : AbstractProcessor(input)
|
||||
{
|
||||
public abstract string DbType { get; }
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
Add("name", "name");
|
||||
Add("img", "img");
|
||||
Add("description", "system.description.value");
|
||||
Add("description_gm", "system.description.gm");
|
||||
Add("type", DbType);
|
||||
Add("rarity", "system.traits.rarity");
|
||||
|
||||
SlugHelper sh = new();
|
||||
Data.Add("slug", sh.GenerateSlug(Data["name"]?.ToString() ?? throw new NullReferenceException("'name' is null")));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Npgsql;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder
|
||||
{
|
||||
internal abstract class AbstractProcessor(JObject input)
|
||||
{
|
||||
public readonly JObject Input = input;
|
||||
|
||||
public Pf2eDatabase Database = Pf2eDatabase.Instance;
|
||||
|
||||
public DataBuilderHelper Helper = DataBuilderHelper.Instance;
|
||||
|
||||
public abstract string Table { get; }
|
||||
|
||||
public Dictionary<string, object?> Data = [];
|
||||
|
||||
protected void Add(string key, string path)
|
||||
{
|
||||
Data.Add(key, DataBuilderHelper.JsonGet(Input, path));
|
||||
}
|
||||
|
||||
public abstract void Process();
|
||||
|
||||
public int Save()
|
||||
{
|
||||
return Helper.Insert(Table, Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Npgsql;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder
|
||||
{
|
||||
internal class DataBuilderHelper
|
||||
{
|
||||
public Pf2eDatabase Database = Pf2eDatabase.Instance;
|
||||
|
||||
private DataBuilderHelper()
|
||||
{
|
||||
}
|
||||
|
||||
public NpgsqlCommand PrepareInsert(string table, Dictionary<string, object?> data, bool returnId)
|
||||
{
|
||||
List<string> columns = [];
|
||||
List<string> patterns = [];
|
||||
|
||||
foreach (var key in data.Keys)
|
||||
{
|
||||
columns.Add(key);
|
||||
patterns.Add($":{key.ToUpper()}");
|
||||
}
|
||||
|
||||
string dml = $"INSERT INTO {table} (\"{string.Join("\", \"", columns)}\") VALUES ({string.Join(", ", patterns)})" + (returnId ? " RETURNING id" : "");
|
||||
|
||||
NpgsqlCommand cmd = Database.GetCommand(dml);
|
||||
foreach (var kvp in data)
|
||||
{
|
||||
cmd.Parameters.AddWithValue(":" + kvp.Key.ToUpper(), kvp.Value ?? DBNull.Value);
|
||||
}
|
||||
|
||||
Console.WriteLine(cmd.CommandText);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
public int Insert(string table, Dictionary<string, object?> data)
|
||||
{
|
||||
var cmd = PrepareInsert(table, data, true);
|
||||
return (int)(cmd.ExecuteScalar() ?? throw new Exception("Not a number"));
|
||||
}
|
||||
|
||||
public void InsertBlind(string table, Dictionary<string, object?> data)
|
||||
{
|
||||
var cmd = PrepareInsert(table, data, false);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
public static object? JsonGet(JObject root, string path)
|
||||
{
|
||||
var token = root.SelectToken(path);
|
||||
|
||||
if (token == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (token.Type == JTokenType.String)
|
||||
{
|
||||
return token.ToString();
|
||||
}
|
||||
else if (token.Type == JTokenType.Integer)
|
||||
{
|
||||
return token.ToObject<int>();
|
||||
}
|
||||
else if (token.Type == JTokenType.Float)
|
||||
{
|
||||
return token.ToObject<float>();
|
||||
}
|
||||
else if (token.Type == JTokenType.Boolean)
|
||||
{
|
||||
return token.ToObject<bool>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return token.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public static DataBuilderHelper Instance = new();
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
using Konsole;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.Compendium;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder
|
||||
{
|
||||
internal class PF2eFoundryDataBuilder
|
||||
{
|
||||
public Pf2eDatabase Database = Pf2eDatabase.Instance;
|
||||
|
||||
/// <summary>
|
||||
/// Загрузчик данных.
|
||||
/// </summary>
|
||||
public readonly CompendiumLoader Loader;
|
||||
|
||||
/// <summary>
|
||||
/// Коллекция папок компендиума.
|
||||
/// </summary>
|
||||
public CompendiumFolderCollection Collection => Loader.Collection;
|
||||
|
||||
public Dictionary<string, ConstructorInfo> Processors = [];
|
||||
|
||||
public PF2eFoundryDataBuilder(CompendiumLoader loader)
|
||||
{
|
||||
Loader = loader;
|
||||
PrepareProcessors();
|
||||
}
|
||||
|
||||
public void PrepareProcessors()
|
||||
{
|
||||
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
|
||||
{
|
||||
if (type.GetCustomAttributes(typeof(Pf2eTypeProcessor), true).Length > 0)
|
||||
{
|
||||
var attribute = type.GetCustomAttribute<Pf2eTypeProcessor>();
|
||||
Processors.Add(attribute!.Type, type.GetConstructor(new[] { typeof(JObject) })!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AbstractProcessor? GetProcessor(string type, JObject input)
|
||||
{
|
||||
if (Processors.TryGetValue(type, out var constructor))
|
||||
{
|
||||
return (AbstractProcessor)constructor.Invoke([input]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void TruncateTables()
|
||||
{
|
||||
Console.WriteLine("Truncating all old data...");
|
||||
|
||||
Database.ExecuteCommand($"SELECT f_truncate_tables();");
|
||||
|
||||
Console.WriteLine("Truncation completed!");
|
||||
}
|
||||
|
||||
public void Build()
|
||||
{
|
||||
Console.WriteLine("Building data...");
|
||||
|
||||
var bar = new ProgressBar(Loader.ItemCount);
|
||||
var i = 0;
|
||||
|
||||
foreach (var entry in Loader.Enrties())
|
||||
{
|
||||
bar.Refresh(i++, $"{entry.Folder.Name}/{entry.File.Name}");
|
||||
|
||||
var processor = GetProcessor($"{entry.Folder.Type}.{entry.Type}", entry.Json);
|
||||
if (processor is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
processor.Process();
|
||||
processor.Save();
|
||||
}
|
||||
|
||||
bar.Refresh(Loader.ItemCount, "Done!");
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
internal class Pf2eTypeProcessor(string type) : Attribute
|
||||
{
|
||||
public readonly string Type = type;
|
||||
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Pf2eDataScrapper.Importers.Implementations.Pf2eFoundry.DataBuilder.Processors
|
||||
{
|
||||
[Pf2eTypeProcessor("Item.condition")]
|
||||
internal class ConditionProcessor(JObject input) : AbstractEntityProcessor(input)
|
||||
{
|
||||
public override string Table => "condition";
|
||||
|
||||
public override string DbType => "condition";
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
base.Process();
|
||||
|
||||
Add("group", "system.group");
|
||||
|
||||
JObject extra = new()
|
||||
{
|
||||
{ "duration", Input.SelectToken("duration") },
|
||||
{ "overrides", Input.SelectToken("overrides") },
|
||||
{ "references", Input.SelectToken("references") },
|
||||
{ "value", Input.SelectToken("value") }
|
||||
};
|
||||
|
||||
Data.Add("extra", extra.ToString(Newtonsoft.Json.Formatting.Indented));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user