using HSchool.Content; namespace HSchool.People.Tests; public class LockerAssignerTests { private static readonly DateTime September = new(2012, 9, 1, 6, 0, 0, DateTimeKind.Utc); [Fact] public void TenLockersForFortyGirls_SeniorsFirst_EleventhHasNone() { var catalog = Fixtures.Catalog(); var map = WithGirlLockerCount(Fixtures.VanillaMap(), 10); var roster = Fixtures.Generate(map); roster = LockerAssigner.Apply(catalog, map, roster); var classes = roster.Classes.ToDictionary(schoolClass => schoolClass.Id, StringComparer.Ordinal); var girls = roster.People .Where(person => person.IsStudent && person.Female) .Select(person => { var year = person.ClassId is { } classId && classes.TryGetValue(classId, out var schoolClass) ? schoolClass.Year : 0; return (Person: person, Year: year); }) .OrderByDescending(entry => entry.Year) .ThenBy(entry => entry.Person.Id, StringComparer.Ordinal) .ToArray(); Assert.True(girls.Length >= 11, $"need at least eleven girls, got {girls.Length}"); var withLocker = girls .Where(entry => entry.Person.LockerRoomId is not null) .ToArray(); Assert.Equal(10, withLocker.Length); Assert.All(withLocker, entry => Assert.Equal("girls-changing-room", entry.Person.LockerRoomId)); Assert.Null(girls[10].Person.LockerRoomId); } [Fact] public void Boy_DoesNotReceiveTheGirlsChangingRoomSlot() { var catalog = Fixtures.Catalog(); var map = Fixtures.VanillaMap(); var roster = LockerAssigner.Apply(catalog, map, Fixtures.Generate(map)); foreach (var boy in roster.People.Where(person => person.IsStudent && !person.Female)) { Assert.NotEqual("girls-changing-room", boy.LockerRoomId); if (boy.LockerRoomId is not null) { Assert.Equal("boys-changing-room", boy.LockerRoomId); } } } [Fact] public void AfterSeptemberIntake_GraduateDoesNotKeepASlot() { var catalog = Fixtures.Catalog(); var map = Fixtures.VanillaMap(); var before = LockerAssigner.Apply(catalog, map, Fixtures.Generate(map)); var maxYear = before.Classes.Max(schoolClass => schoolClass.Year); var graduate = before.People.First(person => person.IsStudent && person.Female && person.LockerRoomId is not null && person.ClassId is { } classId && before.Classes.Single(schoolClass => schoolClass.Id == classId).Year == maxYear); var after = LockerAssigner.Apply( catalog, map, YearlyIntake.Apply(catalog, before, Fixtures.SchoolSeed, "Russia", September)); Assert.DoesNotContain(after.People, person => person.Id.Equals(graduate.Id, StringComparison.Ordinal)); } [Fact] public void Staff_NeverReceiveLockerSlots() { var catalog = Fixtures.Catalog(); var map = Fixtures.VanillaMap(); var roster = Fixtures.Generate(map); var pool = ApplicantPool.Create(catalog, roster, Fixtures.SchoolSeed, "Russia", Fixtures.AsOf); var hired = Staffing.Hire(catalog, map, roster, pool, pool.Applicants[0].Person.Id, Staffing.TeacherPosition, 100_000f); var assigned = LockerAssigner.Apply(catalog, map, hired.Roster); Assert.All( assigned.People.Where(person => person.IsStaff), person => Assert.Null(person.LockerRoomId)); } private static MapLayout WithGirlLockerCount(MapLayout map, int count) { var rooms = map.Rooms .Select(room => { if (!room.Id.Equals("girls-changing-room", StringComparison.Ordinal)) { return room; } return new RoomNode { Id = room.Id, Def = room.Def, Building = room.Building, Floor = room.Floor, Label = room.Label, Seats = room.Seats, Slots = [new SlotFill { Key = "lockers", Thing = "Locker", Count = count }], }; }) .ToArray(); return new MapLayout { Territory = map.Territory, Buildings = map.Buildings, Floors = map.Floors, Rooms = rooms, Links = map.Links, }; } }