Enhance school creation functionality by introducing support for name sets in the API and UI. Update the catalog to include skills, traits, body attributes, needs, and name sets, improving character generation capabilities. Revise localization strings for better user guidance and update tests to validate the new name set functionality and ensure robustness in school creation processes.
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
namespace HSchool.Content.Tests;
|
||||
|
||||
public class PeopleDefTests
|
||||
{
|
||||
private readonly CatalogLoader _loader = new();
|
||||
|
||||
[Fact]
|
||||
public void VanillaCore_LoadsPeopleDefs()
|
||||
{
|
||||
var root = Path.Combine(AppContext.BaseDirectory, "vanilla");
|
||||
var catalog = _loader.Load([CatalogLoader.CorePackId], PackDocuments.FromDirectory(CatalogLoader.CorePackId, root));
|
||||
|
||||
Assert.True(catalog.Skills.Count >= 10);
|
||||
Assert.Equal(10, catalog.Traits.Count);
|
||||
Assert.Equal(4, catalog.Needs.Count);
|
||||
Assert.True(catalog.BodyAttributes.ContainsKey("Height"));
|
||||
Assert.Equal(BodyAttributeKind.Number, catalog.BodyAttributes["Height"].Kind);
|
||||
Assert.Equal(BodyAttributeKind.Choice, catalog.BodyAttributes["HairColor"].Kind);
|
||||
Assert.All(catalog.Needs.Values, need => Assert.Equal(0, need.DecayPerHour));
|
||||
Assert.Contains(catalog.Skills["Agility"].BodyLimits, limit => limit.Attribute == "Build" && limit.Value == "Obese");
|
||||
Assert.True(catalog.NameSets.ContainsKey("Slavic"));
|
||||
Assert.True(catalog.NameSets["Slavic"].MaleGiven.Count >= 20);
|
||||
Assert.Equal("Славянский", catalog.Label("ru", catalog.NameSets["Slavic"]));
|
||||
Assert.Equal("Slavic", catalog.Label("en", catalog.NameSets["Slavic"]));
|
||||
Assert.Equal("Усидчивый", catalog.Label("ru", catalog.Traits["Diligent"]));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Skill_InheritsRangeFromParent()
|
||||
{
|
||||
var catalog = _loader.Load(
|
||||
[CatalogLoader.CorePackId],
|
||||
[
|
||||
PackDocuments.Def(
|
||||
CatalogLoader.CorePackId,
|
||||
"skills",
|
||||
"base",
|
||||
"""{ "defName": "AcademicBase", "abstract": true, "range": { "min": 0, "max": 100 }, "distribution": { "mean": 40, "stdDev": 10 } }"""),
|
||||
PackDocuments.Def(
|
||||
CatalogLoader.CorePackId,
|
||||
"skills",
|
||||
"math",
|
||||
"""{ "defName": "Mathematics", "parent": "AcademicBase", "distribution": { "mean": 55, "stdDev": 12 } }"""),
|
||||
]);
|
||||
|
||||
Assert.Equal(0, catalog.Skills["Mathematics"].Range.Min);
|
||||
Assert.Equal(100, catalog.Skills["Mathematics"].Range.Max);
|
||||
Assert.Equal(55, catalog.Skills["Mathematics"].Distribution?.Mean);
|
||||
Assert.False(catalog.Skills["Mathematics"].Abstract);
|
||||
Assert.True(catalog.Skills["AcademicBase"].Abstract);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TraitPatch_AddsAnIncompatibility()
|
||||
{
|
||||
var catalog = _loader.Load(
|
||||
[CatalogLoader.CorePackId, "addon"],
|
||||
[
|
||||
PackDocuments.Def(CatalogLoader.CorePackId, "skills", "math", """{ "defName": "Mathematics" }"""),
|
||||
PackDocuments.Def(
|
||||
CatalogLoader.CorePackId,
|
||||
"traits",
|
||||
"kind",
|
||||
"""{ "defName": "Kind", "weight": 1, "incompatible": [] }"""),
|
||||
PackDocuments.Def(
|
||||
CatalogLoader.CorePackId,
|
||||
"traits",
|
||||
"bully",
|
||||
"""{ "defName": "Bully", "weight": 1 }"""),
|
||||
PackDocuments.Patch(
|
||||
"addon",
|
||||
"kind",
|
||||
"""{ "target": "Kind", "ops": [ { "op": "add", "path": "/incompatible/-", "value": "Bully" } ] }"""),
|
||||
]);
|
||||
|
||||
Assert.Equal(["Bully"], catalog.Traits["Kind"].Incompatible);
|
||||
Assert.Contains("Bully", catalog.TraitIncompatibilities("Kind"));
|
||||
Assert.Contains("Kind", catalog.TraitIncompatibilities("Bully"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnknownBodyLimitAttribute_FailsTheCatalog()
|
||||
{
|
||||
var ex = Assert.Throws<ContentLoadException>(() => _loader.Load(
|
||||
[CatalogLoader.CorePackId],
|
||||
[
|
||||
PackDocuments.Def(
|
||||
CatalogLoader.CorePackId,
|
||||
"skills",
|
||||
"agility",
|
||||
"""{ "defName": "Agility", "bodyLimits": [ { "attribute": "Missing", "value": "X", "max": 10 } ] }"""),
|
||||
]));
|
||||
|
||||
Assert.Contains("Missing", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnknownBuildValue_FailsTheCatalog()
|
||||
{
|
||||
var ex = Assert.Throws<ContentLoadException>(() => _loader.Load(
|
||||
[CatalogLoader.CorePackId],
|
||||
[
|
||||
PackDocuments.Def(
|
||||
CatalogLoader.CorePackId,
|
||||
"skills",
|
||||
"agility",
|
||||
"""{ "defName": "Agility", "bodyLimits": [ { "attribute": "Build", "value": "Huge", "max": 10 } ] }"""),
|
||||
]));
|
||||
|
||||
Assert.Contains("Huge", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnknownTraitIncompatibility_FailsTheCatalog()
|
||||
{
|
||||
var ex = Assert.Throws<ContentLoadException>(() => _loader.Load(
|
||||
[CatalogLoader.CorePackId],
|
||||
[
|
||||
PackDocuments.Def(
|
||||
CatalogLoader.CorePackId,
|
||||
"traits",
|
||||
"kind",
|
||||
"""{ "defName": "Kind", "incompatible": ["Ghost"] }"""),
|
||||
]));
|
||||
|
||||
Assert.Contains("Ghost", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OneWayIncompatibility_IsMutual()
|
||||
{
|
||||
var catalog = _loader.Load(
|
||||
[CatalogLoader.CorePackId],
|
||||
[
|
||||
PackDocuments.Def(CatalogLoader.CorePackId, "traits", "a", """{ "defName": "Diligent", "weight": 1, "incompatible": ["Lazy"] }"""),
|
||||
PackDocuments.Def(CatalogLoader.CorePackId, "traits", "b", """{ "defName": "Lazy", "weight": 1 }"""),
|
||||
]);
|
||||
|
||||
Assert.Equal(["Lazy"], catalog.Traits["Diligent"].Incompatible);
|
||||
Assert.Empty(catalog.Traits["Lazy"].Incompatible);
|
||||
Assert.Contains("Lazy", catalog.TraitIncompatibilities("Diligent"));
|
||||
Assert.Contains("Diligent", catalog.TraitIncompatibilities("Lazy"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExtraPack_AddsANameSetAndTrait()
|
||||
{
|
||||
var catalog = _loader.Load(
|
||||
[CatalogLoader.CorePackId, "addon"],
|
||||
[
|
||||
PackDocuments.Def(CatalogLoader.CorePackId, "traits", "kind", """{ "defName": "Kind", "weight": 1 }"""),
|
||||
PackDocuments.Def(
|
||||
CatalogLoader.CorePackId,
|
||||
"namesets",
|
||||
"slavic",
|
||||
"""
|
||||
{
|
||||
"defName": "Slavic",
|
||||
"maleGiven": [{ "form": "Иван" }],
|
||||
"femaleGiven": [{ "form": "Анна", "declension": "a" }],
|
||||
"surnames": [{ "male": "Иванов", "female": "Иванова" }]
|
||||
}
|
||||
"""),
|
||||
PackDocuments.Def("addon", "traits", "stoic", """{ "defName": "Stoic", "weight": 3 }"""),
|
||||
PackDocuments.Def("addon", "traits", "cheerful", """{ "defName": "Cheerful", "weight": 2 }"""),
|
||||
PackDocuments.Def(
|
||||
"addon",
|
||||
"namesets",
|
||||
"nordic",
|
||||
"""
|
||||
{
|
||||
"defName": "Nordic",
|
||||
"maleGiven": [{ "form": "Lars", "declension": "indeclinable" }],
|
||||
"femaleGiven": [{ "form": "Ingrid", "declension": "indeclinable" }],
|
||||
"surnames": [{ "male": "Berg", "female": "Berg", "declension": "indeclinable" }]
|
||||
}
|
||||
"""),
|
||||
PackDocuments.Locale("addon", "ru", """{ "Nordic": "Северный", "Stoic": "Стоик", "Cheerful": "Жизнерадостный" }"""),
|
||||
]);
|
||||
|
||||
Assert.True(catalog.NameSets.ContainsKey("Nordic"));
|
||||
Assert.True(catalog.Traits.ContainsKey("Stoic"));
|
||||
Assert.True(catalog.Traits.ContainsKey("Cheerful"));
|
||||
Assert.Equal("Северный", catalog.Label("ru", catalog.NameSets["Nordic"]));
|
||||
Assert.Equal("Стоик", catalog.Label("ru", catalog.Traits["Stoic"]));
|
||||
}
|
||||
}
|
||||
|
||||
public class NameGrammarTests
|
||||
{
|
||||
[Fact]
|
||||
public void HardGiven_FollowsTheConsonantModel()
|
||||
{
|
||||
var entry = new GivenNameEntry { Form = "Иван", Declension = NameGrammar.Hard };
|
||||
|
||||
Assert.Equal("Иван", NameGrammar.InflectGiven(entry, GrammaticalCase.Nominative, NameGrammar.Hard));
|
||||
Assert.Equal("Ивана", NameGrammar.InflectGiven(entry, GrammaticalCase.Genitive, NameGrammar.Hard));
|
||||
Assert.Equal("Ивану", NameGrammar.InflectGiven(entry, GrammaticalCase.Dative, NameGrammar.Hard));
|
||||
Assert.Equal("Иваном", NameGrammar.InflectGiven(entry, GrammaticalCase.Instrumental, NameGrammar.Hard));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExplicitTable_OverridesTheModel()
|
||||
{
|
||||
var entry = new GivenNameEntry
|
||||
{
|
||||
Form = "Любовь",
|
||||
Declension = NameGrammar.Soft,
|
||||
Cases = new CaseTable
|
||||
{
|
||||
Nom = "Любовь",
|
||||
Gen = "Любови",
|
||||
Dat = "Любови",
|
||||
Acc = "Любовь",
|
||||
Ins = "Любовью",
|
||||
Pre = "Любови",
|
||||
},
|
||||
};
|
||||
|
||||
Assert.Equal("Любови", NameGrammar.InflectGiven(entry, GrammaticalCase.Genitive, NameGrammar.Soft));
|
||||
Assert.Equal("Любовью", NameGrammar.InflectGiven(entry, GrammaticalCase.Instrumental, NameGrammar.Soft));
|
||||
Assert.Equal("Любовя", NameGrammar.InflectGivenForm("Любовь", NameGrammar.Soft, GrammaticalCase.Genitive));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OvSurname_UsesGenderedEndings()
|
||||
{
|
||||
var entry = new SurnameEntry { Male = "Иванов", Female = "Иванова", Declension = NameGrammar.Ov };
|
||||
|
||||
Assert.Equal("Иванова", NameGrammar.InflectSurname(entry, female: false, GrammaticalCase.Genitive, NameGrammar.Ov));
|
||||
Assert.Equal("Ивановой", NameGrammar.InflectSurname(entry, female: true, GrammaticalCase.Genitive, NameGrammar.Ov));
|
||||
Assert.Equal("Иванову", NameGrammar.InflectSurname(entry, female: true, GrammaticalCase.Accusative, NameGrammar.Ov));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SlavicPatronymic_FromTheFathersName()
|
||||
{
|
||||
Assert.Equal("Иванович", NameGrammar.Patronymic("Иван", female: false, NameGrammar.SlavicPatronymic));
|
||||
Assert.Equal("Ивановна", NameGrammar.Patronymic("Иван", female: true, NameGrammar.SlavicPatronymic));
|
||||
Assert.Equal("Андреевич", NameGrammar.Patronymic("Андрей", female: false, NameGrammar.SlavicPatronymic));
|
||||
Assert.Equal("Дмитриевич", NameGrammar.Patronymic("Дмитрий", female: false, NameGrammar.SlavicPatronymic));
|
||||
Assert.Equal("Ильинична", NameGrammar.Patronymic("Илья", female: true, NameGrammar.SlavicPatronymic));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BodyBuild_ComesFromBmiBands()
|
||||
{
|
||||
Assert.Equal(BodyBuilds.Skinny, BodyBuilds.FromHeightAndWeight(170, 50));
|
||||
Assert.Equal(BodyBuilds.Athletic, BodyBuilds.FromHeightAndWeight(170, 68));
|
||||
Assert.Equal(BodyBuilds.Obese, BodyBuilds.FromHeightAndWeight(170, 90));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Patronymic_InflectsLikeAHardOrAStem()
|
||||
{
|
||||
Assert.Equal("Ивановича", NameGrammar.InflectPatronymic("Иванович", female: false, GrammaticalCase.Genitive));
|
||||
Assert.Equal("Ивановны", NameGrammar.InflectPatronymic("Ивановна", female: true, GrammaticalCase.Genitive));
|
||||
Assert.Equal("Ивановну", NameGrammar.InflectPatronymic("Ивановна", female: true, GrammaticalCase.Accusative));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user