Enhance protocol and simulation features with activity tracking and behavior definitions
- Updated protocol documentation to include new `activity` and `activityLabel` fields in the person card response, reflecting real-time activity status. - Introduced `BehaviorDef` to define behavior rules, including need thresholds and lesson skill gains, enhancing AI decision-making. - Revised the `DefCatalog` to incorporate behavior definitions and updated validation logic to ensure proper behavior handling. - Enhanced the simulation to manage presence and activity states, allowing for more dynamic interactions within the school environment. - Updated tests to validate the new activity tracking and behavior functionalities, ensuring robust performance and reliability. - Improved localization strings to support new activity and behavior features, enhancing user experience.
This commit is contained in:
@@ -49,6 +49,16 @@ internal static class PeopleDefValidator
|
||||
ValidateHoliday(holiday);
|
||||
}
|
||||
|
||||
foreach (var action in catalog.Actions.Values)
|
||||
{
|
||||
ValidateAction(action, catalog);
|
||||
}
|
||||
|
||||
foreach (var behavior in catalog.Behavior.Values)
|
||||
{
|
||||
ValidateBehavior(behavior);
|
||||
}
|
||||
|
||||
if (catalog.Staffing.Values.Count(def => !def.Abstract) > 1)
|
||||
{
|
||||
throw new ContentLoadException("A catalog may only have one concrete StaffingDef.");
|
||||
@@ -59,6 +69,11 @@ internal static class PeopleDefValidator
|
||||
throw new ContentLoadException("A catalog may only have one concrete DayFrameDef.");
|
||||
}
|
||||
|
||||
if (catalog.Behavior.Values.Count(def => !def.Abstract) > 1)
|
||||
{
|
||||
throw new ContentLoadException("A catalog may only have one concrete BehaviorDef.");
|
||||
}
|
||||
|
||||
RequireBuildInputs(catalog);
|
||||
}
|
||||
|
||||
@@ -373,6 +388,93 @@ internal static class PeopleDefValidator
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateAction(ActionDef action, DefCatalog catalog)
|
||||
{
|
||||
if (action.Abstract)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(action.Room))
|
||||
{
|
||||
throw new ContentLoadException($"ActionDef '{action.DefName}' needs a room.");
|
||||
}
|
||||
|
||||
var roomKnown = catalog.Rooms.TryGetValue(action.Room, out var room) && !room.Abstract;
|
||||
var territoryKnown = catalog.Territories.TryGetValue(action.Room, out var territory) && !territory.Abstract;
|
||||
if (!roomKnown && !territoryKnown)
|
||||
{
|
||||
throw new ContentLoadException($"ActionDef '{action.DefName}' references unknown room '{action.Room}'.");
|
||||
}
|
||||
|
||||
if (action.Minutes <= 0)
|
||||
{
|
||||
throw new ContentLoadException($"ActionDef '{action.DefName}' minutes must be positive.");
|
||||
}
|
||||
|
||||
if (action.Weight < 0)
|
||||
{
|
||||
throw new ContentLoadException($"ActionDef '{action.DefName}' weight cannot be negative.");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(action.Thing))
|
||||
{
|
||||
if (!catalog.Things.TryGetValue(action.Thing, out var thing) || thing.Abstract)
|
||||
{
|
||||
throw new ContentLoadException($"ActionDef '{action.DefName}' references unknown ThingDef '{action.Thing}'.");
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(action.Need))
|
||||
{
|
||||
if (action.NeedGain != 0)
|
||||
{
|
||||
throw new ContentLoadException($"ActionDef '{action.DefName}' has needGain without a need.");
|
||||
}
|
||||
}
|
||||
else if (!catalog.Needs.TryGetValue(action.Need, out var need) || need.Abstract)
|
||||
{
|
||||
throw new ContentLoadException($"ActionDef '{action.DefName}' references unknown NeedDef '{action.Need}'.");
|
||||
}
|
||||
|
||||
foreach (var role in action.Roles)
|
||||
{
|
||||
if (!PersonRoles.IsKnown(role))
|
||||
{
|
||||
throw new ContentLoadException($"ActionDef '{action.DefName}' has unknown role '{role}'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateBehavior(BehaviorDef behavior)
|
||||
{
|
||||
if (behavior.Abstract)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (behavior.NeedThreshold < 0f || behavior.NeedThreshold > 1f)
|
||||
{
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' needThreshold must be 0–1.");
|
||||
}
|
||||
|
||||
if (behavior.LessonSkillPerHour < 0f)
|
||||
{
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' lessonSkillPerHour cannot be negative.");
|
||||
}
|
||||
|
||||
if (behavior.SwitchMargin < 0f)
|
||||
{
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' switchMargin cannot be negative.");
|
||||
}
|
||||
|
||||
if (behavior.CommuteSlackMin < 0 || behavior.CommuteSlackMax < behavior.CommuteSlackMin)
|
||||
{
|
||||
throw new ContentLoadException(
|
||||
$"BehaviorDef '{behavior.DefName}' commute slack must be a non-negative range with min ≤ max.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateHoliday(HolidayDef holiday)
|
||||
{
|
||||
if (holiday.Abstract)
|
||||
|
||||
Reference in New Issue
Block a user