Отчистка кода

This commit is contained in:
2025-04-24 17:58:58 +04:00
parent 31ad99ade5
commit cc7e97b6ff
20 changed files with 1972 additions and 1562 deletions
@@ -1,35 +1,42 @@
using Pf2eModel.Model.Enum;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
public static class AonprdEnumResolver
{
private static readonly ICollection<Solver> Solvers = [
new Solver<SourceCategory>(new()
{
{ "Rulebooks", SourceCategory.Rulebooks },
{ "Adventure Paths", SourceCategory.AdventurePaths },
{ "Lost Omens", SourceCategory.LostOmens },
{ "Adventures", SourceCategory.Adventures },
{ "Comics", SourceCategory.Comics },
{ "Blog Posts", SourceCategory.BlogPosts },
{ "Society", SourceCategory.Society },
}),
new Solver<AncestryVision>(new()
{
{ "Low-Light Vision", AncestryVision.LowLightVision },
{ "Darkvision", AncestryVision.DarkVision },
}),
new Solver<AttributeValues>(new()
{
{ "Consitution", AttributeValues.Constitution },
{ "Other", AttributeValues.Free },
{ "other", AttributeValues.Free },
})
private static readonly ICollection<Solver> Solvers =
[
new Solver<SourceCategory>(
new()
{
{ "Rulebooks", SourceCategory.Rulebooks },
{ "Adventure Paths", SourceCategory.AdventurePaths },
{ "Lost Omens", SourceCategory.LostOmens },
{ "Adventures", SourceCategory.Adventures },
{ "Comics", SourceCategory.Comics },
{ "Blog Posts", SourceCategory.BlogPosts },
{ "Society", SourceCategory.Society },
}
),
new Solver<AncestryVision>(
new()
{
{ "Low-Light Vision", AncestryVision.LowLightVision },
{ "Darkvision", AncestryVision.DarkVision },
}
),
new Solver<AttributeValues>(
new()
{
{ "Consitution", AttributeValues.Constitution },
{ "Other", AttributeValues.Free },
{ "other", AttributeValues.Free },
}
),
];
public static T Resolve<T>(string value) where T : Enum
public static T Resolve<T>(string value)
where T : Enum
{
Type type = typeof(T);
@@ -40,9 +47,11 @@ public static class AonprdEnumResolver
throw new EnumResolverEnumUnknownException(type);
}
Solver<T> tSolver = (Solver<T>) solver;
Solver<T> tSolver = (Solver<T>)solver;
return tSolver.Data.TryGetValue(value, out T? data) ? data : throw new EnumResolverValueUnknownException(type, value);
return tSolver.Data.TryGetValue(value, out T? data)
? data
: throw new EnumResolverValueUnknownException(type, value);
}
private abstract class Solver
@@ -50,14 +59,16 @@ public static class AonprdEnumResolver
public abstract Type Type { get; }
}
private class Solver<T>(Dictionary<string, T> data) : Solver where T : Enum
private class Solver<T>(Dictionary<string, T> data) : Solver
where T : Enum
{
public override Type Type { get; } = typeof(T);
public Dictionary<string, T> Data { get; } = data;
}
public class EnumResolverEnumUnknownException(Type t) : Exception($"Can't resolve type '{t.FullName}': Solver not defined");
public class EnumResolverValueUnknownException(Type t, string value) : Exception($"Can't resolve type '{t.FullName}': Value '{value}' is not matched");
public class EnumResolverEnumUnknownException(Type t)
: Exception($"Can't resolve type '{t.FullName}': Solver not defined");
public class EnumResolverValueUnknownException(Type t, string value)
: Exception($"Can't resolve type '{t.FullName}': Value '{value}' is not matched");
}
@@ -1,4 +1,6 @@
using LinqToDB.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@@ -10,10 +12,6 @@ using Pf2eModel.Model.Base.Targets;
using Pf2eModel.Model.Common.I18n;
using Pf2eModel.Model.Enum;
using Pf2eModel.Model.Structure;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors;
@@ -32,7 +30,7 @@ internal abstract partial class AbstractProcessor(AonprdProcessorInput input)
public abstract IEntity Object { get; }
protected abstract void Add();
public virtual void Process()
{
if (Input.GetOptional<JArray>("remaster_id") is not null)
@@ -57,9 +55,11 @@ internal abstract partial class AbstractProcessor(AonprdProcessorInput input)
Context.SaveChanges();
}
protected string AddedDescription(string path) => $"\r\n\r\n========== [{path}] ==========\r\n\r\n{Input.GetOptional<string>(path) ?? ""}";
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 string AddedDescription(string[] paths) =>
string.Join("", paths.Select(AddedDescription));
protected virtual string GetDescription() => Input.GetRequired<string>("markdown");
@@ -130,7 +130,7 @@ internal abstract partial class AbstractProcessor(AonprdProcessorInput input)
Entity = Entity,
Source = source,
Suffix = ((match?.Captures.Count > 0) ? match?.Captures[0]?.Value : "") ?? "",
IsRemaster = Input.GetOptional<JArray>("legacy_id") is not null
IsRemaster = Input.GetOptional<JArray>("legacy_id") is not null,
};
Context.EntitySources.Add(entitySource);
@@ -140,7 +140,9 @@ internal abstract partial class AbstractProcessor(AonprdProcessorInput input)
{
if (AonprdTarget is null)
{
AonprdTarget = Context.ExternalTargets.FirstOrDefault(t => t.Name == AonprdImporter.SourceName);
AonprdTarget = Context.ExternalTargets.FirstOrDefault(t =>
t.Name == AonprdImporter.SourceName
);
AonprdTarget ??= new()
{
@@ -155,7 +157,7 @@ internal abstract partial class AbstractProcessor(AonprdProcessorInput input)
Entity = Entity,
Target = AonprdTarget,
Suffix = Input.GetRequired<string>("url"),
Md5 = Md5(Input.Input.ToString())
Md5 = Md5(Input.Input.ToString()),
};
Context.EntityExternals.Add(external);
}
@@ -170,13 +172,13 @@ internal abstract partial class AbstractProcessor(AonprdProcessorInput input)
}
IEnumerable<string> names = traitsJson.ToArray().Select(jToken => jToken.ToString());
List<Entity> traitEntities = Context.Traits
.Select(t => t.Entity)
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)
List<Trait> traits = Context
.Traits.Include(t => t.Entity)
.Where(t => traitEntities.Contains(t.Entity))
.ToList();
@@ -238,7 +240,9 @@ internal abstract partial class AbstractProcessor(AonprdProcessorInput input)
[GeneratedRegex(@"^\[.*?\]\(.*?\)\s+(.*)$")]
private static partial Regex SourceSuffixRegex();
public class LegacyItemException(string name) : Exception($"Item '{name}' is linked with newer version, skipping.") { }
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}.") { }
public class SkipItemException(string name, string reason)
: Exception($"Item '{name}' is skipped, reason: {reason}.") { }
}
@@ -1,6 +1,4 @@
using Newtonsoft.Json.Linq;
using Pf2eModel.Model;
using Pf2eModel.Model.Enum;
using Pf2eModel.Model.Enum;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
@@ -17,25 +15,30 @@ internal class ActionProcessor(AonprdProcessorInput input) : AbstractProcessor(i
{
base.Process();
AonprdProcessorInput.ActionStruct action = Input.ResolveActionString(Input.GetOptional<string>("actions") ?? "");
AonprdProcessorInput.ActionStruct action = Input.ResolveActionString(
Input.GetOptional<string>("actions") ?? ""
);
Object.Actions = action.Actions;
Object.MaxActions = action.MaxActions;
Object.IsFreeAction = action.IsFreeAction;
Object.IsPassive = action.IsPassive;
Object.IsReaction = action.IsReaction;
;
;
Object.Extra = GenerateExtra("school");
}
protected override string GetDescription()
=> base.GetDescription() + AddedDescription([
"cost_markdown",
"trait_markdown",
"source_markdown",
"search_markdown",
"requirement_markdown",
"trigger_markdown",
"summary_markdown",
]);
protected override string GetDescription() =>
base.GetDescription()
+ AddedDescription(
[
"cost_markdown",
"trait_markdown",
"source_markdown",
"search_markdown",
"requirement_markdown",
"trigger_markdown",
"summary_markdown",
]
);
}
@@ -1,10 +1,8 @@
using LinqToDB;
using Newtonsoft.Json.Linq;
using Pf2eModel.Model;
using Pf2eModel.Model.Enum;
using Pf2eModel.Model.Structure;
using Pf2eModel.Model.Structure.AncestryRelation;
using System.Text.RegularExpressions;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
@@ -28,8 +26,11 @@ internal class AncestryProcessor(AonprdProcessorInput input) : AbstractProcessor
base.Process();
Object.Size = Input.GetRequired<JArray>("size").Select(t => Input.Enum<Size>(t.ToString())).ToArray();
Object.Size = Input
.GetRequired<JArray>("size")
.Select(t => Input.Enum<Size>(t.ToString()))
.ToArray();
string hp = Input.GetRequired<string>("hp_raw");
Object.Hp = Convert.ToInt32((hp != "") ? hp : "0");
@@ -46,7 +47,8 @@ internal class AncestryProcessor(AonprdProcessorInput input) : AbstractProcessor
protected void AddBoosts(string path, bool isBoost)
{
List<string> boosts = Input.GetOptional<JArray>(path)?.ToArray().Select(t => t.ToString()).ToList() ?? [];
List<string> boosts =
Input.GetOptional<JArray>(path)?.ToArray().Select(t => t.ToString()).ToList() ?? [];
if (boosts.Contains("Two free ability boosts"))
{
@@ -67,5 +69,4 @@ internal class AncestryProcessor(AonprdProcessorInput input) : AbstractProcessor
Context.AncestryBoosts.Add(ancestryBoost);
}
}
}
}
@@ -1,10 +1,5 @@
using Pf2eModel.Model.Enum;
using Pf2eModel.Model.Structure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
@@ -22,13 +17,9 @@ internal class ArchetypeProcessor(AonprdProcessorInput input) : AbstractProcesso
base.Process();
Object.Level = Input.GetOptional<int>("level");
}
protected override string GetDescription()
=> base.GetDescription() + AddedDescription([
"prerequisite_markdown",
"requirement_markdown",
"summary_markdown"
]);
protected override string GetDescription() =>
base.GetDescription()
+ AddedDescription(["prerequisite_markdown", "requirement_markdown", "summary_markdown"]);
}
@@ -1,13 +1,7 @@
using Newtonsoft.Json.Linq;
using Pf2eModel.Model;
using Pf2eModel.Model.Enum;
using Pf2eModel.Model.Structure;
using Pf2eModel.Model.Structure.BackgroundRelation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
@@ -29,22 +23,17 @@ internal class BackgroundProcessor(AonprdProcessorInput input) : AbstractProcess
BackgroundBoost boost = new()
{
Background = Object,
Attribute = Input.Enum<AttributeValues>(token.ToString())
Attribute = Input.Enum<AttributeValues>(token.ToString()),
};
Object.BackgroundBoosts.Add(boost);
Context.BackgroundBoosts.Add(boost);
}
}
protected override string GetDescription()
=> base.GetDescription() + AddedDescription([
"feat_markdown",
"summary_markdown",
"skill_markdown",
"prerequisite_markdown",
]);
protected override string GetDescription() =>
base.GetDescription()
+ AddedDescription(
["feat_markdown", "summary_markdown", "skill_markdown", "prerequisite_markdown"]
);
}
@@ -1,18 +1,11 @@
using LinqToDB;
using System.Text.RegularExpressions;
using LinqToDB;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using Pf2eModel.Model;
using Pf2eModel.Model.Common;
using Pf2eModel.Model.Enum;
using Pf2eModel.Model.Structure;
using Pf2eModel.Model.Structure.ClassRelation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
@@ -28,10 +21,11 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractProcessor(in
public override void Process()
{
base.Process();
Object.Hp = Convert.ToInt32(Input.GetRequired<string>("hp_raw"));
AttributeValues[] attributes = Input.GetRequired<JArray>("attribute")
AttributeValues[] attributes = Input
.GetRequired<JArray>("attribute")
.Select(token => Input.Enum<AttributeValues>(token.ToString()))
.ToArray();
@@ -39,18 +33,24 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractProcessor(in
{
ClassKeyAbility classKeyAbility = new ClassKeyAbility()
{
Class = Object,
Value = attribute
Class = Object,
Value = attribute,
};
Context.ClassKeyAbilities.Add(classKeyAbility);
Object.ClassKeyAbilities.Add(classKeyAbility);
}
ClassTraining[] classTrainings =
[
.. ProcessTraining(Input.GetRequired<JArray>("attack_proficiency"), TrainingType.Weapon),
.. ProcessTraining(Input.GetRequired<JArray>("defense_proficiency"), TrainingType.Armor),
.. ProcessTraining(
Input.GetRequired<JArray>("attack_proficiency"),
TrainingType.Weapon
),
.. ProcessTraining(
Input.GetRequired<JArray>("defense_proficiency"),
TrainingType.Armor
),
.. GetSkillTrainings(),
.. GetSaveTrainings(),
];
@@ -84,19 +84,22 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractProcessor(in
protected ICollection<ClassTraining> GetSkillTrainings()
{
string[] skillNames = Input.GetRequired<JArray>("skill_proficiency")
string[] skillNames = Input
.GetRequired<JArray>("skill_proficiency")
.Select(token => token.ToString())
.ToArray();
Training[] skills = Context.Trainings.Where(t => skillNames.Contains(t.Name)).ToArray();
// Training[] skills = Context.Trainings.Where(t => Pf2eDbContext.LocaleSearchArray(t.Name, skillNames)).ToArray();
return skills.Select(skill => new ClassTraining()
{
Class = Object,
Training = skill,
Stage = TrainingStage.Trained,
}).ToArray();
return skills
.Select(skill => new ClassTraining()
{
Class = Object,
Training = skill,
Stage = TrainingStage.Trained,
})
.ToArray();
}
protected ICollection<ClassTraining> ProcessTraining(JArray array, TrainingType type)
@@ -119,16 +122,13 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractProcessor(in
foreach (string part in parts)
{
Training? training = Context.Trainings
.FirstOrDefault(t => t.Name == part && t.Type == type);
Training? training = Context.Trainings.FirstOrDefault(t =>
t.Name == part && t.Type == type
);
if (training == null)
{
training = new Training()
{
Name = part,
Type = type,
};
training = new Training() { Name = part, Type = type };
Context.Trainings.Add(training);
}
@@ -137,7 +137,7 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractProcessor(in
{
Class = Object,
Training = training,
Stage = stage
Stage = stage,
};
trainings.Add(classTraining);
@@ -149,27 +149,20 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractProcessor(in
protected string[] GetTrainingString(string value)
{
if (value.StartsWith("favored weapon of your deity"))
{
return ["Favored weapon of your deity"];
}
if (value == "simple and martial weapons")
{
return ["Simple weapon", "Martial weapon"];
}
return Regex.Split(value, @"\s*(?:,|and)\s*")
.Where(s => s != "")
.Select(s => string.Concat(s[0].ToString().ToUpper(), s.AsSpan(1)))
.ToArray();
;
return value.StartsWith("favored weapon of your deity") ? ["Favored weapon of your deity"]
: value == "simple and martial weapons" ? ["Simple weapon", "Martial weapon"]
: Regex
.Split(value, @"\s*(?:,|and)\s*")
.Where(s => s != "")
.Select(s => string.Concat(s[0].ToString().ToUpper(), s.AsSpan(1)))
.ToArray();
;
}
protected ICollection<ClassTraining> GetSaveTrainings()
{
Dictionary<string, Training> result = Context.Trainings
.Where(t => t.Type == TrainingType.Save)
Dictionary<string, Training> result = Context
.Trainings.Where(t => t.Type == TrainingType.Save)
.ToDictionary(t => t.Name);
foreach (string name in new[] { "Will", "Fortitude", "Reflex", "Perception" })
@@ -179,23 +172,29 @@ internal class ClassProcessor(AonprdProcessorInput input) : AbstractProcessor(in
continue;
}
Training training = new() { Name = name, Type = (name == "Perception") ? TrainingType.Perception : TrainingType.Save };
Training training = new()
{
Name = name,
Type = (name == "Perception") ? TrainingType.Perception : TrainingType.Save,
};
result.Add(name, training);
Context.Trainings.Add(training);
}
return result.Select(pair =>
{
ClassTraining classTraining = new()
return result
.Select(pair =>
{
Class = Object,
Training = pair.Value,
Stage = Input.EnumRequired<TrainingStage>($"{pair.Key.ToLower()}_proficiency"),
};
ClassTraining classTraining = new()
{
Class = Object,
Training = pair.Value,
Stage = Input.EnumRequired<TrainingStage>($"{pair.Key.ToLower()}_proficiency"),
};
return classTraining;
}).ToList();
return classTraining;
})
.ToList();
}
protected void ProcessDependecies()
@@ -20,11 +20,13 @@ internal class FeatProcessor(AonprdProcessorInput input) : AbstractProcessor(inp
Object.Level = Input.GetRequired<int>("level");
Object.Category = (Entity.Traits.Any(t => t.Type == TraitType.Class))
? ActionCategory.ClassFeat
Object.Category = Entity.Traits.Any(t => t.Type == TraitType.Class)
? ActionCategory.ClassFeat
: ActionCategory.Unknown;
AonprdProcessorInput.ActionStruct action = Input.ResolveActionString(Input.GetOptional<string>("actions") ?? "");
AonprdProcessorInput.ActionStruct action = Input.ResolveActionString(
Input.GetOptional<string>("actions") ?? ""
);
Object.Actions = action.Actions;
Object.MaxActions = action.MaxActions;
Object.IsFreeAction = action.IsFreeAction;
@@ -39,12 +41,13 @@ internal class FeatProcessor(AonprdProcessorInput input) : AbstractProcessor(inp
"heighten_level",
"school",
"frequency"
);
);
string[] archetypeStrings = Input.GetOptional<JArray>("archetype")?.Select(t => t.ToString()).ToArray() ?? [];
string[] archetypeStrings =
Input.GetOptional<JArray>("archetype")?.Select(t => t.ToString()).ToArray() ?? [];
var archetypes = Context.Archetypes
.Where(a => Pf2eDbContext.LocaleSearchArray(a.Entity.Name, archetypeStrings))
Archetype[] archetypes = Context
.Archetypes.Where(a => Pf2eDbContext.LocaleSearchArray(a.Entity.Name, archetypeStrings))
// .Where(a => archetypeStrings.Contains(a.Entity.Name.ToString()))
.ToArray();
@@ -53,7 +56,7 @@ internal class FeatProcessor(AonprdProcessorInput input) : AbstractProcessor(inp
Object.Category = ActionCategory.Archetype;
}
foreach (var archetype in archetypes)
foreach (Archetype? archetype in archetypes)
{
Object.Archetypes.Add(archetype);
@@ -64,13 +67,16 @@ internal class FeatProcessor(AonprdProcessorInput input) : AbstractProcessor(inp
}
}
protected override string GetDescription()
=> base.GetDescription() + AddedDescription([
"cost_markdown",
"feat_markdown",
"summary_markdown",
"prerequisite_markdown",
"requirement_markdown",
"trigger_markdown"
]);
protected override string GetDescription() =>
base.GetDescription()
+ AddedDescription(
[
"cost_markdown",
"feat_markdown",
"summary_markdown",
"prerequisite_markdown",
"requirement_markdown",
"trigger_markdown",
]
);
}
@@ -1,12 +1,6 @@
using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder;
using Pf2eModel.Model;
using Pf2eModel.Model;
using Pf2eModel.Model.Base.Source;
using Pf2eModel.Model.Enum;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
@@ -15,7 +9,7 @@ internal class SourceProcessor(AonprdProcessorInput input) : AbstractProcessor(i
{
public override EntityType Type => EntityType.Unknown;
public override IEntity Object => null;
public override IEntity? Object => null;
protected override void Add() { }
@@ -1,12 +1,6 @@
using Pf2eModel.Model.Base.Source;
using Pf2eModel.Model.Enum;
using Pf2eModel.Model;
using Pf2eModel.Model;
using Pf2eModel.Model.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Pf2eModel.Model.Enum;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Processors.Types;
@@ -15,7 +9,7 @@ internal class TrainingProcessor(AonprdProcessorInput input) : AbstractProcessor
{
public override EntityType Type => EntityType.Unknown;
public override IEntity Object => null;
public override IEntity? Object => null;
protected override void Add() { }
+14 -12
View File
@@ -1,8 +1,4 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Pf2eModel.Model.Structure;
using static LinqToDB.Common.Configuration;
using static System.Runtime.InteropServices.JavaScript.JSType;
using System.Buffers;
#nullable disable
@@ -14,7 +10,8 @@ public partial class Function : Migration
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("""
migrationBuilder.Sql(
"""
CREATE OR REPLACE FUNCTION f_truncate_tables()
RETURNS void
LANGUAGE plpgsql AS
@@ -30,8 +27,10 @@ BEGIN
);
END
$func$;
""");
migrationBuilder.Sql("""
"""
);
migrationBuilder.Sql(
"""
CREATE OR REPLACE FUNCTION f_drop_tables()
RETURNS void
LANGUAGE plpgsql AS
@@ -46,8 +45,10 @@ BEGIN
);
END
$func$;
""");
migrationBuilder.Sql("""
"""
);
migrationBuilder.Sql(
"""
CREATE OR REPLACE FUNCTION f_permission_tables(_username text)
RETURNS void
LANGUAGE plpgsql AS
@@ -68,7 +69,8 @@ $func$;
"""
);
migrationBuilder.Sql("""
migrationBuilder.Sql(
"""
CREATE OR REPLACE FUNCTION locale_search(data jsonb, search_value text)
RETURNS boolean
LANGUAGE plpgsql AS
@@ -80,7 +82,8 @@ $func$;
"""
);
migrationBuilder.Sql("""
migrationBuilder.Sql(
"""
CREATE OR REPLACE FUNCTION locale_search_array(data jsonb, search_values text[])
RETURNS boolean
LANGUAGE plpgsql AS
@@ -95,7 +98,6 @@ END;
$func$;
"""
);
}
/// <inheritdoc />
File diff suppressed because it is too large Load Diff
+11 -8
View File
@@ -1,30 +1,33 @@
using Microsoft.EntityFrameworkCore;
using Pf2eModel.Model.Base;
using System.ComponentModel;
using System.Linq.Expressions;
using System.ComponentModel;
using System.Reflection;
namespace Pf2eModel.Model.Common.I18n;
public static class LocaleExtension
{
public static string GetTypeString(this LocaleType localeType)
{
FieldInfo fi = localeType.GetType().GetField(localeType.ToString())!;
DescriptionAttribute[] attributes = (DescriptionAttribute[]) fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
DescriptionAttribute[] attributes = (DescriptionAttribute[])
fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
return (attributes.Length != 0 ? attributes.FirstOrDefault()?.Description : null) ?? localeType.ToString();
return (attributes.Length != 0 ? attributes.FirstOrDefault()?.Description : null)
?? localeType.ToString();
}
public static LocaleType GetTypeByString(this string localeType)
{
foreach (System.Reflection.FieldInfo field in typeof(LocaleType).GetFields())
{
if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute descriptionAttribute)
if (
Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))
is DescriptionAttribute descriptionAttribute
)
{
if (descriptionAttribute.Description == localeType)
{
return (LocaleType) field.GetValue(null)!;
return (LocaleType)field.GetValue(null)!;
}
}
}
+14 -13
View File
@@ -1,18 +1,12 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using Newtonsoft.Json.Linq;
namespace Pf2eModel.Model.Common.I18n;
public class LocaleString : ICollection<LocaleItem>
{
private readonly List<LocaleItem> _items = [];
private void AssureDefault()
{
if (_items.Count == 0)
@@ -34,16 +28,19 @@ public class LocaleString : ICollection<LocaleItem>
private LocaleType _E(string localeString) => LocaleExtension.GetTypeByString(localeString);
private LocaleType RealLocale(LocaleType locale) => Contains(locale) ? locale : LocaleType.English;
private LocaleType RealLocale(LocaleType locale) =>
Contains(locale) ? locale : LocaleType.English;
private LocaleType RealLocale(string localeString) => RealLocale(_E(localeString));
public LocaleItem GetItem(LocaleType locale) => this.First(c => c.Locale == RealLocale(locale));
public LocaleItem GetItem(string locale) => this.First(c => c.Locale == RealLocale(locale));
public string this[LocaleType locale]
{
get => GetItem(locale).Value;
set
set
{
if (Types.Contains(locale))
{
@@ -65,6 +62,7 @@ public class LocaleString : ICollection<LocaleItem>
{
this[item.Locale] = item.Value;
}
public void Add(LocaleType locale, string value)
{
this[locale] = value;
@@ -80,10 +78,12 @@ public class LocaleString : ICollection<LocaleItem>
{
return _items.Contains(item);
}
public bool Contains(LocaleType locale)
{
return Types.Contains(locale);
}
public bool Contains(string value)
{
return this.Any(item => item.Value == value);
@@ -111,6 +111,7 @@ public class LocaleString : ICollection<LocaleItem>
{
return _items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
@@ -132,17 +133,17 @@ public class LocaleString : ICollection<LocaleItem>
return json.ToString();
}
public static LocaleString Deserialize(string input)
{
JObject json = JObject.Parse(input);
LocaleString result = new();
foreach (var item in json)
foreach (KeyValuePair<string, JToken?> item in json)
{
result[item.Key] = item.ToString();
}
return result;
}
}
+3 -8
View File
@@ -1,12 +1,7 @@
using Pf2eModel.Model.Base;
using Pf2eModel.Model.Enum;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Pf2eModel.Model.Base;
using Pf2eModel.Model.Enum;
namespace Pf2eModel.Model.Structure;
@@ -1,9 +1,4 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pf2eModel.Model.Structure.ArchetypeRelation;
@@ -11,6 +6,6 @@ namespace Pf2eModel.Model.Structure.ArchetypeRelation;
internal class ArchetypeFeats
{
public int ArchetypeId { get; set; }
public int FeatId { get; set; }
}
+4 -5
View File
@@ -1,12 +1,12 @@
using Pf2eModel.Model.Base;
using Pf2eModel.Model.Enum;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Pf2eModel.Model.Base;
using Pf2eModel.Model.Enum;
namespace Pf2eModel.Model.Structure;
[EntityOfType(EntityType.Language)]
public partial class Language: IEntity
public partial class Language : IEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -14,5 +14,4 @@ public partial class Language: IEntity
public int Id { get; set; }
public Entity Entity { get; set; } = null!;
}
+144 -65
View File
@@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Pf2eModel.Model;
using Pf2eModel.Model.Base;
using Pf2eModel.Model.Base.Keywords;
@@ -17,8 +18,6 @@ using Pf2eModel.Model.Structure.ClassRelation;
using Pf2eModel.Model.Structure.DeityRelation;
using Pf2eModel.Model.Structure.FeatRelation;
using Pf2eModel.Model.Structure.SpellRelation;
using System.Linq.Expressions;
using System.Reflection;
namespace Pf2eModel;
@@ -37,15 +36,21 @@ public partial class Pf2eDbContext
DefineMethods(modelBuilder);
}
private void BindEntity<T>(EntityTypeBuilder<T> entity) where T : class, IEntity
private void BindEntity<T>(EntityTypeBuilder<T> entity)
where T : class, IEntity
{
entity.HasOne(entity => entity.Entity)
entity
.HasOne(entity => entity.Entity)
.WithOne()
.HasForeignKey<T>(entity => entity.Id)
.IsRequired();
}
private void BindLocaleString<T>(EntityTypeBuilder<T> entity, Expression<Func<T, LocaleString>> func) where T : class
private void BindLocaleString<T>(
EntityTypeBuilder<T> entity,
Expression<Func<T, LocaleString>> func
)
where T : class
{
/*
entity.OwnsMany(func, d =>
@@ -54,11 +59,9 @@ public partial class Pf2eDbContext
});
*/
entity.Property(func)
.HasConversion(
v => v.Serialize(),
v => LocaleString.Deserialize(v)
)
entity
.Property(func)
.HasConversion(v => v.Serialize(), v => LocaleString.Deserialize(v))
.HasColumnType("jsonb");
}
@@ -84,8 +87,7 @@ public partial class Pf2eDbContext
.HasPostgresEnum<SpellDamageKinds>()
.HasPostgresEnum<AttributeValues>()
.HasPostgresEnum<TrainingStage>()
.HasPostgresEnum<SourceCategory>()
;
.HasPostgresEnum<SourceCategory>();
}
private void DefineBase(ModelBuilder modelBuilder)
@@ -99,12 +101,16 @@ public partial class Pf2eDbContext
entity.HasMany(e => e.Keywords).WithMany(t => t.Entities);
// EntitySource
entity.HasMany(e => e.Sources).WithOne(e => e.Entity)
entity
.HasMany(e => e.Sources)
.WithOne(e => e.Entity)
.HasForeignKey(e => e.EntityId)
.OnDelete(DeleteBehavior.Cascade);
// EntityExternal
entity.HasMany(e => e.Externals).WithOne(e => e.Entity)
entity
.HasMany(e => e.Externals)
.WithOne(e => e.Entity)
.HasForeignKey(e => e.EntityId)
.OnDelete(DeleteBehavior.Cascade);
});
@@ -114,7 +120,9 @@ public partial class Pf2eDbContext
{
entity.Property(e => e.Id).HasColumnName("id");
entity.HasMany(s => s.EntitySources).WithOne(e => e.Source)
entity
.HasMany(s => s.EntitySources)
.WithOne(e => e.Source)
.HasForeignKey(e => e.SourceId)
.OnDelete(DeleteBehavior.Cascade);
@@ -125,7 +133,9 @@ public partial class Pf2eDbContext
// External
modelBuilder.Entity<ExternalTarget>(entity =>
{
entity.HasMany(t => t.EntityExternals).WithOne(e => e.Target)
entity
.HasMany(t => t.EntityExternals)
.WithOne(e => e.Target)
.HasForeignKey(e => e.TargetId)
.OnDelete(DeleteBehavior.Cascade);
});
@@ -134,7 +144,9 @@ public partial class Pf2eDbContext
// Keywords
modelBuilder.Entity<Keyword>(entity =>
{
entity.HasMany(e => e.Aliases).WithOne(e => e.Keyword)
entity
.HasMany(e => e.Aliases)
.WithOne(e => e.Keyword)
.HasForeignKey(e => e.KeywordId)
.OnDelete(DeleteBehavior.Cascade);
});
@@ -163,28 +175,38 @@ public partial class Pf2eDbContext
{
BindEntity(entity);
entity.HasMany(e => e.AncestryBoosts).WithOne(e => e.Ancestry)
entity
.HasMany(e => e.AncestryBoosts)
.WithOne(e => e.Ancestry)
.HasForeignKey(e => e.AncestryId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasMany(e => e.AncestryItems).WithOne(e => e.Ancestry)
entity
.HasMany(e => e.AncestryItems)
.WithOne(e => e.Ancestry)
.HasForeignKey(e => e.AncestryId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasMany(e => e.AncestryLanguages).WithOne(e => e.Ancestry)
entity
.HasMany(e => e.AncestryLanguages)
.WithOne(e => e.Ancestry)
.HasForeignKey(e => e.AncestryId)
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<AncestryBoost>(entity => { });
modelBuilder.Entity<AncestryItem>(entity =>
{
entity.HasOne(d => d.Item).WithMany()
entity
.HasOne(d => d.Item)
.WithMany()
.HasForeignKey(d => d.ItemId)
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<AncestryLanguage>(entity =>
{
entity.HasOne(d => d.Language).WithMany()
entity
.HasOne(d => d.Language)
.WithMany()
.HasForeignKey(d => d.LanguageId)
.OnDelete(DeleteBehavior.Cascade);
});
@@ -194,11 +216,15 @@ public partial class Pf2eDbContext
{
BindEntity(entity);
entity.HasOne(a => a.DedicationFeat).WithOne()
entity
.HasOne(a => a.DedicationFeat)
.WithOne()
.HasForeignKey<Archetype>(a => a.DedicationFeatId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasMany(a => a.Feats).WithMany(f => f.Archetypes)
entity
.HasMany(a => a.Feats)
.WithMany(f => f.Archetypes)
.UsingEntity<ArchetypeFeats>(
l => l.HasOne<Feat>().WithMany().HasForeignKey(af => af.FeatId),
r => r.HasOne<Archetype>().WithMany().HasForeignKey(af => af.ArchetypeId)
@@ -212,23 +238,31 @@ public partial class Pf2eDbContext
});
modelBuilder.Entity<BackgroundBoost>(entity =>
{
entity.HasOne(d => d.Background).WithMany(p => p.BackgroundBoosts)
entity
.HasOne(d => d.Background)
.WithMany(p => p.BackgroundBoosts)
.HasForeignKey(d => d.BackgroundId)
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<BackgroundItem>(entity =>
{
entity.HasOne(d => d.Background).WithMany(p => p.BackgroundItems)
entity
.HasOne(d => d.Background)
.WithMany(p => p.BackgroundItems)
.HasForeignKey(d => d.BackgroundId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasOne(d => d.Entity).WithMany()
entity
.HasOne(d => d.Entity)
.WithMany()
.HasForeignKey(d => d.EntityId)
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<BackgroundTraining>(entity =>
{
entity.HasOne(d => d.Background).WithMany(p => p.BackgroundSkills)
entity
.HasOne(d => d.Background)
.WithMany(p => p.BackgroundSkills)
.HasForeignKey(d => d.BackgroundId)
.OnDelete(DeleteBehavior.Cascade);
});
@@ -240,27 +274,37 @@ public partial class Pf2eDbContext
});
modelBuilder.Entity<ClassKeyAbility>(entity =>
{
entity.HasOne(d => d.Class).WithMany(p => p.ClassKeyAbilities)
entity
.HasOne(d => d.Class)
.WithMany(p => p.ClassKeyAbilities)
.HasForeignKey(d => d.ClassId)
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<ClassProgression>(entity =>
{
entity.HasOne(d => d.Class).WithMany(p => p.ClassProgressions)
entity
.HasOne(d => d.Class)
.WithMany(p => p.ClassProgressions)
.HasForeignKey(d => d.ClassId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasOne(d => d.Entity).WithMany()
entity
.HasOne(d => d.Entity)
.WithMany()
.HasForeignKey(d => d.EntityId)
.OnDelete(DeleteBehavior.SetNull);
});
modelBuilder.Entity<ClassTraining>(entity =>
{
entity.HasOne(d => d.Class).WithMany(p => p.ClassTrainings)
entity
.HasOne(d => d.Class)
.WithMany(p => p.ClassTrainings)
.HasForeignKey(d => d.ClassId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasOne(d => d.Training).WithMany()
entity
.HasOne(d => d.Training)
.WithMany()
.HasForeignKey(d => d.TrainingId)
.OnDelete(DeleteBehavior.SetNull);
});
@@ -276,19 +320,27 @@ public partial class Pf2eDbContext
{
BindEntity(entity);
entity.HasMany(e => e.DeityAttributes).WithOne(e => e.Deity)
entity
.HasMany(e => e.DeityAttributes)
.WithOne(e => e.Deity)
.HasForeignKey(e => e.DeityId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasMany(e => e.DeityDomains).WithOne(e => e.Deity)
entity
.HasMany(e => e.DeityDomains)
.WithOne(e => e.Deity)
.HasForeignKey(e => e.DeityId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasMany(e => e.DeitySpells).WithOne(e => e.Deity)
entity
.HasMany(e => e.DeitySpells)
.WithOne(e => e.Deity)
.HasForeignKey(e => e.DeityId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasMany(e => e.DeityWeapons).WithOne(e => e.Deity)
entity
.HasMany(e => e.DeityWeapons)
.WithOne(e => e.Deity)
.HasForeignKey(e => e.DeityId)
.OnDelete(DeleteBehavior.Cascade);
@@ -298,7 +350,9 @@ public partial class Pf2eDbContext
modelBuilder.Entity<DeityDomain>(entity => { });
modelBuilder.Entity<DeitySpell>(entity =>
{
entity.HasOne(d => d.Spell).WithMany()
entity
.HasOne(d => d.Spell)
.WithMany()
.HasForeignKey(d => d.SpellId)
.OnDelete(DeleteBehavior.Cascade);
});
@@ -309,7 +363,9 @@ public partial class Pf2eDbContext
{
BindEntity(entity);
entity.HasMany(e => e.FeatPrerequisites).WithOne(e => e.Feat)
entity
.HasMany(e => e.FeatPrerequisites)
.WithOne(e => e.Feat)
.HasForeignKey(e => e.FeatId)
.OnDelete(DeleteBehavior.Cascade);
});
@@ -320,7 +376,9 @@ public partial class Pf2eDbContext
{
BindEntity(entity);
entity.HasOne(d => d.Ancestry).WithMany(p => p.Heritages)
entity
.HasOne(d => d.Ancestry)
.WithMany(p => p.Heritages)
.HasForeignKey(d => d.AncestryId)
.OnDelete(DeleteBehavior.Cascade);
});
@@ -330,21 +388,29 @@ public partial class Pf2eDbContext
{
BindEntity(entity);
entity.HasOne(e => e.SpellArea).WithOne(e => e.Spell)
entity
.HasOne(e => e.SpellArea)
.WithOne(e => e.Spell)
.HasForeignKey<SpellArea>(e => e.SpellId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired(false);
entity.HasOne(e => e.SpellRitual).WithOne(e => e.Spell)
entity
.HasOne(e => e.SpellRitual)
.WithOne(e => e.Spell)
.HasForeignKey<SpellRitual>(e => e.SpellId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired(false);
entity.HasMany(e => e.SpellDamages).WithOne(e => e.Spell)
entity
.HasMany(e => e.SpellDamages)
.WithOne(e => e.Spell)
.HasForeignKey(e => e.SpellId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasMany(e => e.SpellDefenses).WithOne(e => e.Spell)
entity
.HasMany(e => e.SpellDefenses)
.WithOne(e => e.Spell)
.HasForeignKey(e => e.SpellId)
.OnDelete(DeleteBehavior.Cascade);
});
@@ -362,27 +428,40 @@ public partial class Pf2eDbContext
private void DefineMethods(ModelBuilder modelBuilder)
{
MethodInfo localeSearch = typeof(Pf2eDbContext).GetMethod(nameof(LocaleSearch), BindingFlags.Static | BindingFlags.Public, [typeof(LocaleString), typeof(string)])!;
modelBuilder.HasDbFunction(localeSearch, builder =>
{
builder.HasName("locale_search");
builder.HasParameter("data").HasStoreType("jsonb");
builder.HasParameter("search_value");
});
MethodInfo localeSearch = typeof(Pf2eDbContext).GetMethod(
nameof(LocaleSearch),
BindingFlags.Static | BindingFlags.Public,
[typeof(LocaleString), typeof(string)]
)!;
modelBuilder.HasDbFunction(
localeSearch,
builder =>
{
builder.HasName("locale_search");
builder.HasParameter("data").HasStoreType("jsonb");
builder.HasParameter("search_value");
}
);
MethodInfo localeSearchArray = typeof(Pf2eDbContext).GetMethod(nameof(LocaleSearchArray), BindingFlags.Static | BindingFlags.Public, [typeof(LocaleString), typeof(IEnumerable<string>)])!;
modelBuilder.HasDbFunction(localeSearchArray, builder =>
{
builder.HasName("locale_search_array");
builder.HasParameter("data").HasStoreType("jsonb");
builder.HasParameter("search_values");
});
MethodInfo localeSearchArray = typeof(Pf2eDbContext).GetMethod(
nameof(LocaleSearchArray),
BindingFlags.Static | BindingFlags.Public,
[typeof(LocaleString), typeof(IEnumerable<string>)]
)!;
modelBuilder.HasDbFunction(
localeSearchArray,
builder =>
{
builder.HasName("locale_search_array");
builder.HasParameter("data").HasStoreType("jsonb");
builder.HasParameter("search_values");
}
);
}
public static bool LocaleSearch(LocaleString data, string search_value)
=> throw new InvalidOperationException("Only for LINQ translation");
public static bool LocaleSearchArray(LocaleString data, IEnumerable<string> search_values)
=> throw new InvalidOperationException("Only for LINQ translation");
public static bool LocaleSearch(LocaleString data, string search_value) =>
throw new InvalidOperationException("Only for LINQ translation");
public static bool LocaleSearchArray(LocaleString data, IEnumerable<string> search_values) =>
throw new InvalidOperationException("Only for LINQ translation");
}
+15 -8
View File
@@ -1,15 +1,13 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Pf2eModel;
using Pf2eModel.Model;
using Pf2eModel.Model.Base;
using Pf2eModel.Model.Base.Source;
using Pf2eModel.Model.Common.I18n;
using Pf2eModel.Model.Structure;
using System.ComponentModel;
namespace Pf2eViewer;
internal class EntityConverter : JsonConverter
{
private readonly Pf2eDbContext _context = new();
@@ -71,7 +69,9 @@ internal class EntityConverter : JsonConverter
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()!;
LocaleString name =
trait.Entity?.Name
?? _context.Entities.Where(e => e.Id == trait.Id).Select(e => e.Name).FirstOrDefault()!;
dictionary.Remove("Entity");
dictionary.Remove("Entities");
@@ -82,11 +82,18 @@ internal class EntityConverter : JsonConverter
{
dictionary.Remove("Description");
}
public override bool CanRead => false;
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
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.");
throw new NotImplementedException(
"Unnecessary because CanRead is false. The type will skip the converter."
);
}
}
+52 -51
View File
@@ -1,5 +1,4 @@
using LinqToDB.Tools;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
@@ -7,8 +6,8 @@ using Newtonsoft.Json.Serialization;
using Pf2eModel;
using Pf2eModel.Model;
using Pf2eModel.Model.Base;
using Pf2eModel.Model.Common.I18n;
using Pf2eModel.Model.Enum;
using static LinqToDB.Common.Configuration;
namespace Pf2eViewer;
@@ -49,11 +48,10 @@ public partial class MainViewForm : Form
public int MaxPage => Convert.ToInt32(Math.Ceiling(1.0 * Count / PerPage));
private void UpdateTreeView()
{
EntityTreeView.Nodes.Clear();
EntityType type = (EntityType) TypesListBox.SelectedItem!;
EntityType type = (EntityType)TypesListBox.SelectedItem!;
Count = Context.Entities.Count(e => e.Type == type);
@@ -63,8 +61,8 @@ public partial class MainViewForm : Form
return;
}
EntityGridView.DataSource = Context.Entities
.Where(e => e.Type == (EntityType) TypesListBox.SelectedItem)
EntityGridView.DataSource = Context
.Entities.Where(e => e.Type == (EntityType)TypesListBox.SelectedItem)
.OrderBy(e => e.Id)
.Select(e => new EntityGridRow(e))
.Skip((Page - 1) * PerPage)
@@ -90,22 +88,27 @@ public partial class MainViewForm : Form
Page = 1;
}
private void FirstPageButton_Click(object sender, EventArgs e)
{
Page = 1;
}
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))
@@ -113,14 +116,16 @@ public partial class MainViewForm : Form
e.Handled = true;
}
if (e.KeyChar == (char) Keys.Return)
if (e.KeyChar == (char)Keys.Return)
{
UpdateTreeView();
}
}
private void EntityGridView_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
private void EntityGridView_RowStateChanged(
object sender,
DataGridViewRowStateChangedEventArgs e
)
{
int rowsCount = EntityGridView.SelectedRows.Count;
if (rowsCount is 0 or > 1)
@@ -130,7 +135,7 @@ public partial class MainViewForm : Form
DataGridViewRow row = EntityGridView.SelectedRows[0];
EntityGridRow data = (EntityGridRow) row.DataBoundItem;
EntityGridRow data = (EntityGridRow)row.DataBoundItem;
ViewEntity(data.Id);
}
@@ -139,18 +144,16 @@ public partial class MainViewForm : Form
{
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.Aliases)
.Include(e => e.Keywords)
.Include(e => e.Externals)
.ThenInclude(x => x.Target)
.Include(e => e.Traits)
.ThenInclude(t => t.Entity)
.FirstOrDefault()
;
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)
{
@@ -158,7 +161,6 @@ public partial class MainViewForm : Form
return;
}
string json = SerializeEntity(entity);
JsonToTreeview(EntityTreeView, json, "Entity");
@@ -166,13 +168,12 @@ public partial class MainViewForm : Form
DescriptionTextBox.Text = entity.Description.Replace("\\r", "").Replace("\\n", "\\r\\n");
}
public string SerializeEntity(Entity entity)
{
JsonSerializerSettings settings = new()
{
Converters = [
Converters =
[
new EntityConverter(),
new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() },
],
@@ -192,51 +193,51 @@ public partial class MainViewForm : Form
switch (entity.Type)
{
case EntityType.Ancestry:
return Context.Ancestries
.Include(a => a.AncestryBoosts)
return Context
.Ancestries.Include(a => a.AncestryBoosts)
.FirstOrDefault(e => e.Id == entity.Id);
case EntityType.Archetype:
return Context.Archetypes
.Include(a => a.DedicationFeat)
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)
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)
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)
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);
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);
? JArray.Parse(jsonString)
: JObject.Parse(jsonString);
treeView.Nodes.Clear();
foreach (TreeNode node in Element2TreeNode(json, rootName).Nodes)
@@ -253,7 +254,7 @@ public partial class MainViewForm : Form
switch (element.GetType().Name)
{
case "JObject":
JObject jObject = (JObject) element;
JObject jObject = (JObject)element;
foreach (KeyValuePair<string, JToken> token in jObject)
{
subNodes.Add(Element2TreeNode(token.Value, token.Key));
@@ -261,7 +262,7 @@ public partial class MainViewForm : Form
break;
case "JArray":
JArray jArray = (JArray) element;
JArray jArray = (JArray)element;
int i = 0;
subNodes.AddRange(jArray.Select(token => Element2TreeNode(token, $"[{i++}]")));
@@ -272,22 +273,23 @@ public partial class MainViewForm : Form
break;
case "JValue":
JValue jValue = (JValue) element;
JValue jValue = (JValue)element;
text += $": ({jValue.Type}) {jValue}";
break;
default:
throw new Exception("clsJSON2Treeview can't interpret object:" + element.GetType().Name);
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()
);
treeNode.Nodes.AddRange(
subNodes.OrderBy(node => node.Nodes.Count > 0 ? 1 : 0).ToArray()
);
}
return treeNode;
@@ -296,12 +298,11 @@ public partial class MainViewForm : Form
private class EntityGridRow(Entity e)
{
public int Id { get; set; } = e.Id;
public string Name { get; set; } = e.Name.ToString();
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;
}
}