Implement applicant pool functionality in school simulation, allowing for the management of job seekers who are not yet part of the school roster. Update the catalog to include staffing definitions and enhance the API to support applicant data retrieval. Revise the school architecture to handle applicant refresh logic and ensure proper integration with existing roster management. Update tests to validate the new applicant functionalities and ensure robustness in handling staffing scenarios.
This commit is contained in:
@@ -308,6 +308,7 @@ public sealed class CatalogLoader
|
||||
var needs = new Dictionary<string, NeedDef>(StringComparer.Ordinal);
|
||||
var nameSets = new Dictionary<string, NameSetDef>(StringComparer.Ordinal);
|
||||
var subjects = new Dictionary<string, SubjectDef>(StringComparer.Ordinal);
|
||||
var staffing = new Dictionary<string, StaffingDef>(StringComparer.Ordinal);
|
||||
|
||||
foreach (var (key, json) in resolved)
|
||||
{
|
||||
@@ -355,6 +356,9 @@ public sealed class CatalogLoader
|
||||
case DefKind.Subject:
|
||||
subjects[key.Name] = Jsonc.Deserialize<SubjectDef>(json);
|
||||
break;
|
||||
case DefKind.Staffing:
|
||||
staffing[key.Name] = Jsonc.Deserialize<StaffingDef>(json);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,6 +378,7 @@ public sealed class CatalogLoader
|
||||
needs,
|
||||
nameSets,
|
||||
subjects,
|
||||
staffing,
|
||||
ru,
|
||||
en);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ public sealed class DefCatalog
|
||||
IReadOnlyDictionary<string, NeedDef> needs,
|
||||
IReadOnlyDictionary<string, NameSetDef> nameSets,
|
||||
IReadOnlyDictionary<string, SubjectDef> subjects,
|
||||
IReadOnlyDictionary<string, StaffingDef> staffing,
|
||||
IReadOnlyDictionary<string, string> ru,
|
||||
IReadOnlyDictionary<string, string> en)
|
||||
{
|
||||
@@ -40,6 +41,7 @@ public sealed class DefCatalog
|
||||
Needs = needs;
|
||||
NameSets = nameSets;
|
||||
Subjects = subjects;
|
||||
Staffing = staffing;
|
||||
_ru = ru;
|
||||
_en = en;
|
||||
AnyNeedDecays = needs.Values.Any(need => !need.Abstract && need.DecayPerHour > 0f);
|
||||
@@ -82,6 +84,11 @@ public sealed class DefCatalog
|
||||
|
||||
public IReadOnlyDictionary<string, SubjectDef> Subjects { get; }
|
||||
|
||||
public IReadOnlyDictionary<string, StaffingDef> Staffing { get; }
|
||||
|
||||
/// <summary>The one concrete staffing ruleset, or null when a pack has not defined it.</summary>
|
||||
public StaffingDef? StaffingRules => Staffing.Values.FirstOrDefault(def => !def.Abstract);
|
||||
|
||||
private readonly IReadOnlyDictionary<string, string> _ru;
|
||||
private readonly IReadOnlyDictionary<string, string> _en;
|
||||
|
||||
@@ -103,6 +110,7 @@ public sealed class DefCatalog
|
||||
DefKind.Need => Needs.GetValueOrDefault(defName),
|
||||
DefKind.NameSet => NameSets.GetValueOrDefault(defName),
|
||||
DefKind.Subject => Subjects.GetValueOrDefault(defName),
|
||||
DefKind.Staffing => Staffing.GetValueOrDefault(defName),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
@@ -177,6 +185,7 @@ public sealed class DefCatalog
|
||||
NeedDef => DefKind.Need,
|
||||
NameSetDef => DefKind.NameSet,
|
||||
SubjectDef => DefKind.Subject,
|
||||
StaffingDef => DefKind.Staffing,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(def)),
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ public enum DefKind
|
||||
Need,
|
||||
NameSet,
|
||||
Subject,
|
||||
Staffing,
|
||||
}
|
||||
|
||||
/// <summary>Shared JSONC fields. Kind comes from the folder under <c>defs/</c>, not from the file.</summary>
|
||||
|
||||
@@ -104,6 +104,9 @@ internal static class PackPaths
|
||||
case "subjects":
|
||||
kind = DefKind.Subject;
|
||||
return true;
|
||||
case "staffing":
|
||||
kind = DefKind.Staffing;
|
||||
return true;
|
||||
default:
|
||||
kind = default;
|
||||
return false;
|
||||
|
||||
@@ -34,6 +34,16 @@ internal static class PeopleDefValidator
|
||||
ValidateSubject(subject, catalog);
|
||||
}
|
||||
|
||||
foreach (var staffing in catalog.Staffing.Values)
|
||||
{
|
||||
ValidateStaffing(staffing);
|
||||
}
|
||||
|
||||
if (catalog.Staffing.Values.Count(def => !def.Abstract) > 1)
|
||||
{
|
||||
throw new ContentLoadException("A catalog may only have one concrete StaffingDef.");
|
||||
}
|
||||
|
||||
RequireBuildInputs(catalog);
|
||||
}
|
||||
|
||||
@@ -260,6 +270,34 @@ internal static class PeopleDefValidator
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateStaffing(StaffingDef staffing)
|
||||
{
|
||||
if (staffing.Abstract)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (staffing.PoolSize < 1 || staffing.PoolSize > 64)
|
||||
{
|
||||
throw new ContentLoadException($"StaffingDef '{staffing.DefName}' poolSize must be 1–64.");
|
||||
}
|
||||
|
||||
if (staffing.StayChance <= 0f || staffing.StayChance >= 1f)
|
||||
{
|
||||
throw new ContentLoadException($"StaffingDef '{staffing.DefName}' stayChance must be between 0 and 1 exclusive.");
|
||||
}
|
||||
|
||||
if (staffing.ParentChance < 0f || staffing.ParentChance > 1f)
|
||||
{
|
||||
throw new ContentLoadException($"StaffingDef '{staffing.DefName}' parentChance must be 0–1.");
|
||||
}
|
||||
|
||||
if (staffing.HourlyWageBase < 0f || staffing.HourlyWagePerSkill < 0f)
|
||||
{
|
||||
throw new ContentLoadException($"StaffingDef '{staffing.DefName}' wage scale cannot be negative.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateNameSet(NameSetDef names)
|
||||
{
|
||||
if (!NameGrammar.IsKnownPatronymic(names.PatronymicRule))
|
||||
|
||||
@@ -157,6 +157,24 @@ public sealed class TraitDef : Def
|
||||
public IntRange? Age { get; init; }
|
||||
|
||||
public IReadOnlyList<TraitSkillModifier> SkillModifiers { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Added to the hourly wage ask. Positive means the person wants more at the same skills.
|
||||
/// </summary>
|
||||
public float WageAsk { get; init; }
|
||||
}
|
||||
|
||||
public sealed class StaffingDef : Def
|
||||
{
|
||||
public int PoolSize { get; init; }
|
||||
|
||||
public float StayChance { get; init; }
|
||||
|
||||
public float ParentChance { get; init; }
|
||||
|
||||
public float HourlyWageBase { get; init; }
|
||||
|
||||
public float HourlyWagePerSkill { get; init; }
|
||||
}
|
||||
|
||||
public enum BodyAttributeKind
|
||||
|
||||
Reference in New Issue
Block a user