Update decision-making phase and enhance localization for presence tracking
ci / server (push) Failing after 3m40s
ci / client (push) Successful in 14s

- Marked tasks as complete in the decision-making phase documentation, indicating readiness for implementation.
- Updated the README to reflect the completion status of the decision-making phase.
- Enhanced localization strings to include new presence tracking features, improving user experience.
- Revised the game screen logic to display real-time presence status, including walking states for individuals.
- Added tests to validate the new localization strings and presence functionalities, ensuring robust performance.
This commit is contained in:
Leonid Pershin
2026-08-19 21:00:12 +03:00
parent b135a9caad
commit 5cd5a6d258
21 changed files with 1839 additions and 72 deletions
+49 -3
View File
@@ -14,6 +14,9 @@ internal static 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>();
@@ -45,6 +48,7 @@ internal static class PersonCardReader
}
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))
@@ -72,7 +76,7 @@ internal static class PersonCardReader
person.Position,
PeopleListMapper.PositionLabel(catalog, locale, person.Position),
Body(person, catalog, locale),
Skills(person, catalog, locale),
Skills(person, skills, catalog, locale),
Traits(person, catalog, locale),
Needs(needs, catalog, locale),
activityId,
@@ -93,6 +97,19 @@ internal static class PersonCardReader
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;
@@ -153,10 +170,21 @@ internal static class PersonCardReader
return rows;
}
private static IReadOnlyList<LabeledStatResponse> Skills(Person person, DefCatalog? catalog, string locale)
private static IReadOnlyList<LabeledStatResponse> Skills(
Person person,
IReadOnlyDictionary<string, float>? live,
DefCatalog? catalog,
string locale)
{
if (catalog is null)
{
if (live is not null)
{
return live
.Select(pair => new LabeledStatResponse(pair.Key, pair.Key, FormatSkill(pair.Value)))
.ToArray();
}
return person.Skills
.Select(pair => new LabeledStatResponse(pair.Key, pair.Key, pair.Value.ToString()))
.ToArray();
@@ -165,7 +193,23 @@ internal static class PersonCardReader
var rows = new List<LabeledStatResponse>();
foreach (var def in catalog.Skills.Values)
{
if (def.Abstract || !person.Skills.TryGetValue(def.DefName, out var value))
if (def.Abstract)
{
continue;
}
if (live is not null)
{
if (!live.TryGetValue(def.DefName, out var liveValue))
{
continue;
}
rows.Add(new LabeledStatResponse(def.DefName, catalog.Label(locale, def), FormatSkill(liveValue)));
continue;
}
if (!person.Skills.TryGetValue(def.DefName, out var value))
{
continue;
}
@@ -176,6 +220,8 @@ internal static class PersonCardReader
return rows;
}
private static string FormatSkill(float value) => Math.Round(value, 2).ToString("0.##");
private static IReadOnlyList<DefLabelResponse> Traits(Person person, DefCatalog? catalog, string locale)
{
var rows = new List<DefLabelResponse>(person.Traits.Count);