Short offense list for the pupil card and save, capped by BehaviorDef — not a discipline score.
104 lines
2.9 KiB
C#
104 lines
2.9 KiB
C#
using System.Text.Json.Serialization;
|
|
using HSchool.Content;
|
|
|
|
namespace HSchool.People;
|
|
|
|
/// <summary>Stable kind ids written into <see cref="OffenseRecord.Kind"/> and listed on <see cref="BehaviorDef.OffenseMemoryKinds"/>.</summary>
|
|
public static class OffenseKinds
|
|
{
|
|
public const string Quarrel = "quarrel";
|
|
|
|
public const string Fight = "fight";
|
|
|
|
public const string Reprimand = "reprimand";
|
|
|
|
public static string LocaleKey(string kind) => kind switch
|
|
{
|
|
Quarrel => "OffenseQuarrel",
|
|
Fight => "OffenseFight",
|
|
Reprimand => "OffenseReprimand",
|
|
_ => "Offense" + char.ToUpperInvariant(kind[0]) + kind[1..],
|
|
};
|
|
}
|
|
|
|
/// <summary>One remembered misconduct. Sparse list on the person — not a discipline score.</summary>
|
|
public sealed class OffenseRecord
|
|
{
|
|
public required string Kind { get; init; }
|
|
|
|
public required DateTime Time { get; init; }
|
|
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? OtherPersonId { get; init; }
|
|
}
|
|
|
|
/// <summary>Appends recent offenses and drops the oldest when over the BehaviorDef ceiling.</summary>
|
|
public static class OffenseMemory
|
|
{
|
|
public static bool IsEnabled(string kind, BehaviorDef rules)
|
|
{
|
|
foreach (var allowed in rules.OffenseMemoryKinds)
|
|
{
|
|
if (allowed.Equals(kind, StringComparison.Ordinal))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static bool Record(Person person, string kind, DateTime time, string? otherPersonId, BehaviorDef rules)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(person);
|
|
ArgumentNullException.ThrowIfNull(rules);
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(kind);
|
|
|
|
if (rules.OffenseMemoryMax <= 0 || !IsEnabled(kind, rules))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var list = person.Offenses;
|
|
if (list is null)
|
|
{
|
|
list = [];
|
|
person.Offenses = list;
|
|
}
|
|
|
|
list.Add(new OffenseRecord
|
|
{
|
|
Kind = kind,
|
|
Time = DateTime.SpecifyKind(time, DateTimeKind.Utc),
|
|
OtherPersonId = string.IsNullOrWhiteSpace(otherPersonId) ? null : otherPersonId,
|
|
});
|
|
|
|
while (list.Count > rules.OffenseMemoryMax)
|
|
{
|
|
list.RemoveAt(0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static string? OtherParticipant(string personId, string? victimId, IReadOnlyList<string> members)
|
|
{
|
|
if (victimId is not null
|
|
&& !victimId.Equals(personId, StringComparison.Ordinal)
|
|
&& members.Contains(victimId, StringComparer.Ordinal))
|
|
{
|
|
return victimId;
|
|
}
|
|
|
|
foreach (var member in members)
|
|
{
|
|
if (!member.Equals(personId, StringComparison.Ordinal))
|
|
{
|
|
return member;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|