using Arch.Core;
using HSchool.Ai;
using HSchool.Content;
using HSchool.People;
namespace HSchool.Simulation;
/// Turns roster records into Arch entities. Parents have no map location — by design.
public static class RosterSpawner
{
private static readonly QueryDescription People = new QueryDescription().WithAll();
private static readonly QueryDescription Classes = new QueryDescription().WithAll();
public static void Spawn(World world, Roster roster, DefCatalog? catalog = null)
{
foreach (var schoolClass in roster.Classes)
{
world.Create(
new ClassIdentity(
schoolClass.Id,
schoolClass.Year,
schoolClass.Letter,
schoolClass.RoomId,
schoolClass.Capacity));
}
foreach (var person in roster.People)
{
world.Create(
new PersonIdentity(person.Id, person.FamilyId, person.Female, person.BirthDate, person.Name),
new PersonBody(person.Numbers, person.Choices),
new PersonSkills(person.Skills.ToDictionary(pair => pair.Key, pair => (float)pair.Value, StringComparer.Ordinal)),
new PersonTraits(person.Traits),
new PersonNeeds(NeedsOf(person, catalog)),
PersonInsulation.FromPerson(person, catalog),
new PersonRoles(
person.IsStudent,
person.IsStaff,
person.IsParent,
person.ClassId,
person.Position,
person.WorkplaceRoomId),
Presence.OffCampus,
PersonActivity.Idle,
Intent.None);
}
}
/// Drops the previous composition and spawns . Called on yearly intake.
public static void Replace(World world, Roster roster, DefCatalog? catalog = null)
{
DestroyAll(world, People);
DestroyAll(world, Classes);
Spawn(world, roster, catalog);
}
private static Dictionary NeedsOf(Person person, DefCatalog? catalog)
{
var values = new Dictionary(person.Needs, StringComparer.Ordinal);
if (catalog is null)
{
return values;
}
foreach (var need in catalog.Needs.Values)
{
if (!need.Abstract && !values.ContainsKey(need.DefName))
{
values[need.DefName] = need.Initial;
}
}
return values;
}
private static void DestroyAll(World world, QueryDescription query)
{
var entities = new List();
world.Query(in query, (Entity entity) => entities.Add(entity));
foreach (var entity in entities)
{
world.Destroy(entity);
}
}
}