168 lines
6.2 KiB
C#
168 lines
6.2 KiB
C#
using Arch.Core;
|
|
using HSchool.Ai;
|
|
using HSchool.Content;
|
|
using HSchool.People;
|
|
using HSchool.Server.Api;
|
|
using HSchool.Simulation;
|
|
|
|
namespace HSchool.Server.Game;
|
|
|
|
/// <summary>
|
|
/// Builds a person card on the school's worker thread so live need values come from the World.
|
|
/// </summary>
|
|
internal static partial class PersonCardReader
|
|
{
|
|
private static readonly QueryDescription IdentityAndNeeds =
|
|
new QueryDescription().WithAll<PersonIdentity, PersonNeeds>();
|
|
|
|
private static readonly QueryDescription IdentityAndSkills =
|
|
new QueryDescription().WithAll<PersonIdentity, PersonSkills>();
|
|
|
|
private static readonly QueryDescription IdentityAndActivity =
|
|
new QueryDescription().WithAll<PersonIdentity, PersonActivity>();
|
|
|
|
private static readonly QueryDescription IdentityAndPresence =
|
|
new QueryDescription().WithAll<PersonIdentity, Presence>();
|
|
|
|
public static PersonCardResponse? Read(School school, string personId, string locale)
|
|
{
|
|
var roster = school.Roster;
|
|
if (roster is null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var person = roster.People.FirstOrDefault(candidate => candidate.Id.Equals(personId, StringComparison.Ordinal));
|
|
person ??= school.Applicants?.Applicants
|
|
.FirstOrDefault(applicant => applicant.Person.Id.Equals(personId, StringComparison.Ordinal))
|
|
?.Person;
|
|
if (person is null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var catalog = school.Catalog;
|
|
var classes = roster.Classes.ToDictionary(schoolClass => schoolClass.Id, StringComparer.Ordinal);
|
|
var people = roster.People.ToDictionary(person => person.Id, StringComparer.Ordinal);
|
|
int? year = null;
|
|
string? letter = null;
|
|
string? classTeacherId = null;
|
|
string? classTeacherName = null;
|
|
if (person.ClassId is { } classId && classes.TryGetValue(classId, out var schoolClass))
|
|
{
|
|
year = schoolClass.Year;
|
|
letter = schoolClass.Letter;
|
|
classTeacherId = schoolClass.ClassTeacherId;
|
|
if (classTeacherId is { } teacherId && people.TryGetValue(teacherId, out var teacher))
|
|
{
|
|
classTeacherName = teacher.Name.Full;
|
|
}
|
|
}
|
|
|
|
var needs = LiveNeeds(school.World, personId) ?? person.Needs;
|
|
var skills = LiveSkills(school.World, personId);
|
|
var activityId = LiveActivity(school.World, personId);
|
|
string? activityLabel = null;
|
|
if (activityId is not null && catalog is not null && catalog.Actions.TryGetValue(activityId, out var action))
|
|
{
|
|
activityLabel = catalog.Label(locale, action);
|
|
}
|
|
else if (activityId is not null)
|
|
{
|
|
activityLabel = activityId;
|
|
}
|
|
|
|
var circle = school.TalkCircleOf(personId);
|
|
|
|
return new PersonCardResponse(
|
|
person.Id,
|
|
person.Name.Full,
|
|
person.Name.Surname,
|
|
person.Name.Given,
|
|
person.Name.Patronymic,
|
|
person.Female,
|
|
person.AgeOn(school.Clock.Time),
|
|
person.BirthDate,
|
|
PeopleListMapper.RolesOf(person),
|
|
year,
|
|
letter,
|
|
person.ClassId,
|
|
person.Position,
|
|
PeopleListMapper.PositionLabel(catalog, locale, person.Position),
|
|
Body(person, catalog, locale),
|
|
Skills(person, skills, catalog, locale),
|
|
Traits(person, catalog, locale),
|
|
Needs(needs, catalog, locale),
|
|
activityId,
|
|
activityLabel,
|
|
Family(roster, person),
|
|
Worn(person, catalog, locale),
|
|
Carried(person, catalog, locale),
|
|
catalog is null ? 0f : CarryMass.Held(catalog, person.Items),
|
|
Capacity(person, skills, catalog),
|
|
person.LockerRoomId is not null
|
|
|| person.Items.Any(item => item.Location.Equals(ItemLocations.Locker, StringComparison.Ordinal)),
|
|
person.Items.Count(item => item.Location.Equals(ItemLocations.Home, StringComparison.Ordinal)),
|
|
Connections: Connections(roster, person, catalog, locale),
|
|
Orientation: OrientationOf(person, catalog, locale),
|
|
TalkCircleMemberIds: circle?.MemberIds ?? [],
|
|
TalkTopicId: circle?.TopicId,
|
|
ClassTeacherId: classTeacherId,
|
|
ClassTeacherName: classTeacherName);
|
|
}
|
|
|
|
private static IReadOnlyDictionary<string, float>? LiveNeeds(World world, string personId)
|
|
{
|
|
Dictionary<string, float>? found = null;
|
|
world.Query(in IdentityAndNeeds, (ref PersonIdentity identity, ref PersonNeeds needs) =>
|
|
{
|
|
if (identity.Id.Equals(personId, StringComparison.Ordinal))
|
|
{
|
|
found = new Dictionary<string, float>(needs.Values, StringComparer.Ordinal);
|
|
}
|
|
});
|
|
return found;
|
|
}
|
|
|
|
private static IReadOnlyDictionary<string, float>? LiveSkills(World world, string personId)
|
|
{
|
|
Dictionary<string, float>? found = null;
|
|
world.Query(in IdentityAndSkills, (ref PersonIdentity identity, ref PersonSkills skills) =>
|
|
{
|
|
if (identity.Id.Equals(personId, StringComparison.Ordinal))
|
|
{
|
|
found = new Dictionary<string, float>(skills.Values, StringComparer.Ordinal);
|
|
}
|
|
});
|
|
return found;
|
|
}
|
|
|
|
private static string? LiveActivity(World world, string personId)
|
|
{
|
|
string? found = null;
|
|
var query = IdentityAndActivity;
|
|
world.Query(in query, (ref PersonIdentity identity, ref PersonActivity activity) =>
|
|
{
|
|
if (identity.Id.Equals(personId, StringComparison.Ordinal) && activity.IsActive)
|
|
{
|
|
found = activity.ActionId;
|
|
}
|
|
});
|
|
return found;
|
|
}
|
|
|
|
public static string? NodeId(School school, string personId)
|
|
{
|
|
string? found = null;
|
|
var query = IdentityAndPresence;
|
|
school.World.Query(in query, (ref PersonIdentity identity, ref Presence presence) =>
|
|
{
|
|
if (identity.Id.Equals(personId, StringComparison.Ordinal))
|
|
{
|
|
found = presence.NodeId;
|
|
}
|
|
});
|
|
return found;
|
|
}
|
|
}
|