From 2a199fda8fa14cff6a3b45ebfd751a70222de2af Mon Sep 17 00:00:00 2001 From: Leonid Pershin Date: Fri, 21 Aug 2026 03:08:40 +0300 Subject: [PATCH] Record slice 2 recheck after notices and portraits. --- docs/phases/02-people/reviewed.md | 57 +++++++++++++++++++ docs/phases/reviewed.md | 2 +- src/HSchool.Client/src/ui/personCard.test.ts | 35 ++++++++++++ .../RosterGeneratorTests.cs | 7 +++ 4 files changed, 100 insertions(+), 1 deletion(-) diff --git a/docs/phases/02-people/reviewed.md b/docs/phases/02-people/reviewed.md index ebf799a..162b025 100644 --- a/docs/phases/02-people/reviewed.md +++ b/docs/phases/02-people/reviewed.md @@ -94,3 +94,60 @@ - Хостовые `PeopleApiTests` / `SchoolSeedTests` в этом проходе не гонялись (Testing policy: HTTP не менялся). Симуляционный переход 1 сентября и библиотечный набор зелёные. - `people.json` теперь ещё пишется после разговора и ссоры — это срез 9, не состав среза 2. + +## Срез 2. Люди — перепроверка после notices и портретов + +- **Фазы:** 5–9 +- **Проверен на:** `c3d17ca`, 2026-08-21 +- **Пути:** `src/HSchool.People`, `src/HSchool.Content/PeopleDefs.cs`, + `src/HSchool.Simulation/RosterSpawner.cs`, `src/HSchool.Simulation/School.cs`, + `src/HSchool.Server/Api/SchoolEndpoints.cs`, `src/HSchool.Server/Game/PersonCardReader.cs`, + `src/HSchool.Server/Game/SchoolWorker.cs`, + `src/HSchool.Client/src/ui/peoplePanel.ts`, `src/HSchool.Client/src/ui/personCard.ts`, + `tests/HSchool.People.Tests`, `tests/HSchool.Content.Tests/PeopleDefTests.cs`, + `tests/HSchool.Simulation.Tests/PeopleInSchoolTests.cs`, + `tests/HSchool.AppHost.Tests/PeopleApiTests.cs`, + `tests/HSchool.AppHost.Tests/SchoolSeedTests.cs` +- **Итог:** перепроверка после дрейфа с `8108508` (notices, scene prompt, портреты, одежда, + мнения). Обещания фаз 5–9 целы; код среза не чинился; дописаны тесты обзора карточки + и номеров кабинетов + +Что подтверждено: + +- Дефы, наследование, патч, неизвестная ссылка, взаимная несовместимость, склонение + правилом и таблицей, мод со своей страной и чертами. `GET /api/catalog` отдаёт страны, + не наборы имён — фаза 29, не регрессия среза 2. +- Генератор: тот же сид → тот же ростер; 13-я семья не двигает первые двенадцать; + отчества отцовские; полное телосложение зажимает ловкость; 1 и 11 кабинетов собираются; + неполные семьи 5–10% и не все материнские. Arch / ASP.NET / `DateTime.Now` в + `HSchool.People` нет. +- Одиннадцать кабинетов-номеров (`101`…`204`…), `Homeroom` не компьютерный класс, + сущности в `World`, `PersistPeople` с `peopleChanged` (набор / штат / разговор), не + с таймера часов. `RecordWorldEvents` в `Tick` не поднимает этот флаг. Штат при создании + пуст — фаза 11. Нужды в `core` с ненулевым `decayPerHour` — срез 5. +- Список читает опубликованный снимок (`FindPeople`), карточка — мейлбокс с + `TaskCompletionSource`. Фильтры роли/параллели/литеры/должности/пола/возраста в + `RosterBrowser`; панель — вкладка рядом с картой, строки через `t(...)`. Обзор карточки + по-прежнему тело, навыки, черты, нужды и семья-ссылка; кнопка notice среза 11 на карточку + не сажалась. +- Выпуск старшей имеющейся, вместимость, младший брат в том же роде, родитель-работник + выпускников остаётся, reload после набора (тесты прошлых проходов на месте). + +Дописано: + +- `renderPersonCard` / `opens a relative from the overview family links` — фаза 8 обещает + переход к родственнику; после вкладок одежды и портрета обзор с пустой `family` больше + не кликали. +- `RosterGeneratorTests.VanillaMap_HasElevenHomeroomsNotTheComputerLab` — подписи + кабинетов это трёхзначные номера, не имена классов. + +Исправлено: ничего в коде среза. + +Открытое: + +- Хостовые `PeopleApiTests` / `SchoolSeedTests` в этом проходе не гонялись (Testing policy: + HTTP списка и карточки не менялся). `RosterGeneratorTests` и клиентский `personCard.test.ts` + зелёные. +- `people.json` после разговора и ссоры — срез 9, не состав среза 2. +- Рядом: `PersonCardReaderShapeTests` всё ещё ждёт один публичный `Read`, а срез 11 + добавил `NodeId` для портрета. Это форма среза 10, не фазы 5–9; здесь не трогалось. diff --git a/docs/phases/reviewed.md b/docs/phases/reviewed.md index 3c2cbde..0ada14b 100644 --- a/docs/phases/reviewed.md +++ b/docs/phases/reviewed.md @@ -21,7 +21,7 @@ | Срез | Проверен на | Журнал | | --- | --- | --- | | Срез 1. Оболочка и карта | `d087486` | [01-shell](01-shell/reviewed.md) | -| Срез 2. Люди | `8108508` | [02-people](02-people/reviewed.md) | +| Срез 2. Люди | `c3d17ca` | [02-people](02-people/reviewed.md) | | Срез 3. Штат | `cf1403e` | [03-staffing](03-staffing/reviewed.md) | | Срез 4. Расписание | `01ef277` | [04-schedule](04-schedule/reviewed.md) | | Срез 5. Жизнь школы | `1118c59` | [05-ai](05-ai/reviewed.md) | diff --git a/src/HSchool.Client/src/ui/personCard.test.ts b/src/HSchool.Client/src/ui/personCard.test.ts index b942c4d..884a49c 100644 --- a/src/HSchool.Client/src/ui/personCard.test.ts +++ b/src/HSchool.Client/src/ui/personCard.test.ts @@ -151,6 +151,41 @@ describe('renderPersonCard', () => { expect(root.querySelector('[data-card-tab="now"]')?.hasAttribute('hidden')).toBe(false); }); + it('opens a relative from the overview family links', () => { + setLocale('ru'); + const onRelative = vi.fn(); + const root = document.createElement('div'); + renderPersonCard( + root, + card({ + skills: [{ id: 'Mathematics', label: 'Математика', value: '62' }], + traits: [{ defName: 'Diligent', label: 'Усидчивый' }], + needs: [{ id: 'Sleep', label: 'Сон', value: 1 }], + family: { + parents: [{ id: 'f0.p0', fullName: 'Иванова Ольга', female: true }], + children: [], + siblings: [], + partners: [], + }, + }), + onRelative, + options(), + ); + + const overview = root.querySelector('[data-card-tab="overview"]'); + expect(overview?.textContent).toContain('Рост'); + expect(overview?.textContent).toContain('Математика'); + expect(overview?.textContent).toContain('Усидчивый'); + expect(overview?.textContent).toContain('Сон'); + expect(overview?.textContent).toContain(t('peopleParents')); + + const mother = overview?.querySelector('.people__link'); + expect(mother).toBeInstanceOf(HTMLButtonElement); + expect(mother?.textContent).toBe('Иванова Ольга'); + (mother as HTMLButtonElement).click(); + expect(onRelative).toHaveBeenCalledWith('f0.p0'); + }); + it('shows the server condition caption, not a band inferred from the number', () => { setLocale('ru'); const root = document.createElement('div'); diff --git a/tests/HSchool.People.Tests/RosterGeneratorTests.cs b/tests/HSchool.People.Tests/RosterGeneratorTests.cs index f7de1c4..cf32508 100644 --- a/tests/HSchool.People.Tests/RosterGeneratorTests.cs +++ b/tests/HSchool.People.Tests/RosterGeneratorTests.cs @@ -127,6 +127,13 @@ public class RosterGeneratorTests Assert.DoesNotContain(demand.Staff, opening => opening.Position == "Teacher"); Assert.DoesNotContain(demand.Staff, opening => opening.RoomId == "computer-lab"); Assert.Contains(demand.Staff, opening => opening.RoomId == "library" && opening.Position == "Librarian"); + + // Phase 7: homeroom captions are room numbers, not class names the generator would + // otherwise try to parse. The map file itself is not this test's to rewrite. + var homerooms = map.Rooms.Where(room => room.Def == "Classroom").ToArray(); + Assert.Equal(11, homerooms.Length); + Assert.All(homerooms, room => Assert.Matches(@"^\d{3}$", room.Label)); + Assert.Contains(homerooms, room => room.Label == "204"); } [Fact]