Merge branch 'main' into phase/32-weather-warmth
This commit is contained in:
@@ -20,7 +20,7 @@ way; this file is *how to work in them*.
|
||||
| connection handling, workers, saves | `src/HSchool.Server` |
|
||||
| what runs locally | `src/HSchool.AppHost/AppHost.cs` |
|
||||
| screens, dialogs, formatting, UI language | `src/HSchool.Client/src` |
|
||||
| clothing, inventory, climate, dress codes | [`docs/design/inventory.md`](docs/design/inventory.md) — slice 7, phases 29–37; country is live, clothing is not |
|
||||
| clothing, inventory, climate, dress codes | [`docs/design/inventory.md`](docs/design/inventory.md) — slice 7, phases 29–37; country and wardrobes are live, weather is not |
|
||||
|
||||
## Commands
|
||||
|
||||
|
||||
@@ -347,10 +347,12 @@ Protocol ← Server → Simulation → People → Content
|
||||
|
||||
## Заведомо не сейчас
|
||||
|
||||
- Поведение: расписание, уроки, перемещение по карте, исполнение действий.
|
||||
- Влияние характеристик на что-либо. Черты и навыки в этом срезе — текст в карточке.
|
||||
Срез 2 закрыт. Строки, которые отменили следующие срезы, помечены.
|
||||
|
||||
- Поведение: расписание, уроки, перемещение по карте — отменено срезами 4–5, см. [`schedule.md`](schedule.md), [`ai.md`](ai.md).
|
||||
- Влияние характеристик на что-либо. Черты и навыки в этом срезе — текст в карточке — отменено срезом 5 (маршрут, обучение).
|
||||
- Вызов родителя в школу. Задел есть (родитель — сущность), реализации нет.
|
||||
- Наём и увольнение вручную. Должности закрываются генератором.
|
||||
- Наём и увольнение вручную. Должности закрываются генератором — отменено срезом 3, см. [`staffing.md`](staffing.md). Школа открывается без штата.
|
||||
- Смеси наборов имён с весами.
|
||||
- Новые роли из модов: ученик, работник, родитель — код, не данные.
|
||||
- Портреты и любой арт.
|
||||
|
||||
@@ -12,30 +12,30 @@
|
||||
|
||||
## Задачи
|
||||
|
||||
- [ ] Экземпляр вещи на человеке: `def`, `color`, `condition` (1), место (`worn` / `bag` /
|
||||
- [x] Экземпляр вещи на человеке: `def`, `color`, `condition` (1), место (`worn` / `bag` /
|
||||
`locker` / `home`), для учебника — `subject`
|
||||
- [ ] Генератор одевает учеников, сотрудников, родителей и соискателей от семейного сида:
|
||||
- [x] Генератор одевает учеников, сотрудников, родителей и соискателей от семейного сида:
|
||||
слои без пересечения, пол, возраст, дефолтные правила (обычная форма, без яркого на теле)
|
||||
- [ ] Учебники — по одному на предмет параллели ученика; в сумке пока могут лежать все, разнос
|
||||
- [x] Учебники — по одному на предмет параллели ученика; в сумке пока могут лежать все, разнос
|
||||
«сегодняшние vs шкафчик» — в фазе 33/35
|
||||
- [ ] Портфель, телефон, бутылка — с возрастом и шансом из данных, не из константы в генераторе
|
||||
- [ ] Навык `Hauling` (`always`); предел массы в дефе правил; на карточке несёшь/можешь.
|
||||
- [x] Портфель, телефон, бутылка — с возрастом и шансом из данных, не из константы в генераторе
|
||||
- [x] Навык `Hauling` (`always`); предел массы в дефе правил; на карточке несёшь/можешь.
|
||||
Перегруз ходьбу не трогает; в сумку сверх предела генератор не кладёт
|
||||
- [ ] `GET .../people/{id}` отдаёт надетое и ношу; список людей — нет
|
||||
- [ ] Карточка пока без вкладок: секции «Одежда» и «Ноша» в том же свитке
|
||||
- [ ] `people.json` пишется при создании и наборе; золотой отпечаток обновляется в этом коммите
|
||||
- [x] `GET .../people/{id}` отдаёт надетое и ношу; список людей — нет
|
||||
- [x] Карточка пока без вкладок: секции «Одежда» и «Ноша» в том же свитке
|
||||
- [x] `people.json` пишется при создании и наборе; золотой отпечаток обновляется в этом коммите
|
||||
с объяснением, что изменилось
|
||||
- [ ] Строки через `t(...)` / локали каталога
|
||||
- [x] Строки через `t(...)` / локали каталога
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [ ] Тот же сид, страна, карта и язык → те же id вещей, цвета и места
|
||||
- [ ] На одном слое не две вещи; платье занимает низ и верх сразу
|
||||
- [ ] Юбка не выдаётся мужчинам на тело; яркий верх не выдаётся на тело при дефолтных правилах
|
||||
- [ ] Ученик параллели с математикой имеет учебник этого предмета
|
||||
- [ ] Родитель и соискатель одеты
|
||||
- [ ] Масса в сумке ≤ предела
|
||||
- [ ] Старый `people.json` без инвентаря поднимается: генератор одевает при загрузке и пишет
|
||||
- [x] Тот же сид, страна, карта и язык → те же id вещей, цвета и места
|
||||
- [x] На одном слое не две вещи; платье занимает низ и верх сразу
|
||||
- [x] Юбка не выдаётся мужчинам на тело; яркий верх не выдаётся на тело при дефолтных правилах
|
||||
- [x] Ученик параллели с математикой имеет учебник этого предмета
|
||||
- [x] Родитель и соискатель одеты
|
||||
- [x] Масса в сумке ≤ предела
|
||||
- [x] Старый `people.json` без инвентаря поднимается: генератор одевает при загрузке и пишет
|
||||
файл (как пул соискателей в фазе 11)
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
| --- | --- | --- |
|
||||
| [29. Страна](29-country.md) | ✅ | `CountryDef`, create выбирает страну, климат-пресет от сида |
|
||||
| [30. Слои и палитра](30-apparel-defs.md) | ✅ | Поля `ThingDef`, `ColorDef`, ванильная одежда и ноша |
|
||||
| [31. Генератор одевает](31-dress-generator.md) | ⬜ | Гардероб на человеке, ноша-число, `people.json` |
|
||||
| [31. Генератор одевает](31-dress-generator.md) | ✅ | Гардероб на человеке, ноша-число, `people.json` |
|
||||
|
||||
29 и 30 независимы; 31 стоит на обеих.
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
|
||||
| Фаза | Статус | Зачем |
|
||||
| --- | --- | --- |
|
||||
| [32. Погода и тепло](32-weather-warmth.md) | ⬜ | Пресет крутит улицу, кадр часов, нужда, две черты |
|
||||
| [32. Погода и тепло](32-weather-warmth.md) | 🔄 | Пресет крутит улицу, кадр часов, нужда, две черты |
|
||||
| [33. Техник и шкафчики](33-lockers-technician.md) | ⬜ | Комната техника, две раздевалки, раздача шкафчиков |
|
||||
|
||||
32 стоит на 29; 33 — на 31 и 32.
|
||||
@@ -146,9 +146,9 @@
|
||||
|
||||
| Фаза | Статус | Зачем |
|
||||
| --- | --- | --- |
|
||||
| [34. Износ и дом](34-wear-home.md) | ⬜ | Прочность, утренняя замена, из ветхого не выходят |
|
||||
| [34. Износ и дом](34-wear-home.md) | 🔄 | Прочность, утренняя замена, из ветхого не выходят |
|
||||
| [35. Уместность](35-appropriateness.md) | ⬜ | Правила, переодевание действием, физкультура |
|
||||
| [36. Вкладки карточки](36-person-card-tabs.md) | ⬜ | Одежда, ноша, сейчас + история за сегодня |
|
||||
| [36. Вкладки карточки](36-person-card-tabs.md) | 🔄 | Одежда, ноша, сейчас + история за сегодня |
|
||||
| [37. Правила школы](37-school-rules.md) | ⬜ | Вкладка в «Управлении», четыре комбобокса, с завтра |
|
||||
|
||||
34 стоит на 31; 35 — на 32–34; 36 — на 31 и может идти параллельно с 35 в части вкладок одежды,
|
||||
|
||||
+128
-619
@@ -6,143 +6,62 @@
|
||||
Коммит в «Проверен на» делает журнал самопроверяющимся. Срез перестаёт считаться проверенным,
|
||||
как только `git log <коммит>..HEAD -- <пути>` перестаёт быть пустым — поэтому «Пути» обязательны.
|
||||
|
||||
Закрытые замечания из прошлых проходов сюда не возвращаются. История перепроверок свёрнута в
|
||||
строку «Проверен на». Последняя проверка срезов 1–6 была до фаз 29–30 (страна, одежда): дрейф
|
||||
по путям есть, это очередь следующего прохода, а не задняя датировка.
|
||||
|
||||
Оговорки, которые относятся сразу к нескольким срезам (не дублировать ниже):
|
||||
|
||||
- Хостовый `OpeningASchoolDuringAMathLesson_...` после правки явки не гонялся: Aspire держал DLL
|
||||
(`MSB3021`). Симуляционные тесты явки зелёные.
|
||||
- `npm test` в клиенте не гоняет `tsc`. Дубликат поля и любой TS2300 зелёный в vitest и красный
|
||||
на `npm run build`.
|
||||
- `GET /api/catalog` отдаёт каркас дня без `lunchBreaks` (только `longBreakAfter`). Сетке смены
|
||||
не нужны; молча расширять HTTP ревью не стало.
|
||||
|
||||
## Срез 1. Оболочка и карта
|
||||
|
||||
- **Фазы:** 0–4
|
||||
- **Проверен на:** `418a4ea`, 2026-08-20 (первичная проверка — `b135a9c`; предыдущая перепроверка — `5a00ad7`)
|
||||
- **Проверен на:** `418a4ea`, 2026-08-20
|
||||
- **Пути:** `src/HSchool.Client`, `src/HSchool.Protocol`, `src/HSchool.Content`,
|
||||
`src/HSchool.Server/Game`, `src/HSchool.Server/Api/ModEndpoints.cs`,
|
||||
`src/HSchool.Server/Api/SchoolEndpoints.cs`, `src/HSchool.Server/Net`,
|
||||
`tests/HSchool.Content.Tests`, `tests/HSchool.Protocol.Tests`,
|
||||
`tests/HSchool.AppHost.Tests/SchoolApiTests.cs`, `tests/HSchool.AppHost.Tests/GameSocketTests.cs`
|
||||
- **Итог:** дописано 2 теста (оба прогнаны на чистом `b135a9c`), расхождений кода с дизайном
|
||||
не найдено кроме одного —
|
||||
панель «Общие события» из фазы 1 снята с экрана в фазе 8 и решение нигде не записано
|
||||
(оставлено открытым, см. ниже)
|
||||
- **Итог:** обещания фаз 0–4 целы; дописаны 3 теста; протокол v7 в трёх местах
|
||||
|
||||
Что подтверждено:
|
||||
|
||||
- **Фаза 0.** `pixi.js` нет ни в `package.json`, ни в lockfile, ни в импортах; `npm run build`
|
||||
проходит.
|
||||
- **Фаза 1.** Дерево карты, панель локации со всеми пятью секциями и пустыми состояниями, клик по
|
||||
дереву фильтрует на клиенте, `localize()` перекрашивает подписи. Панели «Общие события» на
|
||||
экране нет — единственное расхождение среза.
|
||||
- **Фаза 2.** `SchoolWorker` — `LongRunning`-поток, свой `PeriodicTimer`, свой `World`, аккумулятор
|
||||
с потолком в 5 шагов. Супервизор держит таблицу и не трогает `World` (инвариант 3). Сейв пишется
|
||||
на create, на shutdown и по `SaveIntervalSeconds`; настройки коалесцируются. Требуемый фазой тест
|
||||
«create → reload → та же школа с тем же временем» — это
|
||||
`GameSocketTests.ReloadFromDisk_RestoresAPausedClock` (точное равенство времени, паузы и
|
||||
скорости), плюс `SchoolApiTests.ReloadFromDisk_RestoresCreatedSchools`. Независимость школ —
|
||||
`GameSocketTests.PausingOneSchool_DoesNotStopAnother`.
|
||||
- **Фаза 3.** Все восемь тестов из списка фазы на месте в `HSchool.Content.Tests` (JSONC-фикстуры,
|
||||
last-wins по `defName` и по ключу локали, parent/abstract и цикл, патч `add` в `actions`,
|
||||
связность, пустая комната, одна комната без двора). Ванильная раскладка валидируется
|
||||
(`VanillaCoreTests.CoreDefaultMap_PassesValidation`). Пропавшая папка мода не стартует школу и
|
||||
не трогает файл: исключение летит до создания `School`, поэтому `finally` с `Persist()`
|
||||
недостижим, а супервизор только снимает школу с таблицы.
|
||||
- **Фаза 4.** `GET /api/mods`, `GET /api/catalog?lang=`, `POST /api/schools` с картой и модами,
|
||||
снимок карты при OpenSchool в языке Hello — всё покрыто тестами
|
||||
(`OpeningASchool_SendsAMapSnapshot`, `LabelsTheSnapshotInTheHelloLocale`,
|
||||
`WithACustomMap_ReturnsThatLayout`, `ReloadFromDisk_RestoresACustomMap`). Кодек, `protocol.ts` и
|
||||
`docs/protocol.md` описывают один и тот же `MapSnapshot`, байтовые смещения проверены с обеих
|
||||
сторон; версия 7 совпадает в `ProtocolConstants` и `PROTOCOL_VERSION`.
|
||||
- **Инварианты.** `Content`/`People`/`Schedule`/`Ai` не ссылаются на Arch и ASP.NET, `Simulation` —
|
||||
только на Arch; `DateTime.Now`/`UtcNow` в этих проектах нет.
|
||||
- **«Things that will bite you».** Ни одна из относящихся к срезу регрессий не вернулась:
|
||||
`modal.ts` резолвит промис явно, `.dialog--screen` держит `height: fit-content`,
|
||||
`DefaultStartDate` форсирует UTC-kind, аккумулятор работника на месте, `MapSnapshotSize`
|
||||
считается от сообщения, `GameClient` переносит оба `WaitToReadAsync` между итерациями, outbox
|
||||
роняет старейший кадр, меню патчит карточки через `card.update`.
|
||||
- PixiJS нет; дерево карты, пять секций локации, клиентский фильтр, `localize()`. Оболочка —
|
||||
вкладки Карта/Люди, не три панели; отказ от ленты событий записан в фазе 1 и в `design/near-term.md`.
|
||||
- `SchoolWorker` — `LongRunning`, свой `World`, аккумулятор с потолком 5. Супервизор таблицу
|
||||
держит и `World` не трогает. Сейв на create/shutdown/`SaveIntervalSeconds`;
|
||||
`ReloadFromDisk_RestoresAPausedClock`, `PausingOneSchool_DoesNotStopAnother`.
|
||||
- Восемь тестов каталога/карты в `HSchool.Content.Tests`. Ванильная раскладка валидна.
|
||||
Пропавшая папка мода не стартует школу и файл не трогает.
|
||||
- `GET /api/mods`, каталог, create с картой и модами, снимок при OpenSchool. `core` в диалоге
|
||||
создания нельзя снять. Кодек, `protocol.ts` и `docs/protocol.md` описывают один `MapSnapshot`.
|
||||
- `modal.ts` резолвит промис явно; `.dialog--screen` — `height: fit-content`;
|
||||
`DefaultStartDate` UTC; `MapSnapshotSize` от сообщения; outbox `DropOldest`;
|
||||
`WaitToReadAsync` переносится между итерациями; меню патчит `card.update`.
|
||||
- Родной язык — HTTP/JSON без бампа протокола. Старый сейв без поля берёт первый язык набора,
|
||||
не бросает кубик (`ReloadWithoutASavedPick_TakesTheFirstLanguageInsteadOfRolling`).
|
||||
|
||||
Дописано:
|
||||
|
||||
- `SchoolApiTests.Catalog_WithAnUnknownMod_IsRejected` — `GET /api/catalog?mods=` с неизвестной
|
||||
пачкой описан в `docs/protocol.md` как `400 unknown-mod`, но не проверялся.
|
||||
- `SchoolApiTests.ModId_ThatEscapesTheModsFolder_IsRejectedOnBothEndpoints` — инвариант 6: id
|
||||
пачки приходит из браузера и подставляется в путь. `ModContent.IsSafePackId` его чистит на обоих
|
||||
входах (каталог и создание школы), тестом это закреплено не было.
|
||||
|
||||
Открыто:
|
||||
|
||||
- **Панель «Общие события» пропала.** Фаза 1 требует три области, `design/near-term.md` держит их
|
||||
в «Что уже зафиксировано», а `design/people.md` описывает список людей как панель «рядом с картой
|
||||
и событиями». Коммит `d8f8db6` (фаза 8) заменил панель вкладками Карта/Люди, не сказав об этом;
|
||||
ключи `eventsTitle`/`eventsEmpty` остались в `i18n/strings.ts` мёртвыми. Решать надо одно из
|
||||
двух: вернуть пустую панель (или третью вкладку) — или записать отказ от неё в дизайн и убрать
|
||||
ключи. Молча менять экран ревью не стало.
|
||||
|
||||
Замечено рядом (за границами среза):
|
||||
|
||||
- `SchoolRegistry` после фазы 2 в бою не используется: сервер тикает школы работниками, а из
|
||||
класса вызывается только `TryNormalizeName`. `SchoolRegistryTests.Tick_AdvancesOnlyRunningSchools`
|
||||
проверяет путь, которым сервер больше не ходит.
|
||||
- **`PeopleApiTests.Card_IncludesFamilyAndLiveNeeds` зависит от порядка тестов** (фаза 8, срез 2).
|
||||
Проверено на чистом checkout `b135a9c` в отдельном worktree: в одиночку класс проходит (8/8),
|
||||
в полном прогоне класса падает на `Assert.Equal(2, card.Family.Parents.Count)` — ожидалось 2,
|
||||
пришёл 1. Причина: тест берёт `People[0]` и требует у него двух родителей, а состав семьи
|
||||
зависит от сида, сид — от id школы, id — от того, сколько школ создали тесты до него (и от
|
||||
`saves/index.json` на машине). На машине с накопленными сейвами тест зелёный, на чистом
|
||||
клоне — красный. Чинить надо тест: брать ученика, у которого два родителя, а не первого
|
||||
попавшегося. Неполные семьи — сознательное решение `design/people.md`, не баг генерации.
|
||||
- **`GameSocketTests.OpeningASchoolDuringAMathLesson_...` не выдерживает полный прогон** (срез 4).
|
||||
В одиночку проходит за 1 с, в полном прогоне падает с «No presence frame matched within 40
|
||||
frames» через 22 с. Похоже на нехватку кадров под нагрузкой, а не на ошибку присутствия.
|
||||
- Полный `dotnet test` один раз упал: процесс `HSchool.Simulation.Tests` умер с `0xC0000005`,
|
||||
успев отчитаться о 44 тестах из 63, и два `ActivityTests` (фаза 20) не прошли. Повторить не
|
||||
удалось. Скорее всего дерево правилось прямо во время прогона (см. ниже).
|
||||
- На момент проверки в рабочем дереве шла правка фазы 21 (`Decision.cs`, `LessonLearning.cs`,
|
||||
`LessonLearningSystem.cs`, `PresenceSystem.cs`, `gameScreen.ts`), и какое-то время решение не
|
||||
компилировалось. Выводам по срезу 1 это не мешает: его файлы правка не трогает, а дописанные
|
||||
тесты прогнаны и на чистом `b135a9c`, и на дереве после починки сборки.
|
||||
|
||||
### Перепроверка на `5a00ad7`, 2026-08-19
|
||||
|
||||
Коммит добавил родные языки: `nativeLanguages` в каталоге, `nativeLanguage` в создании школы,
|
||||
поле в сейве. Проверено по изменению:
|
||||
|
||||
- **Инвариант протокола цел.** Версия осталась `7` в обоих местах, `ProtocolCodec.cs` и
|
||||
`protocol.ts` не тронуты — и правильно: изменение целиком в HTTP/JSON, который документ
|
||||
объявляет расширяемым. `docs/protocol.md` пополнен тем же коммитом, включая новый код ошибки
|
||||
`unknown-native-language`, и этот код проверяется тестом.
|
||||
- **Формат сейва вырос на nullable-поле** без бампа `CurrentFormat`. Старый сейв без поля
|
||||
загружается сознательно: `NativeLanguages.Pick(..., rollIfOmitted: false)` берёт первый язык
|
||||
набора, а не бросает кубик, — иначе существующая школа сменила бы язык при первом же старте
|
||||
сервера и следующий набор пришёл бы другим. Ветка была описана комментарием, но не проверялась.
|
||||
- Дописанные в первый проход тесты (`unknown-mod` и побег из папки `mods`) проходят на новом коде.
|
||||
|
||||
Дописано: `SkillGrantTests.ReloadWithoutASavedPick_TakesTheFirstLanguageInsteadOfRolling` —
|
||||
закрывает всю таблицу `Pick`: старый сейв берёт первый язык, новая школа бросает кубик и бросок
|
||||
стабилен по сиду, сохранённый выбор уважается, чужой id даёт `null`, из которого создание школы
|
||||
делает `400`.
|
||||
|
||||
### Перепроверка на `418a4ea`, 2026-08-20
|
||||
|
||||
Дрейф после `5a00ad7` — это срез 6 (пакеты, сид, формат сейва, тесты экранов) плюс раздельные обеды.
|
||||
Обещания фаз 0–4 целы; протокол остался v7 в трёх местах, `ProtocolCodec` / `protocol.ts` не трогались.
|
||||
|
||||
Что подтверждено повторно:
|
||||
|
||||
- **Фаза 0.** `pixi.js` нет; `npm run build` проходит (после правки ниже).
|
||||
- **Фаза 1.** Дерево, пять секций локации, клиентский фильтр, `localize()`. Отказ от панели событий записан в фазе 1 и в нарративе `design/near-term.md`; в таблице «Что уже зафиксировано» строка всё ещё говорила «панель есть» — поправлена.
|
||||
- **Фаза 2.** `LongRunning`, аккумулятор с потолком 5, супервизор не трогает `World`, `WorkerFailed` снимает школу с таблицы и не удаляет файл. `ReloadFromDisk_RestoresAPausedClock` и `PausingOneSchool_DoesNotStopAnother` зелёные.
|
||||
- **Фаза 3.** Все восемь тестов списка на месте в `HSchool.Content.Tests` (86/86). Ванильная карта валидна.
|
||||
- **Фаза 4.** `GET /api/mods` (core обязателен), каталог, create с картой и отказ на дырявый граф, снимок при OpenSchool, reload раскладки — зелёные. `core` в диалоге создания нельзя снять — теперь ещё и клиентским тестом (`keeps core checked and disabled`, фаза 28).
|
||||
- **Инварианты и «Things that will bite you».** `Content` без ASP.NET; `DateTime.Now` в симуляции нет; `modal.ts` резолвит явно; `.dialog--screen` — `height: fit-content`; `DefaultStartDate` UTC; `MapSnapshotSize` от сообщения; outbox `DropOldest`; `WaitToReadAsync` переносится; меню патчит `card.update`.
|
||||
- `SchoolApiTests.Catalog_WithAnUnknownMod_IsRejected`
|
||||
- `SchoolApiTests.ModId_ThatEscapesTheModsFolder_IsRejectedOnBothEndpoints`
|
||||
- `SkillGrantTests.ReloadWithoutASavedPick_TakesTheFirstLanguageInsteadOfRolling`
|
||||
|
||||
Исправлено:
|
||||
|
||||
- `School` в `src/HSchool.Client/src/net/api.ts` содержал два поля `speedIndex` подряд — артефакт мержа фазы 26 (`edd3d35`). `npm test` (vitest) это не ловит, `npm run build` падал с TS2300. Дубликат убран; поле как было одно.
|
||||
- В таблице `design/near-term.md` «События | Панель есть, лента пустая» расходилась с решением фазы 8, которое журнал уже считал закрытым. Строка приведена к вкладочной оболочке.
|
||||
|
||||
Замечено рядом (за границами среза):
|
||||
|
||||
- `GameSocketTests.OpeningASchoolDuringAMathLesson_...` теперь падает **и в полном прогоне, и в одиночку** (40 кадров присутствия после снятия паузы, `People.Count == 0`). Раньше это был флак под нагрузкой, и тест ослабили до «люди вообще едут». После среза 6 никто не появляется: планы дня собраны для пустого штата, найм в 10:20 на паузе пересобирает таблицу, но явка завязана на `AppearAt` утреннего прихода. Чинить в срезе 5, не здесь.
|
||||
- `npm test` в клиенте не гоняет `tsc`. Дубликат поля и любой другой TS2300 зелёный в vitest и красный на `build`. Это фаза 28.
|
||||
- Два поля `speedIndex` в клиентском `School` (`api.ts`) — артефакт мержа фазы 26; vitest не
|
||||
ловил, `npm run build` падал с TS2300.
|
||||
|
||||
## Срез 2. Люди
|
||||
|
||||
- **Фазы:** 5–9
|
||||
- **Проверен на:** `bdb1253`, 2026-08-20 (первичная проверка — `5cd5a6d`; предыдущая перепроверка — `5a00ad7`)
|
||||
- **Проверен на:** `bdb1253`, 2026-08-20
|
||||
- **Пути:** `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`,
|
||||
@@ -152,134 +71,38 @@
|
||||
`tests/HSchool.Simulation.Tests/PeopleInSchoolTests.cs`,
|
||||
`tests/HSchool.AppHost.Tests/PeopleApiTests.cs`,
|
||||
`tests/HSchool.AppHost.Tests/SchoolSeedTests.cs`
|
||||
- **Итог:** исправлен один тест, который падал на чистом клоне, укреплён второй, дописан один;
|
||||
расхождение с дизайном одно и то же, что в срезе 1 (раскладка оболочки менеджера)
|
||||
- **Итог:** обещания фаз 5–9 целы; починены два API-теста, дописан один на reload после набора
|
||||
|
||||
Что подтверждено:
|
||||
|
||||
- **Фаза 5.** Все шесть пунктов списка тестов на месте в `PeopleDefTests` (разбор каждого вида,
|
||||
наследование навыка, патч черты, неизвестная ссылка — ошибка каталога, склонение по модели и
|
||||
перекрытие явной таблицей), плюс `ExtraPack_AddsANameSetAndTrait` — критерий «мод со своим
|
||||
набором имён виден в каталоге». Наборы имён в `GET /api/catalog` проверены в
|
||||
`SchoolApiTests.Catalog_LabelsDefsInTheRequestedLanguage`.
|
||||
- **Фаза 6.** Все шесть тестов из списка фазы существуют и проходят. Критерий «в проекте нет
|
||||
сокетов, ECS и `DateTime.Now`» закреплён самими тестами —
|
||||
`Assembly_DoesNotReferenceArchAspNetOrSockets` и `Sources_DoNotUseWallClock`.
|
||||
- **Фаза 7.** Одиннадцать кабинетов (`VanillaMap_HasElevenHomeroomsNotTheComputerLab`), нужды
|
||||
тикают со школой, ростер публикуется снимком, `PersistPeople` зовётся только когда состав
|
||||
изменился — файл не переписывается по таймеру. Ростер, не сходящийся с картой, оставляет школу
|
||||
незапущенной (`RosterFit.Matches` → `SchoolContentUnavailableException`).
|
||||
- **Фаза 8.** Список читает опубликованный снимок (`loop.FindPeople`), карточка идёт через
|
||||
очередь команд с `TaskCompletionSource` — инвариант 3 цел. Все пять требуемых фазой тестов API
|
||||
на месте. Клиент: фильтры, сортируемые колонки, пейджер, семейные ссылки, всё через `t(...)`;
|
||||
в строке списка только лёгкие поля.
|
||||
- **Фаза 9.** Выпуск старшей имеющейся параллели, сохранение вместимости, семьи через поколения и
|
||||
уход родителей выпускников покрыты в `YearlyIntakeTests` и `PeopleInSchoolTests`.
|
||||
- **Дизайн.** `design/people.md` сверен построчно: неполные семьи ≈8% (тест требует 5–10%),
|
||||
фамилия и отчество отцовские даже у одинокой матери, идентификатор ребёнка — счётчик, места
|
||||
раздаются вперемешку. Расхождений нет.
|
||||
|
||||
Исправлено:
|
||||
|
||||
- **`PeopleApiTests.Card_IncludesFamilyAndLiveNeeds` падал на чистом клоне.** Тест брал первого
|
||||
ученика страницы и требовал у него ровно двух родителей. Состав семьи выводится из сида, а сид —
|
||||
это id школы (`SchoolWorker.InstallPeople`: `seed = school.Id`), то есть зависит от того,
|
||||
сколько школ создали тесты до него и что лежит в `saves/index.json`. Замер по сидам 1–30: у 28
|
||||
первый пятиклассник с двумя родителями, у 2 — с одним, и полный прогон на свежем checkout
|
||||
`b135a9c` в отдельном worktree ловил как раз такой сид. Одинокие родители — сознательное
|
||||
решение дизайна, поэтому неправ был тест: теперь он ищет ученика, у которого есть мать, а
|
||||
количество родителей проверяет диапазоном. Проверено тем же способом, каким ловилось: полный
|
||||
прогон на чистом `b135a9c` трижды, 60/60.
|
||||
- **`PeopleApiTests.List_SortsBySurname` мерил не тем.** Тест требовал ordinal-порядка, а сервер
|
||||
ставит Ё на место Е (`RosterBrowser.NameOrder`, тест `SurnameSort_FollowsTheAlphabetNotCodePoints`).
|
||||
Совпадали они только потому, что в `core` нет фамилий на Ё — мод с такой фамилией уронил бы
|
||||
тест, а не код. Теперь тест складывает Ё в Е так же, как сервер.
|
||||
- Дефы человека: разбор, наследование, патч, неизвестная ссылка, склонение, мод со своим набором.
|
||||
- Генератор: шесть тестов списка фазы, без Arch/ASP.NET/`DateTime.Now`. Неполные семьи 5–10%.
|
||||
Сид — поле школы, не `school.Id`; хостовые тесты, которым нужен состав, передают сид явно.
|
||||
- Одиннадцать кабинетов, сущности в `World`, `PersistPeople` только при смене состава.
|
||||
Штат при создании пуст — это фаза 11.
|
||||
- Список с опубликованного снимка, карточка через `TaskCompletionSource`. Фильтры, пейджер,
|
||||
семейные ссылки, всё через `t(...)`. Вкладка рядом с картой, не нижний ряд — так записано
|
||||
в фазе 8 и в `design/people.md`.
|
||||
- Выпуск старшей имеющейся, вместимость, семьи через поколения, reload после набора.
|
||||
|
||||
Дописано:
|
||||
|
||||
- `PeopleApiTests.ReloadAfterTheYearlyIntake_RestoresTheNewComposition` — критерии фаз 7 и 9
|
||||
«перезапуск поднимает тех же людей» и «перезапуск после перехода поднимает **новый** состав» не
|
||||
проверялись сквозь сервер. Просто сравнить людей до и после reload недостаточно: генерация
|
||||
детерминирована от id школы, поэтому забывший файл сервер собрал бы тот же ростер и тест бы
|
||||
ничего не поймал. Тест поэтому ждёт 1 сентября (школа создаётся за 15 игровых минут до
|
||||
полуночи, это около трёх секунд реального времени), а после reload требует состав **после**
|
||||
набора и явно отличный от исходного.
|
||||
|
||||
Открыто:
|
||||
|
||||
- **Раскладка оболочки менеджера разошлась с дизайном** — то же расхождение, что записано в срезе
|
||||
1. Фаза 8 обещает панель «Люди» нижним рядом во всю ширину, `design/people.md` фиксирует
|
||||
«панель в оболочке менеджера, нижний ряд; не отдельный экран», а на экране она вкладкой рядом с
|
||||
картой. Тот же коммит `d8f8db6`, что убрал панель событий. Решается одним решением на оба
|
||||
пункта: либо вернуть нижний ряд, либо переписать обе строки дизайна.
|
||||
|
||||
Замечено рядом (за границами среза):
|
||||
|
||||
- `design/people.md` и задача фазы 5 говорят «скорость убывания нужд в `core` — ноль», а в
|
||||
`defs/needs` теперь `decayPerHour` от 0.05 до 0.15. Это сознательная работа фазы 20, не
|
||||
регрессия; строка дизайна просто устарела и относится к срезу 5.
|
||||
- Срез 1 успел сдвинуться: коммит `5cd5a6d` тронул `gameScreen.ts` и `strings.ts` (подпись
|
||||
идущего человека). По правилу журнала он больше не «проверен на `b135a9c`» — правка маленькая и
|
||||
относится к срезу 5, но следующий проход это увидит.
|
||||
|
||||
### Перепроверка на `5a00ad7`, 2026-08-19
|
||||
|
||||
`5a00ad7` переписал половину генератора: `PersonSampler` (+266), `FamilyFactory` (+52),
|
||||
`YearlyIntake` (+61), новый `NativeLanguages`, новые навыки в `core` (языки, социальные,
|
||||
рабочие). Проверено по изменению:
|
||||
|
||||
- Решение записано заранее — `design/people.md` описывает родные языки и порядок выдачи навыков
|
||||
ещё с `a441ed9`, код догнал документ. Дрейфа нет, это тот редкий случай, когда дизайн шёл первым.
|
||||
- Восемь новых тестов в `SkillGrantTests` закрывают выдачу навыков по параллелям, отсутствие
|
||||
рабочих навыков у учеников и набор без переброса уже выданного. Старые тесты детерминизма,
|
||||
согласованности семьи и годового набора зелёные — генератор переписан, а обещания среза целы.
|
||||
- Исправления среза 2 (карточка семьи, сортировка по фамилии, состав после набора и перезапуска)
|
||||
проходят на новом коде.
|
||||
|
||||
### Перепроверка на `bdb1253`, 2026-08-20
|
||||
|
||||
Дрейф после `5a00ad7` — свой сид школы (фаза 26), золотые ростеры (25), тесты панели (28) и
|
||||
данные поведения. Обещания фаз 5–9 целы.
|
||||
|
||||
Что подтверждено повторно:
|
||||
|
||||
- **Фаза 5.** Все пункты списка в `PeopleDefTests` (10/10): разбор, наследование, патч черты,
|
||||
неизвестная ссылка, склонение и таблица, мод со своим набором.
|
||||
- **Фаза 6.** Все шесть тестов генератора на месте, плюс `NewSchool_HasNoStaff` (фаза 11 не
|
||||
отменяет детерминизм и заполнение мест). `Assembly_DoesNotReferenceArchAspNetOrSockets` и
|
||||
`Sources_DoNotUseWallClock` зелёные. Неполные семьи 5–10% — `ReviewFixTests`.
|
||||
- **Фаза 7.** Одиннадцать кабинетов, сущности в `World`, `PersistPeople` только при изменении
|
||||
состава. Штат при создании пуст — это фаза 11, тест обновлён (`LeaveJobsEmpty`).
|
||||
- **Фаза 8.** Список с опубликованного снимка (`FindPeople`), карточка через `TaskCompletionSource`.
|
||||
Пять API-тестов плюс клиентские фильтры/пейджер (`peoplePanel.test.ts` 3/3). Вкладка, не нижний ряд.
|
||||
- **Фаза 9.** Выпуск старшей имеющейся, вместимость, семьи через поколения, reload после набора
|
||||
(`ReloadAfterTheYearlyIntake_RestoresTheNewComposition`).
|
||||
- **Сид.** Больше не `school.Id`. Новая школа берёт `_createSeed`, сейв — `loaded.Seed`; запасной
|
||||
`school.Id` только если `people.json` нет. `Card_IncludesFamilyAndLiveNeeds` передаёт `seed: 1`.
|
||||
`SchoolSeedTests`: тот же сид — те же люди, два без сида — разные, reload хранит выпавший.
|
||||
- `PeopleApiTests.ReloadAfterTheYearlyIntake_RestoresTheNewComposition` — ждёт 1 сентября и
|
||||
требует состав **после** набора, отличный от исходного (детерминизм от сида иначе скрыл бы
|
||||
потерянный файл).
|
||||
|
||||
Исправлено:
|
||||
|
||||
- В `design/people.md` скорость нужд всё ещё была «ноль» (нарратив, совет и таблица), хотя срез 5
|
||||
это отменил. Помечено как отменённое со ссылкой на `ai.md`, по тому же шаблону, что расписание.
|
||||
Код не трогался.
|
||||
|
||||
Закрыто из прошлого прохода:
|
||||
|
||||
- **Раскладка оболочки.** «Открыто» выше больше не действует: `design/people.md` и фаза 8 уже
|
||||
записаны под вкладку рядом с картой. Решение принято в том же ходе, что отказ от панели событий.
|
||||
|
||||
Замечено рядом:
|
||||
|
||||
- «Заведомо не сейчас» в `people.md` всё ещё говорит «должности закрываются генератором» —
|
||||
отменено срезом 3. Не переписывал исторический список стопов.
|
||||
|
||||
People 34, PeopleDef 10, PeopleInSchool 7, PeopleApi+SchoolSeed 13, клиентская панель 3/3.
|
||||
- `Card_IncludesFamilyAndLiveNeeds` брал `People[0]` и требовал двух родителей. Состав зависит
|
||||
от сида; на чистом клоне первый ученик иногда из неполной семьи. Теперь ищет ученика с матерью
|
||||
и проверяет диапазон.
|
||||
- `List_SortsBySurname` требовал ordinal-порядок, сервер ставит Ё на место Е. Совпадали, пока
|
||||
в `core` не было фамилий на Ё.
|
||||
|
||||
## Срез 3. Штат
|
||||
|
||||
- **Фазы:** 10–13
|
||||
- **Проверен на:** `bdb1253`, 2026-08-20 (первичная проверка — `21d79cb`; предыдущая перепроверка — `5a00ad7`)
|
||||
- **Проверен на:** `bdb1253`, 2026-08-20
|
||||
- **Пути:** `src/HSchool.People/Staffing.cs`, `src/HSchool.People/ApplicantPool.cs`,
|
||||
`src/HSchool.Content/SubjectDef` и `defs/staffing`, `src/HSchool.Server/Api/SchoolEndpoints.cs`
|
||||
(staffing/hire/subjects), `src/HSchool.Server/mods/core/defs/{subjects,positions,rooms,staffing,traits}`,
|
||||
@@ -287,131 +110,40 @@ People 34, PeopleDef 10, PeopleInSchool 7, PeopleApi+SchoolSeed 13, клиент
|
||||
`tests/HSchool.People.Tests/{StaffingTests,ApplicantPoolTests}.cs`,
|
||||
`tests/HSchool.AppHost.Tests/StaffingApiTests.cs`,
|
||||
`src/HSchool.Client/src/ui/managementPanel.test.ts`
|
||||
- **Итог:** дописано 3 теста (один из них — прямо требуемый фазой 12 и отсутствовавший),
|
||||
дополнен `docs/protocol.md`; расхождений кода с дизайном не найдено
|
||||
- **Итог:** обещания фаз 10–13 целы; дописаны 3 теста; `docs/protocol.md` дополнен `?lang=`
|
||||
|
||||
Что подтверждено:
|
||||
|
||||
- **Фаза 10.** `PETeacher` в `core` нет, `Classroom`, `ComputerLab` и `GymHall` не открывают
|
||||
должностей — должности остались у библиотеки, приёмной, столовой, медкабинета и кабинета
|
||||
директора, ровно как обещано. Кабинет описан числом мест (`seatThing`/`defaultSeats`, пустой
|
||||
список слотов — проверено в `Catalog_LabelsDefsInTheRequestedLanguage`), редактор карты
|
||||
показывает у него одно поле «мест». Неизвестный навык в предмете роняет каталог
|
||||
(`Subject_UnknownSkill_FailsTheCatalog`), полнота локалей — `EveryVanillaLabel_ExistsInBothLocales`,
|
||||
стартовая дата 31 марта 2012 зашита в тестах API.
|
||||
- **Фаза 11.** Все шесть тестов из списка фазы на месте и проходят: детерминизм пула по сиду и
|
||||
неделе, частичное обновление с сохранением навыков и запроса, устойчивый размер за пятьдесят
|
||||
недель, «сильный просит больше», пустой штат при полной школе, соискатель вне ростера до найма.
|
||||
- **Фаза 12.** Фонд оплаты, деление часов между учителями предмета, пол одной ставки и покрытие
|
||||
предметов покрыты в `StaffingTests`. `GET /staffing` читает опубликованный снимок
|
||||
(`loop.FindPeople`), наём и назначение идут в воркер через `GameCommand` с
|
||||
`TaskCompletionSource` — инвариант 3 цел. Перезапуск с тем же штатом и назначениями —
|
||||
`AssignAndUnassign_HonourTheCap_AndReloadKeepsAssignments`.
|
||||
- **Фаза 13.** Строка денег, непокрытые предметы, список соискателей со ставкой и сильными
|
||||
навыками, кнопка найма с текстом ошибки, список штата с предметами и стоимостью, назначение и
|
||||
снятие с карточки — всё есть и всё через `t(...)`.
|
||||
- **Дизайн.** `design/staffing.md` сверен построчно. Особо проверено: `MaxWeeklyHours` не
|
||||
запрещает назначение, а делает предмет непокрытым (в коде нет такой ошибки, и замер это
|
||||
подтверждает); цена часа считается от навыков **и от черт**.
|
||||
- `PETeacher` нет; кабинеты без учительской должности; места через `defaultSeats`.
|
||||
Неизвестный навык в предмете роняет каталог. Стартовая дата 31 марта 2012.
|
||||
- Пул: детерминизм по сиду и неделе, частичное обновление, устойчивый размер, «сильный просит
|
||||
больше», пустой штат, соискатель вне ростера до найма. Пул 32.
|
||||
- Фонд оплаты, деление часов, пол ставки, покрытие. `GET /staffing` читает снимок, наём и
|
||||
назначение — `GameCommand` с `TaskCompletionSource`. `MaxWeeklyHours` не запрещает назначение,
|
||||
а оставляет предмет непокрытым. `PrimarySchool` на ванили требует трёх учителей (`teachersShort`).
|
||||
- Экран: деньги, непокрытые, пул, штат, назначение с карточки, отказ по пределу текстом,
|
||||
всё через `t(...)`.
|
||||
- Полностью укомплектованная школа влезает в 100 000 впритык (запас 5–13%). Нанять пул целиком
|
||||
без назначений предела достигает. Раскладка «каждому все предметы» — самая дешёвая, не
|
||||
«укомплектованная школа».
|
||||
|
||||
Дописано:
|
||||
|
||||
- `StaffingApiTests.AssigningPastTheCap_IsRejectedWithTheNumbers` — фаза 12 требует теста API на
|
||||
«отклонение по пределу», а его не было: единственное место, где он мог сработать, было написано
|
||||
через `if (over.StatusCode == Conflict) … else …` и проходило при любом исходе. Пределом
|
||||
занялся замер: при выделенных 100 000 полностью загруженная школа стоит всего 68–72 тысячи,
|
||||
то есть «нанять всех» предела не достигает. Но пик фонда приходится на середину раздачи
|
||||
предметов — пока часы предмета несут один-два учителя, а не двенадцать, — и там отказ
|
||||
случается: по сидам 1–30 отказов от 4 до 24 на прогон, ни одного сида без отказа. Тест
|
||||
раздаёт предметы штату, ловит первый `409`, сверяет `payroll-exceeded`, `allocated`,
|
||||
`attempted > allocated`, `remaining` и то, что отклонённое назначение действительно не легло.
|
||||
- `ApplicantPoolTests.ConfidentTraits_AskForMoreAndQuietOnesForLess` — дизайн фиксирует «цена
|
||||
часа: от навыков и от черт (самоуверенный просит больше)», код это делает через
|
||||
`TraitDef.WageAsk` (в `core` Leader +10, HotTempered +6, Quiet −8), а тестом закреплена была
|
||||
только половина про навыки.
|
||||
- Проверка в `AssignAndUnassign_HonourTheCap_AndReloadKeepsAssignments`, что после перезапуска
|
||||
возвращается **тот же пул** с теми же ставками — критерий готовности фазы 11, который никто не
|
||||
проверял. Тест кусается: пул на диске уже без нанятого, а сгенерированный заново вернул бы его
|
||||
обратно.
|
||||
- `StaffingApiTests.AssigningPastTheCap_IsRejectedWithTheNumbers` — фаза 12 требовала API-тест
|
||||
на отказ по пределу; единственное место было написано через `if (over.StatusCode == Conflict)`
|
||||
и проходило при любом исходе.
|
||||
- `ApplicantPoolTests.ConfidentTraits_AskForMoreAndQuietOnesForLess`
|
||||
- В `AssignAndUnassign_HonourTheCap_AndReloadKeepsAssignments` — тот же пул с теми же ставками
|
||||
после перезапуска.
|
||||
|
||||
Исправлено:
|
||||
|
||||
- `docs/protocol.md` не упоминал `?lang=ru|en` у `POST staff/hire`, `POST …/subjects` и
|
||||
`DELETE …/subjects/{subject}`, хотя все три его принимают и клиент его шлёт. Поведение не
|
||||
трогалось — дописана документация.
|
||||
|
||||
Замечено рядом (за границами среза):
|
||||
|
||||
- Предел фонда при ванильных данных почти не ограничивает игрока: нанять всех двенадцать и
|
||||
раздать им все предметы стоит около 70 000 из 100 000. Отказ достижим только по дороге, на
|
||||
пике неравномерной нагрузки. Это игровой баланс, а не ошибка (см. коммит `207e7ec`, которым
|
||||
предел поднимали намеренно), но если предел задумывался как настоящее ограничение — числа
|
||||
сейчас говорят обратное.
|
||||
- В `AssignAndUnassign_HonourTheCap_AndReloadKeepsAssignments` осталась ветка `if/else` вокруг
|
||||
ожидаемого отказа. Теперь, когда отказ проверяется отдельным тестом, эта ветка просто не может
|
||||
упасть — её стоит однажды упростить, но трогать работающий тест ради этого ревью не стало.
|
||||
### Перепроверка на `5a00ad7`, 2026-08-19 — **вывод про бюджет исправлен**
|
||||
|
||||
`5a00ad7` поднял `poolSize` с 12 до 32. Это не косметика: предел фонда начал работать, и запись
|
||||
выше про «предел почти не ограничивает игрока» больше не описывает игру. Перемерено на шести
|
||||
сидах:
|
||||
|
||||
| что делаем | сколько людей | фонд из 100 000 | непокрыто |
|
||||
| --- | --- | --- | --- |
|
||||
| нанимать подряд, не назначая предметов | 20–21 из 32 | 95 000–99 400, дальше отказ | всё |
|
||||
| по учителю на предмет | 12 | 86 800–94 700 | `PrimarySchool` |
|
||||
| закрыть и его | 14 | 87 100–95 100 | ничего |
|
||||
|
||||
То есть полностью укомплектованная школа теперь **влезает, но впритык** — запас 5–13%, и
|
||||
`PrimarySchool` (1–4 классы, 80 часов в неделю против потолка в 36 на человека) требует трёх
|
||||
учителей, о чём игрок узнаёт только из списка непокрытых.
|
||||
|
||||
Прежняя цифра «около 70 000 из 100 000» получена на вырожденной раскладке — когда каждому из
|
||||
двенадцати назначены все двенадцать предметов. Так часы предмета делятся на всех и почти каждый
|
||||
садится на пол одной ставки; это самая **дешёвая** конфигурация, а не «полностью
|
||||
укомплектованная школа». Ошибка была в замере, а не в коде.
|
||||
|
||||
Ставки соискателей при этом не изменились (в среднем 57.9–59.3 против прежних 58.5–62.5), хотя
|
||||
навыков у человека стало больше — цена часа считается от среднего по навыкам, и среднее устояло.
|
||||
|
||||
`Hire_IdlePool_FitsUnderTheCap` в том же коммите переписан так, чтобы принимать отказ по пределу
|
||||
как штатный исход. Это правильно: с пулом в 32 человека нанять всех и остаться в пределах суммы
|
||||
уже нельзя.
|
||||
|
||||
### Перепроверка на `bdb1253`, 2026-08-20
|
||||
|
||||
Дрейф после `5a00ad7` — `teachersShort` (фаза 25), свой сид, удостоверение пака. Обещания фаз 10–13
|
||||
целы; новых тестов не дописывал, расхождений с `design/staffing.md` нет.
|
||||
|
||||
Что подтверждено повторно:
|
||||
|
||||
- **Фаза 10.** `PETeacher` нет, кабинеты без учительской должности, места через `defaultSeats`,
|
||||
редактор показывает у homeroom одно поле «мест». `Subject_UnknownSkill_FailsTheCatalog`,
|
||||
стартовая дата 31 марта 2012.
|
||||
- **Фаза 11.** Все шесть тестов пула на месте (`SameSeedAndWeek`, частичное обновление, 50 недель,
|
||||
сильный просит больше, пустой штат, соискатель вне ростера). Пул 32, reload хранит ставки.
|
||||
- **Фаза 12.** `Hire_TwoPeopleAtThreeAndSevenThousand_RejectsTheThird` на фикстуре 10 000.
|
||||
`AssigningPastTheCap_IsRejectedWithTheNumbers` на API. `GET /staffing` читает снимок,
|
||||
наём/назначение — `TaskCompletionSource`. `MaxWeeklyHours` не запрещает назначение
|
||||
(`SubjectNeedingMoreHoursThanOnePersonCarries_StaysUncovered`). Ветка `if/else` вокруг предела
|
||||
убрана.
|
||||
- **Фаза 13.** Деньги, непокрытые, пул, штат, назначение с карточки, всё через `t(...)`.
|
||||
Отказ по пределу текстом — `managementPanel.test.ts`.
|
||||
- **Покрытие.** `PrimarySchool` на ванили требует трёх учителей (`TeachersShort == 3` в API и в
|
||||
`PrimarySchool_OnVanillaMap_NeedsThreeTeachers_AndASecondDoesNotCloseIt`). Это фаза 25, не
|
||||
ломает фазу 12: список непокрытых был и раньше, появилось число.
|
||||
|
||||
Замечено рядом:
|
||||
|
||||
- `people.md` «Заведомо не сейчас» всё ещё говорит, что должности закрывает генератор — то же, что
|
||||
в срезе 2. Исторический стоп среза 2, не трогал.
|
||||
|
||||
Staffing+ApplicantPool 18, Content 3, StaffingApi 9.
|
||||
- `docs/protocol.md` не упоминал `?lang=` у hire/subjects, хотя клиент его шлёт.
|
||||
|
||||
## Срез 4. Расписание
|
||||
|
||||
- **Фазы:** 14–17
|
||||
- **Проверен на:** `bdb1253`, 2026-08-20 (первичная проверка — `21d79cb`; предыдущая перепроверка — `5a00ad7`)
|
||||
- **Проверен на:** `bdb1253`, 2026-08-20
|
||||
- **Пути:** `src/HSchool.Schedule`, `src/HSchool.Content` (каркас дня, каникулы, `SubjectDef.room`),
|
||||
`src/HSchool.Simulation/SchoolTimetables.cs`, `src/HSchool.Server/Api/TimetableEndpoints.cs`,
|
||||
`src/HSchool.Server/Game/SchoolWorker.cs` (пин, перестроение),
|
||||
@@ -420,238 +152,69 @@ Staffing+ApplicantPool 18, Content 3, StaffingApi 9.
|
||||
`tests/HSchool.Content.Tests/LunchBreakTests.cs`,
|
||||
`tests/HSchool.AppHost.Tests/TimetableApiTests.cs`,
|
||||
`src/HSchool.Client/src/ui/timetableGrid.test.ts`
|
||||
- **Итог:** дописан один тест на пять непокрытых кодов отказа, поправлены две устаревшие строки
|
||||
дизайна; расхождений кода с принятыми решениями нет
|
||||
- **Итог:** обещания фаз 14–17 целы; дописан тест на коды отказа пина; две строки дизайна
|
||||
помечены как отменённые срезом 5
|
||||
|
||||
Что подтверждено:
|
||||
|
||||
- **Фаза 14.** Все пункты критерия закрыты в `CalendarTests`: суббота, каникулы и ночь дают «вне
|
||||
учебного дня», 10:20 буднего дня — третий урок, шестидневка делает субботу рабочей, зимние
|
||||
каникулы переносятся через 1 января. Требование помещения у предмета есть (физкультура —
|
||||
спортзал), неизвестная комната роняет каталог.
|
||||
- **Фаза 15.** Все шесть тестов из списка фазы на месте. Четыре запрета проверяются одним
|
||||
утверждением в `TeacherWithTwoSubjects_IsNeverInTwoRoomsAtOnce` (уникальность по учителю, классу
|
||||
и кабинету в слоте) плюс `ClassOfSixteen_DoesNotEnterALabOfTwelve`. Отсутствие сокетов, ECS и
|
||||
часов реального времени — самопроверкой сборки, как в `HSchool.People`.
|
||||
- **Фаза 16.** Расписание пересобирается только когда изменился состав: `TimetableDirty` ставится
|
||||
в `InstallPeople`/`Replace` и в годовом наборе, а воркер перестраивает таблицу под
|
||||
`if (result.PeopleChanged)` — по тику этого не происходит. `GET /timetable` читает
|
||||
опубликованный снимок, пин и снятие идут через `GameCommand` с `TaskCompletionSource`.
|
||||
Перезапуск с закреплениями — `Reload_RestoresLockedLessons`.
|
||||
- **Фаза 17.** Скобки в дереве (`Математика · 5Б`) собираются из присутствия, сетка «день × урок»
|
||||
с переносом, сменой кабинета и отметкой «закреплено» есть, отказ планировщика показывается
|
||||
текстом (`timetableErrorPin`, `timetableErrorNoTeacher`, `timetableErrorLesson`), личное
|
||||
расписание — в карточке. Всё через `t(...)`. Клиентские тесты и сборка на `21d79cb`: 33/33 и
|
||||
зелёная сборка.
|
||||
- Календарь: суббота, каникулы и ночь — «вне учебного дня»; 10:20 вторника — третий урок;
|
||||
шестидневка; зима через 1 января. Физкультура в спортзале. Обеденные смены в каркасе дня
|
||||
(младшие после 3-го, старшие после 4-го).
|
||||
- Планировщик: четыре запрета, класс не влезает в меньший кабинет, без Arch/ASP.NET/`DateTime.Now`.
|
||||
- Перестроение только при `PeopleChanged` + `TimetableDirty`, не по тику. `GET /timetable`
|
||||
читает снимок, пин — `TaskCompletionSource`. `Reload_RestoresLockedLessons`.
|
||||
- Сетка, закрепление, тексты отказа (`pin-rejected` / `no-teacher` / `unknown-lesson`),
|
||||
скобки в дереве из присутствия, личное расписание в карточке. Всё через `t(...)`.
|
||||
- Занятость узла в протоколе v7 живёт в кадре `Presence`, не в снимке карты — фаза 19.
|
||||
|
||||
Дописано:
|
||||
|
||||
- `TimetableApiTests.PinAndUnpinRefusals_CarryTheDocumentedCodes` — из шести кодов отказа пина в
|
||||
`docs/protocol.md` тестом был закрыт только `pin-rejected` (хвост
|
||||
`PinThenHireAnother_KeepsTheLockedSlot`, попытка провести урок в спортзале). Остальные пять —
|
||||
`no-teacher`, `unknown-class`, `unknown-subject`, `unknown-room`, `unknown-lesson` на повторном
|
||||
снятии, плюс `invalid-query` на неполном запросе — не проверялись, хотя клиент по ним
|
||||
переключает текст ошибки.
|
||||
- `TimetableApiTests.PinAndUnpinRefusals_CarryTheDocumentedCodes` — `no-teacher`, `unknown-class`,
|
||||
`unknown-subject`, `unknown-room`, `unknown-lesson`, `invalid-query`.
|
||||
|
||||
Исправлено:
|
||||
|
||||
- `design/schedule.md` держал в «Зафиксировано» две строки, которые срез 5 сознательно отменил:
|
||||
«Панель локации заполняется из расписания» и «Люди находятся по расписанию; ходьбы нет».
|
||||
Отмена записана в `design/ai.md` («присутствие — состояние человека, а не функция от
|
||||
расписания»), а старый документ об этом не знал. Помечены как отменённые со ссылкой; код не
|
||||
трогался — он давно живёт по новому решению.
|
||||
|
||||
Замечено рядом (за границами среза):
|
||||
|
||||
- Задача фазы 16 «снимок карты отдаёт по узлу, что там сейчас идёт и у кого» в протоколе v7
|
||||
выглядит иначе: снимок карты стал статическим, а занятость уехала в кадр `Presence`. Это
|
||||
сделано фазой 19 намеренно и описано в `docs/protocol.md`; строка фазы 16 просто историческая.
|
||||
- `GameSocketTests.OpeningASchoolDuringAMathLesson_...`, который в срезе 1 падал дважды под
|
||||
нагрузкой, за этот проход не воспроизвёлся ни разу: шесть полных прогонов подряд на чистом
|
||||
worktree и два одиночных под искусственной нагрузкой из шести жгущих процессов — зелено.
|
||||
Оставляю как «наблюдалось, не воспроизводится»; если вернётся, смотреть на выдачу кадров
|
||||
присутствия под нехваткой процессора, а не на логику.
|
||||
|
||||
Про окружение:
|
||||
|
||||
- Во время проверки параллельная сессия правила `core` и клиент (размер пула соискателей 12 → 32,
|
||||
новые навыки, диалог соискателей). Два прогона на рабочем дереве успели показать «падения»
|
||||
`Hire_IdlePool_FitsUnderTheCap` и `GetStaffing_EmptySchool_HasPoolAndNoPayroll` — это артефакт
|
||||
прогона старых бинарников против новых данных, а не находка. Поэтому весь срез проверялся в
|
||||
отдельном worktree на `21d79cb`: AppHost 63/63 (три прогона подряд), клиент 33/33 и сборка.
|
||||
|
||||
### Перепроверка на `5a00ad7`, 2026-08-19
|
||||
|
||||
Из путей среза коммит тронул только каталог навыков: пять строк ушли из `skills/academic.jsonc`,
|
||||
появились `languages`, `social` и `work`. Предметы ссылаются на навыки долями, и обе защиты на
|
||||
месте и зелёные — `Subject_UnknownSkill_FailsTheCatalog` и `EveryVanillaLabel_ExistsInBothLocales`.
|
||||
Планировщик, каркас дня и API расписания не менялись; дописанный в прошлый проход тест на коды
|
||||
отказа пина проходит.
|
||||
|
||||
### Перепроверка на `bdb1253`, 2026-08-20
|
||||
|
||||
Дрейф после `5a00ad7` — обеденные смены в каркасе дня (`SchoolDay` / `CalendarDefs`) и сид/дамп в
|
||||
воркере. Планировщик и API расписания не менялись. Обещания фаз 14–17 целы; тестов не дописывал.
|
||||
|
||||
Что подтверждено повторно:
|
||||
|
||||
- **Фаза 14.** Суббота, каникулы и ночь — «вне учебного дня»; 10:20 вторника — третий урок;
|
||||
шестидневка делает субботу рабочей; зима через 1 января. Физкультура в спортзале.
|
||||
Обеденные смены уже стоят в `design/schedule.md`: младшие после 3-го, старшие после 4-го,
|
||||
обе перемены длинные (`LunchBreakTests`).
|
||||
- **Фаза 15.** Все шесть тестов планировщика на месте, плюс самопроверка сборки без Arch/ASP.NET
|
||||
и `DateTime.Now`.
|
||||
- **Фаза 16.** Перестроение только при `PeopleChanged` + `TimetableDirty`, не по тику.
|
||||
`GET /timetable` читает снимок, пин — `TaskCompletionSource`. `Reload_RestoresLockedLessons`,
|
||||
`PinAndUnpinRefusals_CarryTheDocumentedCodes`.
|
||||
- **Фаза 17.** Сетка, закрепление, тексты отказа — `timetableGrid.test.ts` (pin-rejected /
|
||||
no-teacher / unknown-lesson). Всё через `t(...)`.
|
||||
|
||||
Замечено рядом:
|
||||
|
||||
- `GET /api/catalog` по-прежнему отдаёт каркас без `lunchBreaks` (только `longBreakAfter`).
|
||||
Сетке расписания смены не нужны — они для решений. Молча расширять HTTP ревью не стало.
|
||||
- `OpeningASchoolDuringAMathLesson_...` с этой перепроверки падает и в одиночку — см. срез 1;
|
||||
это явка, не раскладка часов.
|
||||
|
||||
Calendar+обеды 20, планировщик 9, TimetableApi 6.
|
||||
- В `design/schedule.md` «панель локации из расписания» и «люди находятся по расписанию» помечены
|
||||
как отменённые срезом 5.
|
||||
|
||||
## Срез 5. Жизнь школы
|
||||
|
||||
- **Фазы:** 18–21
|
||||
- **Проверен на:** `cbe739a`, 2026-08-20 (первичная проверка — `21d79cb`; предыдущая перепроверка — `5a00ad7`; дерево до коммита правок — `450495f`)
|
||||
- **Проверен на:** `cbe739a`, 2026-08-20
|
||||
- **Пути:** `src/HSchool.Ai`, `src/HSchool.Simulation/{PresenceSystem,ActivitySystem,LessonLearningSystem,School}.cs`,
|
||||
`src/HSchool.Protocol` (кадр `Presence`, пропуск в кадре часов),
|
||||
`src/HSchool.Server/Game/PresenceFrame.cs`, `src/HSchool.Client/src/ui/gameScreen.ts`,
|
||||
`src/HSchool.Server/mods/core/defs/{actions,behavior,needs}`, `tests/HSchool.Ai.Tests`,
|
||||
`tests/HSchool.Simulation.Tests/{PresenceTests,DecisionTests,ActivityTests,NeedDecayTests,LunchTests}.cs`,
|
||||
`tests/HSchool.AppHost.Tests/GameSocketTests.cs`
|
||||
- **Итог:** все 32 теста из списков четырёх фаз на месте; дописаны 2 теста явки после смены таблицы,
|
||||
`SetTimetable` сбрасывает планы дня, хостовый тест ждёт `Clock.Running` после снятия паузы.
|
||||
Голод из первого прохода уже закрыт данными. AppHost не гонялся — Aspire держит DLL.
|
||||
- **Итог:** все 32 теста из списков фаз на месте; дописаны 2 теста явки; `SetTimetable` сбрасывает
|
||||
планы дня. Голод закрыт данными. AppHost после правки не гонялся — Aspire держал DLL.
|
||||
|
||||
Что подтверждено:
|
||||
|
||||
- **Фаза 18.** Все 13 требуемых тестов есть: маршрут 201 → санузел через лестницу, совпадение
|
||||
суммы `travelMinutes` с реально пройденным временем, пустая школа в воскресенье и в каникулы,
|
||||
класс без уроков не приходит, ученик в кабинете к звонку, спортзал впритык к перемене,
|
||||
детерминизм по сиду, сохранение посреди перемены, четыре сценария пропуска пустого времени,
|
||||
школа без учителей, лето с первым сентября, промотанная неделя против прожитой.
|
||||
- **Фаза 19.** Все пять тестов: байтовая раскладка присутствия с обеих сторон, круговой прогон,
|
||||
отсутствие людей и урока в снимке карты, разрешение на пропуск в кадре часов, отброшенный
|
||||
пропуск в учебное время.
|
||||
- **Фаза 20.** Все шесть: декей голода за час, обед на заявленные минуты и величину, нехватка
|
||||
стульев, ночь вне школы, действие с неизвестной нуждой роняет каталог, детерминизм нужд.
|
||||
- **Фаза 21.** Все восемь, включая сквозной `ZeroToilet_LeavesClass_ReachesRestroom_AndReturns`,
|
||||
`DecisionCap_DefersTheOverflow` и `SameSeedAndActions_MatchAfterAWeek`, плюс табличный разбор
|
||||
решений в `DecisionPlannerTests` без мира.
|
||||
- **Инварианты.** `HSchool.Ai` не знает Arch, ASP.NET и часов реального времени, `HSchool.Simulation`
|
||||
не знает сокетов — обе проверки в самих тестах. Протокол v7 сходится в трёх местах.
|
||||
|
||||
Измерено (временный тест, удалён после):
|
||||
|
||||
Полностью укомплектованная ванильная школа (12 учителей, 225 уроков, 176 учеников), прожитая
|
||||
тиками с вторника по пятницу:
|
||||
|
||||
| | день 1 | день 2 | день 3 | день 4 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| побывали в столовой | 0 | 144 | 133 | 141 |
|
||||
| завершённых обедов | 0 | 75 | 132 | 111 |
|
||||
| минимальный голод | 0.32 | 0.00 | 0.00 | 0.00 |
|
||||
|
||||
Картина дня в остальном осмысленная: в 8:25 двор, вестибюль и лестницы полны, к 8:45 все 144
|
||||
пришедших в кабинетах и спортзале, на перемене коридор — самый людный узел школы (пик 112),
|
||||
после уроков остаются только те, у кого урок ещё идёт.
|
||||
|
||||
- **Столовая пустует весь первый день.** Голод стартует с 1.0 и падает на 0.1 в игровой час
|
||||
только на территории школы, так что порог 0.35 достигается лишь к концу первого дня. Критерий
|
||||
готовности фазы 21 обещает «перемены с коридором и столовой» — со второго дня так и есть, но
|
||||
прогон одного дня, как в критерии написано, столовой не покажет. Это не поломка, это то, чего
|
||||
стоит ожидать при проверке руками.
|
||||
- **Со второго дня голод упирается в ноль и оттуда не выходит.** К концу четырёх учебных дней
|
||||
27 учеников из 176 держат голод ≤0.05, 98 из 176 — ниже порога срочности, средний по школе
|
||||
ровно 0.35. Причина арифметическая: вне школы голод не восстанавливается (в отличие от сна),
|
||||
дома никто не ест, а единственный источник еды — восемь стульев в столовой на 176 человек при
|
||||
обеде в 15 минут. Обедов в день выходит 75–132, то есть до половины школы ежедневно остаётся
|
||||
без еды, и дефицит переносится на завтра. Поскольку рост навыка на уроке зависит от состояния
|
||||
нужд, больше половины школы учится со штрафом постоянно. Это баланс, а не логика: числа лежат
|
||||
в `core` (`decayPerHour`, `needGain`, число стульев на карте) и правятся данными. Молча их
|
||||
менять ревью не стало — см. «Открыто».
|
||||
|
||||
Открыто:
|
||||
|
||||
- **Чем закрывать голод.** Вариантов три, и это решение автора, а не ревью: восстанавливать голод
|
||||
вне школы, как сон (`restoredOffCampus` на `Hunger`); поставить в ванильную столовую больше
|
||||
стульев; или снизить `decayPerHour` голода. Первое честнее всего описывает «поел дома», третье
|
||||
дешевле всего, второе меняет карту. Числа выше дают точку отсчёта для любого из них.
|
||||
|
||||
Замечено рядом (за границами среза):
|
||||
|
||||
- **`GameSocketTests.OpeningASchoolDuringAMathLesson_...` подтверждённо нестабилен.** За сессию
|
||||
он упал четырежды — и все четыре раза в полном `dotnet test` по решению, когда параллельно шла
|
||||
сборка; в одиночку он проходит всегда, в том числе шесть прогонов подряд и два под нагрузкой из
|
||||
шести жгущих процессов. Симптом всегда один: последнее ожидание после снятия паузы — «нанятый
|
||||
учитель появился среди людей в кадре присутствия» — не выполняется за 40 кадров (~20 секунд).
|
||||
Механизм не пойман: инструментированный прогон, печатающий замороженное время и уроки этого
|
||||
учителя, три раза подряд прошёл зелёным. Две правдоподобные версии, обе про то, что тест
|
||||
зависит от игрового времени, набежавшего за время его собственных HTTP-вызовов (5 игровых минут
|
||||
на реальную секунду): либо замороженный момент уезжает за последний урок учителя и он по плану
|
||||
дня уже не приходит, либо за 20 секунд ожидания школьный день успевает кончиться. В обоих
|
||||
случаях чинить надо тест, а не присутствие: занятость узла берётся из расписания, а явка — из
|
||||
состояния, и совпадать они не обязаны — фаза 21 прямо обещает, что «опоздание и отсутствие
|
||||
видны».
|
||||
|
||||
### Перепроверка на `5a00ad7`, 2026-08-19
|
||||
|
||||
`School.cs` изменился на десять строк — родной язык прокинут в `InstallPeople`. Присутствие,
|
||||
ходьба, действия и решения не тронуты, `decayPerHour` и `needGain` тоже, поэтому измеренная выше
|
||||
картина с голодом остаётся в силе: вопрос «чем закрывать голод» по-прежнему открыт.
|
||||
|
||||
### Перепроверка на `450495f`, 2026-08-20
|
||||
|
||||
Дрейф после `5a00ad7` — обеденные смены, веса в `BehaviorDef` (фаза 24), `Decision.cs`,
|
||||
`PresenceSystem` (очередь после действий). Обещания фаз 18–21 целы; протокол остался v7.
|
||||
|
||||
Что подтверждено повторно:
|
||||
|
||||
- **Фаза 18.** Все 13 тестов списка на месте в `WalkingTests` / `PresenceTests`. Пустая школа
|
||||
без учителей в рабочее окно не пропускается. `EnsurePlans` пересобирал планы только при смене
|
||||
дня или численности — после пина или назначения предмета без найма `AppearAt` оставался `null`.
|
||||
- **Фаза 19.** Раскладка присутствия с обеих сторон (`Presence_RoundTrips`, `protocol.test.ts`),
|
||||
снимок карты без людей, пропуск в учебное время отбрасывается. Кадр часов несёт разрешение на
|
||||
пропуск; клиент его не считает.
|
||||
- **Фаза 20.** Декей голода, обед, стулья, ночь вне школы, неизвестная нужда, детерминизм.
|
||||
`SleepAndHunger_ReturnToMaxOffCampus` и `AfterASchoolDay_NobodyIsLeftStarving` закрывают
|
||||
открытый в первом проходе голод.
|
||||
- **Фаза 21.** Восемь тестов списка плюс обеденные веса в `DecisionPlannerTests`. `HSchool.Ai`
|
||||
без Arch/ASP.NET/`DateTime.Now`, `Simulation` без сокетов.
|
||||
|
||||
Исправлено:
|
||||
|
||||
- `School.SetTimetable` обнуляет `PlanDay`. Иначе `EnsurePlans` считает планы актуальными,
|
||||
пока не сменятся день или численность, и после назначения математики в 10:20 никто не приходит:
|
||||
вчерашний план собран по пустой таблице, `AppearAt == null`. Найм это маскировал (численность
|
||||
растёт), пин и назначение — нет.
|
||||
- `OpeningASchoolDuringAMathLesson_...` после снятия паузы сразу ждал людей в кадре. Присутствие
|
||||
уходит и на паузе (пустые люди, подписи урока из таблицы), и 40 кадров бюджета уходили в эти
|
||||
кадры до обработки `SetRunning`. Теперь тест ждёт `clock.Running`, потом людей. Сам хост
|
||||
с Aspire в этой сессии не гонялся (MSB3021).
|
||||
- Ходьба: 13 тестов списка фазы 18 (маршрут, `travelMinutes`, воскресенье/каникулы, звонок,
|
||||
детерминизм, пропуск пустого времени, лето, промотанная неделя).
|
||||
- Присутствие: раскладка с обеих сторон, круговой прогон, люди не в снимке карты, пропуск в
|
||||
учебное время отбрасывается. На паузе кадры **идут** (occupancy + подписи урока); людей в них
|
||||
может не быть.
|
||||
- Нужды: декей, обед, стулья, ночь вне школы, неизвестная нужда, детерминизм.
|
||||
`Hunger` восстанавливается вне школы, в столовой 112 стульев, обед — смена по параллелям.
|
||||
`SleepAndHunger_ReturnToMaxOffCampus`, `AfterASchoolDay_NobodyIsLeftStarving`.
|
||||
- Решения: восемь тестов фазы 21, в том числе туалет с урока и возврат, потолок отложенных,
|
||||
детерминизм за неделю. `HSchool.Ai` без Arch/ASP.NET/`DateTime.Now`.
|
||||
|
||||
Дописано:
|
||||
|
||||
- `HireAndAssignMath_DuringLessonThree_PutsSomeoneOnCampus` — найм на паузе в 10:20, потолок
|
||||
64 решения, шаг 20 Гц, как у работника.
|
||||
- `AssigningMath_AfterDayPlansWereBuilt_PutsSomeoneOnCampus` — назначение без смены численности;
|
||||
без сброса `PlanDay` кампус остаётся пустым.
|
||||
- `HireAndAssignMath_DuringLessonThree_PutsSomeoneOnCampus`
|
||||
- `AssigningMath_AfterDayPlansWereBuilt_PutsSomeoneOnCampus`
|
||||
|
||||
Закрыто из прошлого прохода:
|
||||
Исправлено:
|
||||
|
||||
- **Голод.** Уже закрыто 2026-08-19 (`restoredOffCampus`, стулья 112, смены). Повторно зелёные
|
||||
`NeedDecayTests.SleepAndHunger_ReturnToMaxOffCampus` и `LunchTests.AfterASchoolDay_NobodyIsLeftStarving`.
|
||||
- **`OpeningASchoolDuringAMathLesson_...`.** Это была явка плюс чтение паузных кадров, не флак
|
||||
нагрузки. Симуляция после правки зелёная; хостовый прогон — когда Aspire отпустят DLL.
|
||||
|
||||
Ai 29, Presence+Decision+Activity+NeedDecay+Lunch 31, Presence_RoundTrips 1.
|
||||
- `School.SetTimetable` обнуляет `PlanDay`. Иначе после назначения предмета без смены численности
|
||||
`EnsurePlans` считает планы актуальными, `AppearAt` остаётся `null`, кампус пуст. Найм это
|
||||
маскировал (численность растёт).
|
||||
- `OpeningASchoolDuringAMathLesson_...` после снятия паузы сразу ждал людей и съедал бюджет на
|
||||
паузные кадры. Теперь ждёт `clock.Running`, потом людей.
|
||||
|
||||
## Срез 6. Фундамент
|
||||
|
||||
@@ -664,87 +227,33 @@ Ai 29, Presence+Decision+Activity+NeedDecay+Lunch 31, Presence_RoundTrips 1.
|
||||
`tests/HSchool.Content.Tests/{PackIdentityTests,ExamplePackTests,BehaviorDefTests}.cs`,
|
||||
`tests/HSchool.People.Tests/GoldenRosterTests.cs`,
|
||||
`tests/HSchool.AppHost.Tests/{ExamplePackTests,GoldenSaveTests,SchoolSeedTests,ServiceabilityTests}.cs`
|
||||
- **Итог:** все тесты из списков семи фаз на месте; дописан один клиентский; исправлен ложный
|
||||
gotcha про паузу; `foundation.md` приведён к закрытому срезу. Хостовые тесты сверены по коду,
|
||||
не прогоном — Aspire держит DLL.
|
||||
- **Итог:** все тесты из списков семи фаз на месте; дописан один клиентский; `foundation.md`
|
||||
приведён к закрытому срезу. Хостовые тесты сверены по коду, не прогоном.
|
||||
|
||||
Что подтверждено:
|
||||
|
||||
- **Фаза 22.** Пак без `pack.jsonc` (id вместо названия), подписи `?lang=`, `core` с манифестом,
|
||||
`400 missing-mod` с id недостающего, зависимость грузится раньше зависимого, цикл — `mod-cycle`,
|
||||
def без подписи предупреждает и грузится. Порядок — устойчивая топология поверх выбора игрока,
|
||||
не алфавит; разрешённый список в ответе создания и в сейве.
|
||||
- **Фаза 23.** `mods/example` на диске (`pack.jsonc`, локали, черты, набор имён, патч, комната,
|
||||
README). Копируется в вывод тестов как `core`. `GET /api/catalog?mods=example`, create+reload,
|
||||
патч только с паком, last-wins, карта пака валидна. Ваниль без выбора не меняется.
|
||||
- **Фаза 24.** Веса в `BehaviorDef` с комментариями, что перевешивают. Таблица ванильных решений,
|
||||
пак с обедом выше урока уводит класс, каталог без дефа на константах, отрицательный вес роняет
|
||||
загрузку.
|
||||
- **Фаза 25.** `golden/roster.txt` и первая несовпавшая строка; правило в README рядом. Сейв
|
||||
текущего формата и сейв без `nativeLanguage`. Кривая голода `Hunger_FollowsTheSchoolDayCurve`.
|
||||
`PrimarySchool` требует трёх, второй учитель не закрывает. `teachersShort` в API и в `t(...)`.
|
||||
- **Фаза 26.** Сид — поле школы, не id. Тот же сид — те же люди; без сида после reload тот же
|
||||
состав; золотой сейв `seed == id` грузится; переданный сид в списке. На экране школы и в create.
|
||||
- **Фаза 27.** Format новее — школа не стартует, файл нетронут. Текущий грузится. Дамп через
|
||||
снимок + мейлбокс (`DumpSchool` → работник), не в `World` с HTTP. `404 unknown-school`.
|
||||
`HSchool.Simulation.Tests` без параллельности. Дамп в `docs/protocol.md` за тем же
|
||||
переключателем, что reload.
|
||||
- **Фаза 28.** `happy-dom` на экранах; фильтры/пейджер, create (`core` нельзя снять, сброс карты,
|
||||
busy submit), сетка (pin-rejected / no-teacher / unknown-lesson), предел фонда текстом.
|
||||
Политика в `AGENTS.md`. `npm test` — 46 тестов, ~5 с.
|
||||
- **Инварианты.** `Simulation` без `DateTime.Now`. Протокол не бампили. Сид в хостовых тестах,
|
||||
которым нужен состав, передаётся явно.
|
||||
- Пак: манифест, `missing-mod`, порядок — выбор игрока плюс топология (не алфавит), цикл —
|
||||
`mod-cycle`, def без подписи предупреждает и грузится.
|
||||
- `mods/example` на диске; каталог/create/reload; патч только с паком; ваниль без выбора не меняется.
|
||||
- Веса в `BehaviorDef`; пак с обедом выше урока уводит класс; отрицательный вес роняет загрузку.
|
||||
- Золотой ростер и сейв; `PrimarySchool` требует трёх; `teachersShort` в API и в `t(...)`.
|
||||
- Сид — поле школы. Format новее — школа не стартует, файл нетронут. Дамп через снимок + мейлбокс,
|
||||
не в `World` с HTTP. `HSchool.Simulation.Tests` без параллельности.
|
||||
- Клиентские экраны в `happy-dom`: фильтры/пейджер, create, сетка, предел фонда текстом.
|
||||
|
||||
Дописано:
|
||||
|
||||
- `managementPanel.test.ts` — непокрытый предмет показывает, скольких учителей не хватает
|
||||
(`staffUncoveredShort` с `n: 3`). Задача фазы 25 была в коде без теста экрана.
|
||||
- `managementPanel.test.ts` — непокрытый предмет показывает `teachersShort`.
|
||||
|
||||
Исправлено:
|
||||
|
||||
- `AGENTS.md` утверждал, что на паузе кадры присутствия не приходят вовсе. Это ложь: работник
|
||||
крутит цикл и шлёт occupancy + подписи урока из таблицы. Фаза 27 записала заблуждение ревью.
|
||||
Строка приведена к факту (тест, который ждёт *людей* на паузе, зависнет; тест на подпись урока —
|
||||
нет).
|
||||
- В `design/foundation.md` «порядок — алфавит плюс зависимости» расходился с кодом (порядок
|
||||
игрока + топология). «Почему сейчас» про веса в `Decision.cs` устарел — срез это закрыл.
|
||||
- `AGENTS.md` утверждал, что на паузе кадры присутствия не приходят. Работник их шлёт
|
||||
(occupancy + подписи). Тест, который ждёт *людей* на паузе, зависнет; тест на подпись урока — нет.
|
||||
- `design/foundation.md`: порядок загрузки — не алфавит; «почему сейчас» про веса в `Decision.cs`
|
||||
устарел.
|
||||
|
||||
Замечено рядом:
|
||||
|
||||
- `Dump_ReturnsPeopleNodesAndTimetable` принимает `NodeId is not null || Needs.Count > 0`.
|
||||
Нужды есть у всех, так что узлы на кампусе не проверяются. Дамп поле `nodeId` отдаёт; критерий
|
||||
«кто где стоит» руками. Усиливать до явки — соседний срез 5, не здесь.
|
||||
- Срез 7 (одежда) в работе: фазы 29–30 🔄, 31–37 ⬜. В журнал как закрытый не писать.
|
||||
|
||||
Content 17, People 2, Ai 3, Hunger curve 1, клиент 46/46. AppHost не гонялся.
|
||||
|
||||
## Что из журнала закрыто, 2026-08-19
|
||||
|
||||
Ревью нашло семь пунктов; шесть закрыты в этот же день, седьмой снят как несуществующий.
|
||||
|
||||
- **Панель «Общие события».** Решено отказаться. `design/near-term.md` и `design/people.md`
|
||||
переписаны под вкладочную оболочку, фазы 1 и 8 помечены сноской, мёртвые ключи
|
||||
`eventsTitle`/`eventsEmpty` убраны из `i18n`. Экран не менялся — он и был правдой.
|
||||
- **Голод упирался в ноль.** Закрыто тремя правками данных и одной правкой поведения:
|
||||
`Hunger` восстанавливается вне школы (дома едят), `decayPerHour` 0.1 → 0.2, стульев в столовой
|
||||
8 → 112, и обед стал сменой по параллелям. Замер после: приходят с 0.97, к своей смене 0.43,
|
||||
уходят с 0.27, к утру снова 1.0; за неделю голодающих нет ни одного (было 27 из 176 на нуле и
|
||||
98 ниже порога).
|
||||
- **Раздельные обеды.** Новая механика: `DayFrameDef.lunchBreaks` — какая параллель ест после
|
||||
какого урока, `ActionDef.lunch` — действие-смена. В свою смену едят и не проголодавшиеся
|
||||
(`DecisionPlanner.LunchWeight`), вне смены столовая не предлагается вовсе. В `core` младшие
|
||||
(1–5) едят после третьего урока, старшие (6–11) после четвёртого; обе перемены стали длинными.
|
||||
Замер: 11:10–11:30 в столовой только младшие, 12:15–12:30 только старшие, поели все 176.
|
||||
- **`SchoolRegistry`.** Удалён вместе со своими тестами. `TryNormalizeName` переехал в
|
||||
`SchoolNames`, `SchoolCreationError` — в свой файл; правила имени, диапазона дат и генератора
|
||||
названий закреплены в `SchoolNamesTests`.
|
||||
- **Нестабильный `OpeningASchoolDuringAMathLesson_...`.** Последнее ожидание требовало, чтобы
|
||||
нанятый в середине дня учитель появился на территории, — а это не гарантировано: явка идёт из
|
||||
плана дня, и замороженный момент уезжает тем дальше, чем дольше сам тест ходил по HTTP. Теперь
|
||||
тест проверяет то, ради чего написан: что люди вообще едут в кадре присутствия.
|
||||
- **Ветка `if/else` вокруг предела в `AssignAndUnassign_HonourTheCap_...`** убрана: отказ по
|
||||
пределу проверяется отдельным тестом, а этот про назначение, снятие и перезапуск.
|
||||
- **Предел фонда «почти не ограничивает игрока»** — снято при перепроверке на `5a00ad7`: это была
|
||||
ошибка замера, а не код. Подробности в разделе среза 3.
|
||||
|
||||
Тесты после всех правок: 315 .NET и 33 клиентских, сборка клиента зелёная.
|
||||
Нужды есть у всех, так что узлы на кампусе не проверяются. Усиливать до явки — срез 5.
|
||||
- Срез 7 (одежда) в работе: не писать в журнал как закрытый.
|
||||
|
||||
+30
-2
@@ -211,7 +211,8 @@ are `400` `invalid-query`. `lang` is `ru` or `en`, same as the catalog — anyth
|
||||
}
|
||||
```
|
||||
|
||||
The list row is identity only — skills, traits and needs stay on the card. Age is computed from
|
||||
The list row is identity only — skills, traits, needs, clothes and what they carry stay on the
|
||||
card. Age is computed from
|
||||
`birthDate` and the published game time, not from the World.
|
||||
|
||||
Applicants live in `saves/{id}.people.json` next to the roster and are **not** in this list.
|
||||
@@ -254,6 +255,11 @@ is that def in the request locale. HTTP JSON is additive — no protocol version
|
||||
`skills` lists only keys the person has, not every `SkillDef` in the catalog. A first-year has
|
||||
no Chemistry; a related tongue from the name set may sit beside the native at a low value.
|
||||
|
||||
`worn` is what is on the body right now: def, colour, and the layers it occupies. `carried` is
|
||||
the bag — textbooks include `subject`. `carryMass` / `carryCapacity` are kilograms; overload
|
||||
does not slow walking. Home and locker stay in `people.json` and are not on this card. The
|
||||
people list does not include any of these fields.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "f0.c0",
|
||||
@@ -276,7 +282,29 @@ no Chemistry; a related tongue from the name set may sit beside the native at a
|
||||
"children": [],
|
||||
"siblings": [{ "id": "f0.c1", "fullName": "Иванов Кирилл Петрович", "female": false }],
|
||||
"partners": []
|
||||
}
|
||||
},
|
||||
"worn": [
|
||||
{
|
||||
"defName": "Shirt",
|
||||
"label": "Рубашка",
|
||||
"color": "White",
|
||||
"colorLabel": "Белый",
|
||||
"layers": [{ "defName": "Top", "label": "Верх" }]
|
||||
}
|
||||
],
|
||||
"carried": [
|
||||
{
|
||||
"defName": "Textbook",
|
||||
"label": "Учебник",
|
||||
"color": null,
|
||||
"colorLabel": null,
|
||||
"subject": "Mathematics",
|
||||
"subjectLabel": "Математика",
|
||||
"mass": 0.4
|
||||
}
|
||||
],
|
||||
"carryMass": 1.2,
|
||||
"carryCapacity": 14
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ describe('t', () => {
|
||||
.toBe('Not enough money: 8 000 of 10 000 is committed, 2 000 free, 12 000 needed.');
|
||||
expect(t('staffUncoveredShort', { label: 'Начальные классы', min: 1, max: 4, n: 3 }))
|
||||
.toBe('Начальные классы (1–4) — 3 short');
|
||||
expect(t('peopleCarryMass', { held: '1.2', cap: '14' })).toBe('1.2 / 14 kg');
|
||||
expect(t('mapOccupancy', { name: 'Кабинет 204', activity: 'Математика · 5Б' }))
|
||||
.toBe('Кабинет 204 (Математика · 5Б)');
|
||||
expect(t('weatherPrecip', { temp: '\u22125', precip: t('precipSnow') })).toBe('\u22125 °C, snow');
|
||||
|
||||
@@ -128,6 +128,9 @@ const ru = {
|
||||
peopleSkills: 'Навыки',
|
||||
peopleTraits: 'Черты',
|
||||
peopleNeeds: 'Нужды',
|
||||
peopleApparel: 'Одежда',
|
||||
peopleCarry: 'Ноша',
|
||||
peopleCarryMass: '{held} / {cap} кг',
|
||||
peopleFamily: 'Семья',
|
||||
peopleParents: 'Родители',
|
||||
peopleChildren: 'Дети',
|
||||
@@ -349,6 +352,9 @@ const en: Messages = {
|
||||
peopleSkills: 'Skills',
|
||||
peopleTraits: 'Traits',
|
||||
peopleNeeds: 'Needs',
|
||||
peopleApparel: 'Clothes',
|
||||
peopleCarry: 'Carried',
|
||||
peopleCarryMass: '{held} / {cap} kg',
|
||||
peopleFamily: 'Family',
|
||||
peopleParents: 'Parents',
|
||||
peopleChildren: 'Children',
|
||||
|
||||
@@ -291,6 +291,28 @@ export interface PersonCard {
|
||||
readonly siblings: readonly PersonRel[];
|
||||
readonly partners: readonly PersonRel[];
|
||||
};
|
||||
readonly worn: readonly WornItem[];
|
||||
readonly carried: readonly CarriedItem[];
|
||||
readonly carryMass: number;
|
||||
readonly carryCapacity: number;
|
||||
}
|
||||
|
||||
export interface WornItem {
|
||||
readonly defName: string;
|
||||
readonly label: string;
|
||||
readonly color: string | null;
|
||||
readonly colorLabel: string | null;
|
||||
readonly layers: readonly DefLabel[];
|
||||
}
|
||||
|
||||
export interface CarriedItem {
|
||||
readonly defName: string;
|
||||
readonly label: string;
|
||||
readonly color: string | null;
|
||||
readonly colorLabel: string | null;
|
||||
readonly subject: string | null;
|
||||
readonly subjectLabel: string | null;
|
||||
readonly mass: number;
|
||||
}
|
||||
|
||||
export async function fetchPeople(schoolId: number, query: PeopleQuery, lang: string): Promise<PeoplePage> {
|
||||
|
||||
@@ -650,6 +650,11 @@ body {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.people__carry-mass {
|
||||
margin: 0 0 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.people__pair {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
||||
@@ -55,6 +55,10 @@ function personCard(): PersonCard {
|
||||
activity: null,
|
||||
activityLabel: null,
|
||||
family: { parents: [], children: [], siblings: [], partners: [] },
|
||||
worn: [],
|
||||
carried: [],
|
||||
carryMass: 0,
|
||||
carryCapacity: 0,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @vitest-environment happy-dom
|
||||
*/
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
import type { PersonCard } from '../net/api.ts';
|
||||
import { getLocale, setLocale } from '../i18n/locale.ts';
|
||||
import { t } from '../i18n/strings.ts';
|
||||
import { renderPersonCard } from './personCard.ts';
|
||||
|
||||
const initial = getLocale();
|
||||
|
||||
afterEach(() => setLocale(initial));
|
||||
|
||||
function card(overrides: Partial<PersonCard> = {}): PersonCard {
|
||||
return {
|
||||
id: 'f0.c0',
|
||||
fullName: 'Иванова Мария',
|
||||
surname: 'Иванова',
|
||||
given: 'Мария',
|
||||
patronymic: '',
|
||||
female: true,
|
||||
age: 12,
|
||||
birthDate: '2000-03-14',
|
||||
roles: ['student'],
|
||||
classYear: 5,
|
||||
classLetter: 'А',
|
||||
classId: 'class-1',
|
||||
position: null,
|
||||
positionLabel: null,
|
||||
body: [],
|
||||
skills: [],
|
||||
traits: [],
|
||||
needs: [],
|
||||
activity: null,
|
||||
activityLabel: null,
|
||||
family: { parents: [], children: [], siblings: [], partners: [] },
|
||||
worn: [
|
||||
{
|
||||
defName: 'Shirt',
|
||||
label: 'Рубашка',
|
||||
color: 'White',
|
||||
colorLabel: 'Белый',
|
||||
layers: [{ defName: 'Top', label: 'Верх' }],
|
||||
},
|
||||
],
|
||||
carried: [
|
||||
{
|
||||
defName: 'Textbook',
|
||||
label: 'Учебник',
|
||||
color: null,
|
||||
colorLabel: null,
|
||||
subject: 'Mathematics',
|
||||
subjectLabel: 'Математика',
|
||||
mass: 0.4,
|
||||
},
|
||||
],
|
||||
carryMass: 1.2,
|
||||
carryCapacity: 14,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe('renderPersonCard', () => {
|
||||
it('shows worn layers with colour and carried mass in the same scroll', () => {
|
||||
setLocale('ru');
|
||||
const root = document.createElement('div');
|
||||
renderPersonCard(root, card(), () => {});
|
||||
|
||||
expect(root.textContent).toContain(t('peopleApparel'));
|
||||
expect(root.textContent).toContain('Верх');
|
||||
expect(root.textContent).toContain('Рубашка · Белый');
|
||||
expect(root.textContent).toContain(t('peopleCarry'));
|
||||
expect(root.textContent).toContain(t('peopleCarryMass', { held: '1.2', cap: '14' }));
|
||||
expect(root.textContent).toContain('Учебник · Математика');
|
||||
expect(root.querySelector('.people__tabs')).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -47,6 +47,8 @@ export function renderPersonCard(
|
||||
appendPairs(parent, t('peopleSkills'), card.skills);
|
||||
appendTags(parent, t('peopleTraits'), card.traits.map((row) => row.label));
|
||||
appendNeeds(parent, t('peopleNeeds'), card.needs);
|
||||
appendApparel(parent, card.worn);
|
||||
appendCarry(parent, card);
|
||||
|
||||
const family = section(t('peopleFamily'));
|
||||
appendRelatives(family, t('peopleParents'), card.family.parents, onRelative);
|
||||
@@ -112,6 +114,58 @@ function appendPairs(
|
||||
parent.append(section(title), grid);
|
||||
}
|
||||
|
||||
function appendApparel(parent: HTMLElement, rows: PersonCard['worn']): void {
|
||||
if (rows.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const grid = el('dl', { class: 'people__pairs' });
|
||||
for (const row of rows) {
|
||||
const layers = row.layers.map((layer) => layer.label).join(', ');
|
||||
const color = row.colorLabel ?? row.color;
|
||||
const value = color !== null && color.length > 0 ? `${row.label} · ${color}` : row.label;
|
||||
grid.append(
|
||||
el(
|
||||
'div',
|
||||
{ class: 'people__pair' },
|
||||
el('dt', { text: layers.length > 0 ? layers : row.label }),
|
||||
el('dd', { text: value }),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
parent.append(section(t('peopleApparel')), grid);
|
||||
}
|
||||
|
||||
function appendCarry(parent: HTMLElement, card: PersonCard): void {
|
||||
const mass = el('p', {
|
||||
class: 'people__carry-mass',
|
||||
text: t('peopleCarryMass', { held: formatMass(card.carryMass), cap: formatMass(card.carryCapacity) }),
|
||||
});
|
||||
const grid = el('dl', { class: 'people__pairs' });
|
||||
for (const row of card.carried) {
|
||||
const extra = row.subjectLabel ?? row.colorLabel;
|
||||
const value = extra !== null && extra.length > 0 ? `${row.label} · ${extra}` : row.label;
|
||||
grid.append(
|
||||
el(
|
||||
'div',
|
||||
{ class: 'people__pair' },
|
||||
el('dt', { text: value }),
|
||||
el('dd', { text: formatMass(row.mass) }),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
parent.append(section(t('peopleCarry')), mass);
|
||||
if (card.carried.length > 0) {
|
||||
parent.append(grid);
|
||||
}
|
||||
}
|
||||
|
||||
function formatMass(value: number): string {
|
||||
return String(Math.round(value * 100) / 100);
|
||||
}
|
||||
|
||||
function appendTags(parent: HTMLElement, title: string, values: readonly string[]): void {
|
||||
if (values.length === 0) {
|
||||
return;
|
||||
|
||||
@@ -609,6 +609,11 @@ public sealed class CatalogLoader
|
||||
throw new ContentLoadException($"ThingDef '{thing.DefName}' has unknown skirtLength '{thing.SkirtLength}'.");
|
||||
}
|
||||
|
||||
if (thing.CarryChance is < 0f or > 1f)
|
||||
{
|
||||
throw new ContentLoadException($"ThingDef '{thing.DefName}' carryChance must be 0–1.");
|
||||
}
|
||||
|
||||
var layers = new HashSet<string>(StringComparer.Ordinal);
|
||||
foreach (var layer in thing.Layers)
|
||||
{
|
||||
|
||||
@@ -104,6 +104,12 @@ public sealed class ThingDef : Def
|
||||
|
||||
/// <summary>PE kit. Worn for that lesson; not a second wardrobe of everyday clothes.</summary>
|
||||
public bool Pe { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Chance the dress generator issues this portable non-apparel item. 0 — not rolled (textbooks
|
||||
/// are granted per subject instead). Apparel ignores this and fills layers.
|
||||
/// </summary>
|
||||
public float CarryChance { get; init; }
|
||||
}
|
||||
|
||||
public sealed class PositionDef : Def;
|
||||
|
||||
@@ -518,6 +518,19 @@ internal static class PeopleDefValidator
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' goal weights cannot be negative.");
|
||||
}
|
||||
|
||||
if (behavior.CarryMassBase < 0f
|
||||
|| behavior.CarryMassPerStrength < 0f
|
||||
|| behavior.CarryMassPerEndurance < 0f
|
||||
|| behavior.CarryMassPerHauling < 0f)
|
||||
{
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' carry mass cannot be negative.");
|
||||
}
|
||||
|
||||
if (behavior.OptionalApparelChance is < 0f or > 1f)
|
||||
{
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' optionalApparelChance must be 0–1.");
|
||||
}
|
||||
|
||||
// A pack may invert this on purpose — lunch then pulls the class out of the lesson.
|
||||
// The warning is the catch; refusing to load would make the number unmoddable.
|
||||
if (behavior.LunchWeight > behavior.DutyLessonWeight)
|
||||
|
||||
@@ -256,6 +256,18 @@ public sealed class BehaviorDef : Def
|
||||
/// pulls anybody out of a lesson.
|
||||
/// </summary>
|
||||
public float LunchWeight { get; init; } = 6f;
|
||||
|
||||
/// <summary>Kilograms a person can carry at strength/endurance/hauling 0, before the per-skill terms.</summary>
|
||||
public float CarryMassBase { get; init; } = 5f;
|
||||
|
||||
public float CarryMassPerStrength { get; init; } = 0.08f;
|
||||
|
||||
public float CarryMassPerEndurance { get; init; } = 0.04f;
|
||||
|
||||
public float CarryMassPerHauling { get; init; } = 0.08f;
|
||||
|
||||
/// <summary>Chance each optional layer (sweater, coat, hat, accessory) is worn at generation.</summary>
|
||||
public float OptionalApparelChance { get; init; } = 0.4f;
|
||||
}
|
||||
|
||||
public enum BodyAttributeKind
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
namespace HSchool.People;
|
||||
|
||||
/// <summary>
|
||||
/// How much a person may carry in the bag. The curve lives on <see cref="BehaviorDef"/>;
|
||||
/// these fallbacks match vanilla so a pack without the new fields still dresses people.
|
||||
/// Worn mass does not count in this slice, and overload does not slow walking.
|
||||
/// </summary>
|
||||
public static class CarryMass
|
||||
{
|
||||
public const string Strength = "Strength";
|
||||
public const string Endurance = "Endurance";
|
||||
public const string Hauling = "Hauling";
|
||||
|
||||
public const float DefaultBase = 5f;
|
||||
public const float DefaultPerStrength = 0.08f;
|
||||
public const float DefaultPerEndurance = 0.04f;
|
||||
public const float DefaultPerHauling = 0.08f;
|
||||
|
||||
public static float Capacity(DefCatalog catalog, IReadOnlyDictionary<string, int> skills) =>
|
||||
Capacity(catalog, Skill(skills, Strength), Skill(skills, Endurance), Skill(skills, Hauling));
|
||||
|
||||
public static float Capacity(DefCatalog catalog, IReadOnlyDictionary<string, float> skills) =>
|
||||
Capacity(
|
||||
catalog,
|
||||
Skill(skills, Strength),
|
||||
Skill(skills, Endurance),
|
||||
Skill(skills, Hauling));
|
||||
|
||||
public static float Capacity(DefCatalog catalog, float strength, float endurance, float hauling)
|
||||
{
|
||||
var rules = catalog.BehaviorRules;
|
||||
var value = (rules?.CarryMassBase ?? DefaultBase)
|
||||
+ (strength * (rules?.CarryMassPerStrength ?? DefaultPerStrength))
|
||||
+ (endurance * (rules?.CarryMassPerEndurance ?? DefaultPerEndurance))
|
||||
+ (hauling * (rules?.CarryMassPerHauling ?? DefaultPerHauling));
|
||||
return MathF.Round(MathF.Max(value, 0f), 2);
|
||||
}
|
||||
|
||||
public static float Held(DefCatalog catalog, IEnumerable<InventoryItem> items)
|
||||
{
|
||||
var sum = 0f;
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (!item.Location.Equals(ItemLocations.Bag, StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (catalog.Things.TryGetValue(item.Def, out var def))
|
||||
{
|
||||
sum += def.Mass;
|
||||
}
|
||||
}
|
||||
|
||||
return MathF.Round(sum, 2);
|
||||
}
|
||||
|
||||
private static float Skill(IReadOnlyDictionary<string, int> skills, string name) =>
|
||||
skills.TryGetValue(name, out var value) ? value : 0f;
|
||||
|
||||
private static float Skill(IReadOnlyDictionary<string, float> skills, string name) =>
|
||||
skills.TryGetValue(name, out var value) ? value : 0f;
|
||||
}
|
||||
@@ -0,0 +1,414 @@
|
||||
namespace HSchool.People;
|
||||
|
||||
/// <summary>
|
||||
/// Fills a person's wardrobe from a stream that does not touch looks or skills. Same person id
|
||||
/// and school seed always yield the same items, colours and places.
|
||||
/// </summary>
|
||||
public static class DressGenerator
|
||||
{
|
||||
public static Person Dress(DefCatalog catalog, Person person, int schoolSeed, int? pupilYear)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(catalog);
|
||||
ArgumentNullException.ThrowIfNull(person);
|
||||
|
||||
var age = person.AgeOn(RosterGenerator.DefaultAsOf);
|
||||
return Dress(catalog, person, schoolSeed, pupilYear, age);
|
||||
}
|
||||
|
||||
public static Person Dress(
|
||||
DefCatalog catalog,
|
||||
Person person,
|
||||
int schoolSeed,
|
||||
int? pupilYear,
|
||||
int age)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(catalog);
|
||||
ArgumentNullException.ThrowIfNull(person);
|
||||
|
||||
var rng = new Random(Seed.Mix(schoolSeed, person.Id, dayNumber: 0, Seed.ApparelSalt));
|
||||
var items = new List<InventoryItem>();
|
||||
var occupied = new HashSet<string>(StringComparer.Ordinal);
|
||||
var chance = catalog.BehaviorRules?.OptionalApparelChance ?? 0.4f;
|
||||
|
||||
foreach (var layer in RequiredLayers)
|
||||
{
|
||||
TryWear(catalog, person, age, rng, layer, occupied, items);
|
||||
}
|
||||
|
||||
foreach (var layer in OptionalLayers)
|
||||
{
|
||||
if (rng.NextDouble() < chance)
|
||||
{
|
||||
TryWear(catalog, person, age, rng, layer, occupied, items);
|
||||
}
|
||||
}
|
||||
|
||||
if (!occupied.Contains(ApparelLayers.Outer))
|
||||
{
|
||||
TryStashOuter(catalog, person, age, rng, items);
|
||||
}
|
||||
|
||||
if (person.IsStudent && HasPhysicalEducation(catalog, pupilYear))
|
||||
{
|
||||
GrantPeKit(catalog, person, age, rng, items);
|
||||
}
|
||||
|
||||
var capacity = CarryMass.Capacity(catalog, person.Skills);
|
||||
var held = 0f;
|
||||
GrantChanceCarry(catalog, person, age, rng, items, ref held, capacity);
|
||||
if (person.IsStudent && pupilYear is { } year)
|
||||
{
|
||||
GrantTextbooks(catalog, year, rng, items, ref held, capacity);
|
||||
}
|
||||
|
||||
return person with { Items = items };
|
||||
}
|
||||
|
||||
public static Person EnsureDressed(
|
||||
DefCatalog catalog,
|
||||
Person person,
|
||||
int schoolSeed,
|
||||
int? pupilYear,
|
||||
int age)
|
||||
{
|
||||
if (person.Items.Count > 0)
|
||||
{
|
||||
return person;
|
||||
}
|
||||
|
||||
return Dress(catalog, person, schoolSeed, pupilYear, age);
|
||||
}
|
||||
|
||||
public static Roster EnsureRoster(DefCatalog catalog, Roster roster, int schoolSeed, DateTime asOf)
|
||||
{
|
||||
var years = roster.Classes.ToDictionary(
|
||||
schoolClass => schoolClass.Id,
|
||||
schoolClass => schoolClass.Year,
|
||||
StringComparer.Ordinal);
|
||||
var people = new Person[roster.People.Count];
|
||||
for (var i = 0; i < roster.People.Count; i++)
|
||||
{
|
||||
var person = roster.People[i];
|
||||
int? year = person.ClassId is { } classId && years.TryGetValue(classId, out var value)
|
||||
? value
|
||||
: null;
|
||||
people[i] = EnsureDressed(catalog, person, schoolSeed, year, person.AgeOn(asOf));
|
||||
}
|
||||
|
||||
return new Roster(people, roster.Families, roster.Classes);
|
||||
}
|
||||
|
||||
public static ApplicantPool EnsurePool(
|
||||
DefCatalog catalog,
|
||||
ApplicantPool pool,
|
||||
Roster roster,
|
||||
int schoolSeed,
|
||||
DateTime asOf)
|
||||
{
|
||||
var rosterPeople = roster.People.ToDictionary(person => person.Id, StringComparer.Ordinal);
|
||||
var applicants = new Applicant[pool.Applicants.Count];
|
||||
for (var i = 0; i < pool.Applicants.Count; i++)
|
||||
{
|
||||
var applicant = pool.Applicants[i];
|
||||
if (rosterPeople.TryGetValue(applicant.Person.Id, out var member))
|
||||
{
|
||||
applicants[i] = applicant with { Person = member };
|
||||
continue;
|
||||
}
|
||||
|
||||
applicants[i] = applicant with
|
||||
{
|
||||
Person = EnsureDressed(
|
||||
catalog,
|
||||
applicant.Person,
|
||||
schoolSeed,
|
||||
pupilYear: null,
|
||||
applicant.Person.AgeOn(asOf)),
|
||||
};
|
||||
}
|
||||
|
||||
return pool with { Applicants = applicants };
|
||||
}
|
||||
|
||||
public static bool NeedsDressing(Roster roster, ApplicantPool? pool)
|
||||
{
|
||||
foreach (var person in roster.People)
|
||||
{
|
||||
if (person.Items.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (pool is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var applicant in pool.Applicants)
|
||||
{
|
||||
if (applicant.Person.Items.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds textbooks for subjects the pupil just became old enough for. Existing clothes stay.
|
||||
/// </summary>
|
||||
public static Person EnsureYearTextbooks(DefCatalog catalog, Person person, int year)
|
||||
{
|
||||
if (!person.IsStudent)
|
||||
{
|
||||
return person;
|
||||
}
|
||||
|
||||
var items = person.Items.ToList();
|
||||
var held = CarryMass.Held(catalog, items);
|
||||
var capacity = CarryMass.Capacity(catalog, person.Skills);
|
||||
var rng = new Random(0);
|
||||
GrantTextbooks(catalog, year, rng, items, ref held, capacity);
|
||||
return person with { Items = items };
|
||||
}
|
||||
|
||||
private static readonly string[] RequiredLayers =
|
||||
[ApparelLayers.Underwear, ApparelLayers.Socks, ApparelLayers.Bottom, ApparelLayers.Top, ApparelLayers.Shoes];
|
||||
|
||||
private static readonly string[] OptionalLayers =
|
||||
[ApparelLayers.OverTop, ApparelLayers.Outer, ApparelLayers.Head, ApparelLayers.Accessory];
|
||||
|
||||
private static void TryWear(
|
||||
DefCatalog catalog,
|
||||
Person person,
|
||||
int age,
|
||||
Random rng,
|
||||
string layer,
|
||||
HashSet<string> occupied,
|
||||
List<InventoryItem> items)
|
||||
{
|
||||
if (occupied.Contains(layer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var candidates = Apparel(catalog, person.Female, age, everyday: true)
|
||||
.Where(def => def.Layers.Contains(layer, StringComparer.Ordinal)
|
||||
&& def.Layers.All(candidate => !occupied.Contains(candidate)))
|
||||
.ToList();
|
||||
if (candidates.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pick = candidates[rng.Next(candidates.Count)];
|
||||
var color = PickColor(catalog, pick, rng, worn: true);
|
||||
items.Add(new InventoryItem(pick.DefName, color, Condition: 1, ItemLocations.Worn));
|
||||
foreach (var taken in pick.Layers)
|
||||
{
|
||||
occupied.Add(taken);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TryStashOuter(
|
||||
DefCatalog catalog,
|
||||
Person person,
|
||||
int age,
|
||||
Random rng,
|
||||
List<InventoryItem> items)
|
||||
{
|
||||
var candidates = Apparel(catalog, person.Female, age, everyday: true)
|
||||
.Where(def => def.Layers.Contains(ApparelLayers.Outer, StringComparer.Ordinal))
|
||||
.ToList();
|
||||
if (candidates.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pick = candidates[rng.Next(candidates.Count)];
|
||||
var color = PickColor(catalog, pick, rng, worn: false);
|
||||
items.Add(new InventoryItem(pick.DefName, color, Condition: 1, ItemLocations.Home));
|
||||
}
|
||||
|
||||
private static void GrantPeKit(
|
||||
DefCatalog catalog,
|
||||
Person person,
|
||||
int age,
|
||||
Random rng,
|
||||
List<InventoryItem> items)
|
||||
{
|
||||
foreach (var def in Apparel(catalog, person.Female, age, everyday: false).Where(candidate => candidate.Pe))
|
||||
{
|
||||
var color = PickColor(catalog, def, rng, worn: false);
|
||||
items.Add(new InventoryItem(def.DefName, color, Condition: 1, ItemLocations.Home));
|
||||
}
|
||||
}
|
||||
|
||||
private static void GrantChanceCarry(
|
||||
DefCatalog catalog,
|
||||
Person person,
|
||||
int age,
|
||||
Random rng,
|
||||
List<InventoryItem> items,
|
||||
ref float held,
|
||||
float capacity)
|
||||
{
|
||||
foreach (var def in catalog.Things.Values
|
||||
.Where(thing => !thing.Abstract
|
||||
&& thing.Portable
|
||||
&& thing.Layers.Count == 0
|
||||
&& thing.CarryChance > 0)
|
||||
.OrderBy(thing => thing.DefName, StringComparer.Ordinal))
|
||||
{
|
||||
if (!AgeFits(def, age) || !SexFits(def, person.Female))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rng.NextDouble() >= def.CarryChance)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var color = PickColor(catalog, def, rng, worn: false);
|
||||
Place(catalog, items, def, color, subject: null, ref held, capacity);
|
||||
}
|
||||
}
|
||||
|
||||
private static void GrantTextbooks(
|
||||
DefCatalog catalog,
|
||||
int year,
|
||||
Random rng,
|
||||
List<InventoryItem> items,
|
||||
ref float held,
|
||||
float capacity)
|
||||
{
|
||||
var textbook = catalog.Things.Values
|
||||
.Where(thing => !thing.Abstract
|
||||
&& thing.Portable
|
||||
&& thing.Layers.Count == 0
|
||||
&& thing.CarryChance <= 0)
|
||||
.OrderBy(thing => thing.DefName, StringComparer.Ordinal)
|
||||
.FirstOrDefault();
|
||||
if (textbook is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var have = items
|
||||
.Where(item => item.Def.Equals(textbook.DefName, StringComparison.Ordinal) && item.Subject is not null)
|
||||
.Select(item => item.Subject!)
|
||||
.ToHashSet(StringComparer.Ordinal);
|
||||
|
||||
foreach (var subject in catalog.Subjects.Values
|
||||
.Where(def => !def.Abstract && year >= def.Grades.Min && year <= def.Grades.Max)
|
||||
.OrderBy(def => def.DefName, StringComparer.Ordinal))
|
||||
{
|
||||
if (!have.Add(subject.DefName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var color = PickColor(catalog, textbook, rng, worn: false);
|
||||
Place(catalog, items, textbook, color, subject.DefName, ref held, capacity);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Place(
|
||||
DefCatalog catalog,
|
||||
List<InventoryItem> items,
|
||||
ThingDef def,
|
||||
string? color,
|
||||
string? subject,
|
||||
ref float held,
|
||||
float capacity)
|
||||
{
|
||||
var location = held + def.Mass <= capacity ? ItemLocations.Bag : ItemLocations.Home;
|
||||
items.Add(new InventoryItem(def.DefName, color, Condition: 1, location, subject));
|
||||
if (location.Equals(ItemLocations.Bag, StringComparison.Ordinal))
|
||||
{
|
||||
held = MathF.Round(held + def.Mass, 2);
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<ThingDef> Apparel(DefCatalog catalog, bool female, int age, bool everyday)
|
||||
{
|
||||
foreach (var def in catalog.Things.Values.OrderBy(thing => thing.DefName, StringComparer.Ordinal))
|
||||
{
|
||||
if (def.Abstract || def.Layers.Count == 0 || !AgeFits(def, age) || !SexFits(def, female))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (everyday)
|
||||
{
|
||||
if (def.Pe)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (def.SkirtLength is not null
|
||||
&& def.SkirtLength.Equals(SkirtLengths.Short, StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
yield return def;
|
||||
}
|
||||
}
|
||||
|
||||
private static string? PickColor(DefCatalog catalog, ThingDef def, Random rng, bool worn)
|
||||
{
|
||||
if (def.Colors.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var pool = def.Colors.ToList();
|
||||
if (worn)
|
||||
{
|
||||
var quiet = def.Colors
|
||||
.Where(id => catalog.Colors.TryGetValue(id, out var color)
|
||||
&& !color.Tags.Contains(ColorTags.Bright, StringComparer.Ordinal))
|
||||
.ToList();
|
||||
if (quiet.Count > 0)
|
||||
{
|
||||
pool = quiet;
|
||||
}
|
||||
}
|
||||
|
||||
pool.Sort(StringComparer.Ordinal);
|
||||
return pool[rng.Next(pool.Count)];
|
||||
}
|
||||
|
||||
private static bool AgeFits(ThingDef def, int age) =>
|
||||
def.Age is not { } range || (age >= range.Min && age <= range.Max);
|
||||
|
||||
private static bool SexFits(ThingDef def, bool female)
|
||||
{
|
||||
if (def.Sex is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var want = female ? "female" : "male";
|
||||
return def.Sex.Equals(want, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static bool HasPhysicalEducation(DefCatalog catalog, int? pupilYear)
|
||||
{
|
||||
if (pupilYear is not { } year)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return catalog.Subjects.Values.Any(subject =>
|
||||
!subject.Abstract
|
||||
&& subject.DefName.Equals("PhysicalEducation", StringComparison.Ordinal)
|
||||
&& year >= subject.Grades.Min
|
||||
&& year <= subject.Grades.Max);
|
||||
}
|
||||
}
|
||||
@@ -78,40 +78,50 @@ internal static class FamilyFactory
|
||||
{
|
||||
parentIds.Add(fatherId);
|
||||
members.Add(
|
||||
RollAdult(
|
||||
DressGenerator.Dress(
|
||||
catalog,
|
||||
names,
|
||||
rng,
|
||||
fatherId,
|
||||
familyId,
|
||||
female: false,
|
||||
fatherBirth,
|
||||
asOf,
|
||||
surname,
|
||||
fatherGiven,
|
||||
NameGrammar.Patronymic(fatherPatronymicSource.Form, female: false, names.PatronymicRule),
|
||||
isParent: childDrafts.Length > 0,
|
||||
nativeLanguage));
|
||||
RollAdult(
|
||||
catalog,
|
||||
names,
|
||||
rng,
|
||||
fatherId,
|
||||
familyId,
|
||||
female: false,
|
||||
fatherBirth,
|
||||
asOf,
|
||||
surname,
|
||||
fatherGiven,
|
||||
NameGrammar.Patronymic(fatherPatronymicSource.Form, female: false, names.PatronymicRule),
|
||||
isParent: childDrafts.Length > 0,
|
||||
nativeLanguage),
|
||||
schoolSeed,
|
||||
pupilYear: null,
|
||||
SchoolYears.AgeYears(fatherBirth, asOf)));
|
||||
}
|
||||
|
||||
if (hasMother)
|
||||
{
|
||||
parentIds.Add(motherId);
|
||||
members.Add(
|
||||
RollAdult(
|
||||
DressGenerator.Dress(
|
||||
catalog,
|
||||
names,
|
||||
rng,
|
||||
motherId,
|
||||
familyId,
|
||||
female: true,
|
||||
motherBirth,
|
||||
asOf,
|
||||
surname,
|
||||
motherGiven,
|
||||
NameGrammar.Patronymic(motherPatronymicSource.Form, female: true, names.PatronymicRule),
|
||||
isParent: childDrafts.Length > 0,
|
||||
nativeLanguage));
|
||||
RollAdult(
|
||||
catalog,
|
||||
names,
|
||||
rng,
|
||||
motherId,
|
||||
familyId,
|
||||
female: true,
|
||||
motherBirth,
|
||||
asOf,
|
||||
surname,
|
||||
motherGiven,
|
||||
NameGrammar.Patronymic(motherPatronymicSource.Form, female: true, names.PatronymicRule),
|
||||
isParent: childDrafts.Length > 0,
|
||||
nativeLanguage),
|
||||
schoolSeed,
|
||||
pupilYear: null,
|
||||
SchoolYears.AgeYears(motherBirth, asOf)));
|
||||
}
|
||||
|
||||
var childIds = new List<string>(childDrafts.Length);
|
||||
@@ -121,17 +131,22 @@ internal static class FamilyFactory
|
||||
var id = $"{familyId}.c{i}";
|
||||
childIds.Add(id);
|
||||
members.Add(
|
||||
RollChild(
|
||||
DressGenerator.Dress(
|
||||
catalog,
|
||||
names,
|
||||
rng,
|
||||
id,
|
||||
familyId,
|
||||
draft,
|
||||
asOf,
|
||||
surname,
|
||||
fatherGiven.Form,
|
||||
nativeLanguage));
|
||||
RollChild(
|
||||
catalog,
|
||||
names,
|
||||
rng,
|
||||
id,
|
||||
familyId,
|
||||
draft,
|
||||
asOf,
|
||||
surname,
|
||||
fatherGiven.Form,
|
||||
nativeLanguage),
|
||||
schoolSeed,
|
||||
draft.Seat.Year,
|
||||
SchoolYears.AgeYears(draft.Birth, asOf)));
|
||||
}
|
||||
|
||||
var family = new Family(familyId, parentIds, childIds, childIds.Count, fatherGiven.Form, surname.Male);
|
||||
@@ -151,6 +166,7 @@ internal static class FamilyFactory
|
||||
DateTime yearStart,
|
||||
DateTime asOf,
|
||||
int childIndex,
|
||||
int schoolSeed,
|
||||
string? nativeLanguage = null)
|
||||
{
|
||||
var fatherGiven = FatherGivenOf(family, members);
|
||||
@@ -184,23 +200,28 @@ internal static class FamilyFactory
|
||||
surnameCases,
|
||||
PatronymicTable(patronymic, female));
|
||||
|
||||
return new Person
|
||||
{
|
||||
Id = $"{family.Id}.c{childIndex}",
|
||||
FamilyId = family.Id,
|
||||
Female = female,
|
||||
BirthDate = DateTime.SpecifyKind(birth, DateTimeKind.Utc),
|
||||
Name = name,
|
||||
IsStudent = true,
|
||||
IsStaff = false,
|
||||
IsParent = false,
|
||||
ClassId = seat.ClassId,
|
||||
Numbers = numbers,
|
||||
Choices = choices,
|
||||
Skills = skills,
|
||||
Traits = traits,
|
||||
Needs = needs,
|
||||
};
|
||||
return DressGenerator.Dress(
|
||||
catalog,
|
||||
new Person
|
||||
{
|
||||
Id = $"{family.Id}.c{childIndex}",
|
||||
FamilyId = family.Id,
|
||||
Female = female,
|
||||
BirthDate = DateTime.SpecifyKind(birth, DateTimeKind.Utc),
|
||||
Name = name,
|
||||
IsStudent = true,
|
||||
IsStaff = false,
|
||||
IsParent = false,
|
||||
ClassId = seat.ClassId,
|
||||
Numbers = numbers,
|
||||
Choices = choices,
|
||||
Skills = skills,
|
||||
Traits = traits,
|
||||
Needs = needs,
|
||||
},
|
||||
schoolSeed,
|
||||
seat.Year,
|
||||
age);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -226,20 +247,25 @@ internal static class FamilyFactory
|
||||
var birth = asOf.AddYears(-(24 + rng.Next(38))).AddDays(-rng.Next(365));
|
||||
|
||||
var id = $"{familyId}.p0";
|
||||
var person = RollAdult(
|
||||
var person = DressGenerator.Dress(
|
||||
catalog,
|
||||
names,
|
||||
rng,
|
||||
id,
|
||||
familyId,
|
||||
female,
|
||||
birth,
|
||||
asOf,
|
||||
surname,
|
||||
given,
|
||||
NameGrammar.Patronymic(patronymicSource.Form, female, names.PatronymicRule),
|
||||
isParent: false,
|
||||
nativeLanguage);
|
||||
RollAdult(
|
||||
catalog,
|
||||
names,
|
||||
rng,
|
||||
id,
|
||||
familyId,
|
||||
female,
|
||||
birth,
|
||||
asOf,
|
||||
surname,
|
||||
given,
|
||||
NameGrammar.Patronymic(patronymicSource.Form, female, names.PatronymicRule),
|
||||
isParent: false,
|
||||
nativeLanguage),
|
||||
schoolSeed,
|
||||
pupilYear: null,
|
||||
SchoolYears.AgeYears(birth, asOf));
|
||||
|
||||
return (new Family(familyId, [id], [], NextChild: 0, FatherGiven: string.Empty, Surname: surname.Male), person);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace HSchool.People;
|
||||
|
||||
/// <summary>Where an instance lives. One place at a time — worn, bag, locker or home.</summary>
|
||||
public static class ItemLocations
|
||||
{
|
||||
public const string Worn = "worn";
|
||||
public const string Bag = "bag";
|
||||
public const string Locker = "locker";
|
||||
public const string Home = "home";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One thing on a person. <see cref="Subject"/> is set only on a textbook instance — the def is
|
||||
/// shared. Condition is 1 at birth; wear is a later phase.
|
||||
/// </summary>
|
||||
public sealed record InventoryItem(
|
||||
string Def,
|
||||
string? Color,
|
||||
float Condition,
|
||||
string Location,
|
||||
string? Subject = null);
|
||||
@@ -46,6 +46,9 @@ public sealed record Person
|
||||
/// <summary>Hourly rate frozen at hire. Null until the person is staff.</summary>
|
||||
public float? HourlyWageAsk { get; init; }
|
||||
|
||||
/// <summary>Worn, bag, locker and home. Empty on rosters written before clothes existed.</summary>
|
||||
public IReadOnlyList<InventoryItem> Items { get; init; } = [];
|
||||
|
||||
public int AgeOn(DateTime asOf) => SchoolYears.AgeYears(BirthDate, asOf);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ public static class Seed
|
||||
public const int SkillGrantSalt = 8;
|
||||
public const int NativeLanguageSalt = 9;
|
||||
public const int ClimatePresetSalt = 10;
|
||||
public const int ApparelSalt = 11;
|
||||
|
||||
/// <summary>A stream that belongs to the school rather than to one family.</summary>
|
||||
public static int ForSchool(int schoolSeed, int salt) => Mix(schoolSeed, familyIndex: -1, salt);
|
||||
|
||||
@@ -175,19 +175,22 @@ public static class YearlyIntake
|
||||
}
|
||||
|
||||
var rng = new Random(Seed.Mix(schoolSeed, person.Id, when.Year, Seed.SkillGrantSalt));
|
||||
people[id] = person with
|
||||
{
|
||||
Skills = PersonSampler.EnsurePupilYear(
|
||||
catalog,
|
||||
names,
|
||||
rng,
|
||||
person.AgeOn(when),
|
||||
person.Choices,
|
||||
person.Traits,
|
||||
person.Skills,
|
||||
year,
|
||||
nativeLanguage),
|
||||
};
|
||||
people[id] = DressGenerator.EnsureYearTextbooks(
|
||||
catalog,
|
||||
person with
|
||||
{
|
||||
Skills = PersonSampler.EnsurePupilYear(
|
||||
catalog,
|
||||
names,
|
||||
rng,
|
||||
person.AgeOn(when),
|
||||
person.Choices,
|
||||
person.Traits,
|
||||
person.Skills,
|
||||
year,
|
||||
nativeLanguage),
|
||||
},
|
||||
year);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +239,7 @@ public static class YearlyIntake
|
||||
|
||||
var childIndex = family.NextChildIndex;
|
||||
var rng = new Random(Seed.Mix(schoolSeed, index, Seed.IntakeSalt + yearStart.Year * 10 + childIndex));
|
||||
var child = FamilyFactory.AddChild(catalog, names, rng, family, members, seats[cursor], yearStart, asOf, childIndex, nativeLanguage);
|
||||
var child = FamilyFactory.AddChild(catalog, names, rng, family, members, seats[cursor], yearStart, asOf, childIndex, schoolSeed, nativeLanguage);
|
||||
people[child.Id] = child;
|
||||
var familyAt = families.FindIndex(candidate => candidate.Id.Equals(family.Id, StringComparison.Ordinal));
|
||||
families[familyAt] = family with
|
||||
|
||||
@@ -61,7 +61,27 @@ internal sealed record PersonCardResponse(
|
||||
IReadOnlyList<NeedStatResponse> Needs,
|
||||
string? Activity,
|
||||
string? ActivityLabel,
|
||||
PersonFamilyResponse Family);
|
||||
PersonFamilyResponse Family,
|
||||
IReadOnlyList<WornItemResponse> Worn,
|
||||
IReadOnlyList<CarriedItemResponse> Carried,
|
||||
float CarryMass,
|
||||
float CarryCapacity);
|
||||
|
||||
internal sealed record WornItemResponse(
|
||||
string DefName,
|
||||
string Label,
|
||||
string? Color,
|
||||
string? ColorLabel,
|
||||
IReadOnlyList<DefLabelResponse> Layers);
|
||||
|
||||
internal sealed record CarriedItemResponse(
|
||||
string DefName,
|
||||
string Label,
|
||||
string? Color,
|
||||
string? ColorLabel,
|
||||
string? Subject,
|
||||
string? SubjectLabel,
|
||||
float Mass);
|
||||
|
||||
internal sealed record LabeledStatResponse(string Id, string Label, string Value);
|
||||
|
||||
|
||||
@@ -81,7 +81,11 @@ internal static class PersonCardReader
|
||||
Needs(needs, catalog, locale),
|
||||
activityId,
|
||||
activityLabel,
|
||||
Family(roster, person));
|
||||
Family(roster, person),
|
||||
Worn(person, catalog, locale),
|
||||
Carried(person, catalog, locale),
|
||||
catalog is null ? 0f : CarryMass.Held(catalog, person.Items),
|
||||
Capacity(person, skills, catalog));
|
||||
}
|
||||
|
||||
private static IReadOnlyDictionary<string, float>? LiveNeeds(World world, string personId)
|
||||
@@ -260,6 +264,99 @@ internal static class PersonCardReader
|
||||
return rows;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<WornItemResponse> Worn(Person person, DefCatalog? catalog, string locale)
|
||||
{
|
||||
var rows = new List<WornItemResponse>();
|
||||
foreach (var item in person.Items)
|
||||
{
|
||||
if (!item.Location.Equals(ItemLocations.Worn, StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IReadOnlyList<string> layerIds = [];
|
||||
if (catalog is not null && catalog.Things.TryGetValue(item.Def, out var def))
|
||||
{
|
||||
layerIds = def.Layers;
|
||||
}
|
||||
|
||||
var layers = layerIds
|
||||
.Select(layer => new DefLabelResponse(layer, catalog?.Text(locale, layer) ?? layer))
|
||||
.ToArray();
|
||||
rows.Add(new WornItemResponse(
|
||||
item.Def,
|
||||
ThingLabel(catalog, locale, item.Def),
|
||||
item.Color,
|
||||
ColorLabel(catalog, locale, item.Color),
|
||||
layers));
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<CarriedItemResponse> Carried(Person person, DefCatalog? catalog, string locale)
|
||||
{
|
||||
var rows = new List<CarriedItemResponse>();
|
||||
foreach (var item in person.Items)
|
||||
{
|
||||
if (!item.Location.Equals(ItemLocations.Bag, StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var mass = catalog is not null && catalog.Things.TryGetValue(item.Def, out var def) ? def.Mass : 0f;
|
||||
string? subjectLabel = null;
|
||||
if (item.Subject is not null)
|
||||
{
|
||||
subjectLabel = catalog is not null && catalog.Subjects.TryGetValue(item.Subject, out var subject)
|
||||
? catalog.Label(locale, subject)
|
||||
: item.Subject;
|
||||
}
|
||||
|
||||
rows.Add(new CarriedItemResponse(
|
||||
item.Def,
|
||||
ThingLabel(catalog, locale, item.Def),
|
||||
item.Color,
|
||||
ColorLabel(catalog, locale, item.Color),
|
||||
item.Subject,
|
||||
subjectLabel,
|
||||
mass));
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
private static string ThingLabel(DefCatalog? catalog, string locale, string defName)
|
||||
{
|
||||
if (catalog is not null && catalog.Things.TryGetValue(defName, out var def))
|
||||
{
|
||||
return catalog.Label(locale, def);
|
||||
}
|
||||
|
||||
return defName;
|
||||
}
|
||||
|
||||
private static string? ColorLabel(DefCatalog? catalog, string locale, string? color) =>
|
||||
color is null ? null : catalog?.Text(locale, color) ?? color;
|
||||
|
||||
private static float Capacity(
|
||||
Person person,
|
||||
IReadOnlyDictionary<string, float>? live,
|
||||
DefCatalog? catalog)
|
||||
{
|
||||
if (catalog is null)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
if (live is not null)
|
||||
{
|
||||
return CarryMass.Capacity(catalog, live);
|
||||
}
|
||||
|
||||
return CarryMass.Capacity(catalog, person.Skills);
|
||||
}
|
||||
|
||||
private static PersonFamilyResponse Family(Roster roster, Person person)
|
||||
{
|
||||
var family = roster.Families.FirstOrDefault(candidate => candidate.Id.Equals(person.FamilyId, StringComparison.Ordinal));
|
||||
|
||||
@@ -924,6 +924,13 @@ internal sealed class SchoolWorker
|
||||
}
|
||||
}
|
||||
|
||||
if (DressGenerator.NeedsDressing(roster, applicants))
|
||||
{
|
||||
roster = DressGenerator.EnsureRoster(catalog, roster, seed, school.Clock.Time);
|
||||
applicants = DressGenerator.EnsurePool(catalog, applicants, roster, seed, school.Clock.Time);
|
||||
generated = true;
|
||||
}
|
||||
|
||||
if (!RosterFit.Matches(roster, demand))
|
||||
{
|
||||
throw new SchoolContentUnavailableException(
|
||||
|
||||
@@ -21,4 +21,11 @@
|
||||
// beats walking on to the next room, below the lesson so it never pulls
|
||||
// anybody out of class. Raise it past dutyLessonWeight and they will.
|
||||
"lunchWeight": 6,
|
||||
// Bag limit: base kg + per point of Strength, Endurance and Hauling.
|
||||
"carryMassBase": 5,
|
||||
"carryMassPerStrength": 0.08,
|
||||
"carryMassPerEndurance": 0.04,
|
||||
"carryMassPerHauling": 0.08,
|
||||
// Sweater, coat, hat, accessory — each rolled separately at generation.
|
||||
"optionalApparelChance": 0.4,
|
||||
}
|
||||
|
||||
@@ -30,4 +30,10 @@
|
||||
{ "attribute": "Build", "value": "Athletic", "min": 40 },
|
||||
],
|
||||
},
|
||||
{
|
||||
"defName": "Hauling",
|
||||
"always": true,
|
||||
"range": { "min": 0, "max": 100 },
|
||||
"distribution": { "mean": 50, "stdDev": 12 },
|
||||
},
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[
|
||||
{ "defName": "SchoolBag", "portable": true, "mass": 0.8 },
|
||||
{ "defName": "SchoolBag", "portable": true, "mass": 0.8, "age": { "min": 6, "max": 18 }, "carryChance": 1 },
|
||||
{ "defName": "Textbook", "portable": true, "mass": 0.4 },
|
||||
{ "defName": "Phone", "portable": true, "mass": 0.15, "colors": ["Black", "White", "Gray"] },
|
||||
{ "defName": "Bottle", "portable": true, "mass": 0.3, "colors": ["Blue", "Green", "White"] },
|
||||
{ "defName": "Phone", "portable": true, "mass": 0.15, "colors": ["Black", "White", "Gray"], "age": { "min": 11 }, "carryChance": 0.45 },
|
||||
{ "defName": "Bottle", "portable": true, "mass": 0.3, "colors": ["Blue", "Green", "White"], "age": { "min": 6 }, "carryChance": 0.7 },
|
||||
]
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
"Agility": "Agility",
|
||||
"Strength": "Strength",
|
||||
"Endurance": "Endurance",
|
||||
"Hauling": "Hauling",
|
||||
"Diligent": "Diligent",
|
||||
"AbsentMinded": "Absent-minded",
|
||||
"Bully": "Bully",
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
"Agility": "Ловкость",
|
||||
"Strength": "Сила",
|
||||
"Endurance": "Выносливость",
|
||||
"Hauling": "Переноска",
|
||||
"Diligent": "Усидчивый",
|
||||
"AbsentMinded": "Рассеянный",
|
||||
"Bully": "Задира",
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace HSchool.AppHost.Tests;
|
||||
|
||||
[Collection(AppHostCollection.Name)]
|
||||
public class InventoryApiTests(AppHostFixture fixture)
|
||||
{
|
||||
private static readonly DateTime Start = new(2012, 4, 3, 6, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
[Fact]
|
||||
public async Task Card_IncludesWornAndCarried_ListDoesNot()
|
||||
{
|
||||
using var client = fixture.App.CreateHttpClient("server");
|
||||
await SchoolApiTests.ResetAsync(client);
|
||||
var school = await SchoolApiTests.CreateAsync(client, "Гардероб карточка", Start, seed: 31);
|
||||
|
||||
var page = await client.GetFromJsonAsync<PeoplePage>(
|
||||
$"/api/schools/{school.Id}/people?role=student&year=5&pageSize=20",
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(page);
|
||||
var girl = page.People.First(person => person.Female);
|
||||
|
||||
using var listResponse = await client.GetAsync(
|
||||
$"/api/schools/{school.Id}/people?pageSize=1",
|
||||
TestContext.Current.CancellationToken);
|
||||
var listJson = await listResponse.Content.ReadAsStringAsync(TestContext.Current.CancellationToken);
|
||||
Assert.DoesNotContain("carryMass", listJson, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("\"worn\"", listJson, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("\"carried\"", listJson, StringComparison.Ordinal);
|
||||
|
||||
var card = await client.GetFromJsonAsync<Card>(
|
||||
$"/api/schools/{school.Id}/people/{Uri.EscapeDataString(girl.Id)}?lang=ru",
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(card);
|
||||
Assert.NotEmpty(card.Worn);
|
||||
Assert.Contains(card.Worn, item => item.Layers.Count > 0 && item.ColorLabel is { Length: > 0 });
|
||||
Assert.True(card.CarryCapacity > 0);
|
||||
Assert.True(card.CarryMass <= card.CarryCapacity);
|
||||
Assert.Contains(card.Carried, item => item.Mass > 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SameSeed_YieldsTheSameShirt()
|
||||
{
|
||||
using var client = fixture.App.CreateHttpClient("server");
|
||||
await SchoolApiTests.ResetAsync(client);
|
||||
var first = await SchoolApiTests.CreateAsync(client, "Синяя рубашка 1", Start, seed: 31);
|
||||
var shirt = await FirstGirlTopAsync(client, first.Id);
|
||||
|
||||
await SchoolApiTests.ResetAsync(client);
|
||||
var second = await SchoolApiTests.CreateAsync(client, "Синяя рубашка 2", Start, seed: 31);
|
||||
var again = await FirstGirlTopAsync(client, second.Id);
|
||||
|
||||
Assert.Equal(shirt.DefName, again.DefName);
|
||||
Assert.Equal(shirt.Color, again.Color);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PeopleJsonWithoutInventory_IsDressedOnReloadAndRewritten()
|
||||
{
|
||||
using var client = fixture.App.CreateHttpClient("server");
|
||||
await SchoolApiTests.ResetAsync(client);
|
||||
var school = await SchoolApiTests.CreateAsync(client, "Старый сейв без одежды", Start, seed: 31);
|
||||
var before = await FirstGirlTopAsync(client, school.Id);
|
||||
|
||||
var directory = await SavesDirectoryAsync(client);
|
||||
var path = Path.Combine(directory, $"{school.Id}.people.json");
|
||||
StripItems(path);
|
||||
Assert.DoesNotContain("\"items\"", File.ReadAllText(path), StringComparison.Ordinal);
|
||||
|
||||
using var reload = await client.PostAsync("/api/dev/reload-schools", content: null, TestContext.Current.CancellationToken);
|
||||
reload.EnsureSuccessStatusCode();
|
||||
|
||||
var after = await FirstGirlTopAsync(client, school.Id);
|
||||
Assert.Equal(before.DefName, after.DefName);
|
||||
Assert.Equal(before.Color, after.Color);
|
||||
Assert.Contains("\"items\"", File.ReadAllText(path), StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static async Task<WornItem> FirstGirlTopAsync(HttpClient client, int schoolId)
|
||||
{
|
||||
var page = await client.GetFromJsonAsync<PeoplePage>(
|
||||
$"/api/schools/{schoolId}/people?role=student&sex=female&pageSize=20",
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(page);
|
||||
Assert.NotEmpty(page.People);
|
||||
var girl = page.People[0];
|
||||
var card = await client.GetFromJsonAsync<Card>(
|
||||
$"/api/schools/{schoolId}/people/{Uri.EscapeDataString(girl.Id)}?lang=ru",
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(card);
|
||||
var top = card.Worn.FirstOrDefault(item =>
|
||||
item.Layers.Any(layer => layer.DefName.Equals("Top", StringComparison.Ordinal)));
|
||||
Assert.NotNull(top);
|
||||
return top;
|
||||
}
|
||||
|
||||
private static async Task<string> SavesDirectoryAsync(HttpClient client)
|
||||
{
|
||||
var payload = await client.GetFromJsonAsync<SavesDirectoryResponse>(
|
||||
"/api/dev/saves-directory",
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(payload);
|
||||
return payload.Path;
|
||||
}
|
||||
|
||||
private static void StripItems(string path)
|
||||
{
|
||||
var root = JsonNode.Parse(File.ReadAllText(path))
|
||||
?? throw new InvalidOperationException("People file parsed to nothing.");
|
||||
foreach (var person in root["people"]?.AsArray() ?? [])
|
||||
{
|
||||
person?.AsObject().Remove("items");
|
||||
}
|
||||
|
||||
var applicants = root["applicants"]?["applicants"]?.AsArray();
|
||||
if (applicants is not null)
|
||||
{
|
||||
foreach (var applicant in applicants)
|
||||
{
|
||||
applicant?["person"]?.AsObject()?.Remove("items");
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(
|
||||
path,
|
||||
root.ToJsonString(new JsonSerializerOptions { WriteIndented = true }));
|
||||
}
|
||||
|
||||
private sealed record SavesDirectoryResponse(string Path);
|
||||
|
||||
private sealed record PeoplePage(IReadOnlyList<PersonRow> People);
|
||||
|
||||
private sealed record PersonRow(string Id, string FullName, bool Female);
|
||||
|
||||
private sealed record Card(
|
||||
IReadOnlyList<WornItem> Worn,
|
||||
IReadOnlyList<CarriedItem> Carried,
|
||||
float CarryMass,
|
||||
float CarryCapacity);
|
||||
|
||||
private sealed record WornItem(
|
||||
string DefName,
|
||||
string Label,
|
||||
string? Color,
|
||||
string? ColorLabel,
|
||||
IReadOnlyList<Layer> Layers);
|
||||
|
||||
private sealed record Layer(string DefName, string Label);
|
||||
|
||||
private sealed record CarriedItem(string DefName, string Label, float Mass);
|
||||
}
|
||||
@@ -7,6 +7,10 @@ than a new roll.
|
||||
These files live forever: a new save field must load `current/` and must not reshuffle
|
||||
`legacy-no-native/`. A real format change adds a new folder; it does not rewrite the old one.
|
||||
|
||||
Phase 31 rewrote `current/1.people.json` because people are born dressed (`items` on each
|
||||
person, plus `Hauling`). `legacy-no-native/` is left as it was: no inventory, so load still
|
||||
has to dress them and must not reshuffle names.
|
||||
|
||||
Regenerate after an intentional roster change (same commit):
|
||||
|
||||
```
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,7 @@ public class ApparelDefTests
|
||||
Assert.Empty(chair.Colors);
|
||||
Assert.Null(chair.SkirtLength);
|
||||
Assert.False(chair.Pe);
|
||||
Assert.Equal(0, chair.CarryChance);
|
||||
Assert.Equal(0, chair.PupilSlots);
|
||||
}
|
||||
|
||||
@@ -166,4 +167,20 @@ public class ApparelDefTests
|
||||
|
||||
Assert.Contains("TShirt", ex.Message, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CarryChanceAboveOne_FailsTheCatalog()
|
||||
{
|
||||
var ex = Assert.Throws<ContentLoadException>(() => _loader.Load(
|
||||
[CatalogLoader.CorePackId],
|
||||
[
|
||||
PackDocuments.Def(
|
||||
CatalogLoader.CorePackId,
|
||||
"things",
|
||||
"phone",
|
||||
"""{ "defName": "Phone", "portable": true, "carryChance": 1.2 }"""),
|
||||
]));
|
||||
|
||||
Assert.Contains("carryChance", ex.Message, StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,4 +47,20 @@ public class BehaviorDefTests
|
||||
warning => warning.Contains("lunchWeight", StringComparison.Ordinal)
|
||||
&& warning.Contains("dutyLessonWeight", StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NegativeCarryMass_FailsTheCatalog()
|
||||
{
|
||||
var error = Assert.Throws<ContentLoadException>(() => _loader.Load(
|
||||
[CatalogLoader.CorePackId],
|
||||
[
|
||||
PackDocuments.Def(
|
||||
CatalogLoader.CorePackId,
|
||||
"behavior",
|
||||
"rules",
|
||||
"""{ "defName": "Behavior", "carryMassBase": -1 }"""),
|
||||
]));
|
||||
|
||||
Assert.Contains("carry mass", error.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ public class PeopleDefTests
|
||||
Assert.Equal(0.2f, catalog.Needs["Hunger"].DecayPerHour);
|
||||
Assert.True(catalog.Skills["Communication"].Always);
|
||||
Assert.True(catalog.Skills["Agility"].Always);
|
||||
Assert.True(catalog.Skills["Hauling"].Always);
|
||||
Assert.True(catalog.Skills["Pedagogy"].Work);
|
||||
Assert.Equal(0.4f, catalog.Skills["English"].AdultChance);
|
||||
Assert.Equal(
|
||||
|
||||
@@ -45,6 +45,9 @@ public class VanillaCoreTests
|
||||
Assert.True(catalog.Things["PeShirt"].Pe);
|
||||
Assert.True(catalog.Things["Textbook"].Portable);
|
||||
Assert.Empty(catalog.Things["Textbook"].Layers);
|
||||
Assert.Equal(0, catalog.Things["Textbook"].CarryChance);
|
||||
Assert.Equal(1, catalog.Things["SchoolBag"].CarryChance);
|
||||
Assert.Equal(11, catalog.Things["Phone"].Age?.Min);
|
||||
Assert.Equal(1, catalog.Things.Values.Count(thing => thing.DefName == "Textbook"));
|
||||
Assert.Equal([ColorTags.Bright], catalog.Colors["Red"].Tags);
|
||||
Assert.Equal([ColorTags.Neutral, ColorTags.School], catalog.Colors["White"].Tags);
|
||||
@@ -100,6 +103,8 @@ public class VanillaCoreTests
|
||||
Assert.Equal(5f, catalog.BehaviorRules.DutyTravelWeight);
|
||||
Assert.Equal(20f, catalog.BehaviorRules.NeedWeightAtZero);
|
||||
Assert.Equal(6f, catalog.BehaviorRules.LunchWeight);
|
||||
Assert.Equal(5f, catalog.BehaviorRules.CarryMassBase);
|
||||
Assert.Equal(0.4f, catalog.BehaviorRules.OptionalApparelChance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
namespace HSchool.People.Tests;
|
||||
|
||||
public class DressGeneratorTests
|
||||
{
|
||||
[Fact]
|
||||
public void SameSeedCountryMapAndLanguage_YieldTheSameItemsColorsAndPlaces()
|
||||
{
|
||||
var map = Fixtures.Classrooms(11);
|
||||
var a = Fixtures.Generate(map);
|
||||
var b = Fixtures.Generate(map);
|
||||
|
||||
Assert.Equal(ItemsSnapshot(a), ItemsSnapshot(b));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WornLayers_DoNotOverlap_AndADressFillsBottomAndTop()
|
||||
{
|
||||
var catalog = Fixtures.Catalog();
|
||||
var roster = Fixtures.Generate(Fixtures.Classrooms(11));
|
||||
|
||||
foreach (var person in roster.People)
|
||||
{
|
||||
var occupied = new HashSet<string>(StringComparer.Ordinal);
|
||||
foreach (var item in person.Items.Where(row => row.Location == ItemLocations.Worn))
|
||||
{
|
||||
Assert.True(catalog.Things.TryGetValue(item.Def, out var def));
|
||||
foreach (var layer in def.Layers)
|
||||
{
|
||||
Assert.True(occupied.Add(layer), $"{person.Id} wears two things on {layer}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert.Contains(
|
||||
roster.People,
|
||||
person => person.Items.Any(item =>
|
||||
item.Location == ItemLocations.Worn && item.Def.Equals("Dress", StringComparison.Ordinal)));
|
||||
var dressed = roster.People.First(person =>
|
||||
person.Items.Any(item => item.Location == ItemLocations.Worn && item.Def == "Dress"));
|
||||
var worn = dressed.Items.Where(item => item.Location == ItemLocations.Worn).Select(item => item.Def).ToHashSet();
|
||||
Assert.DoesNotContain("TShirt", worn);
|
||||
Assert.DoesNotContain("Shirt", worn);
|
||||
Assert.DoesNotContain("Skirt", worn);
|
||||
Assert.DoesNotContain("Pants", worn);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Men_DoNotWearSkirts_AndWornColors_AreNotBright()
|
||||
{
|
||||
var catalog = Fixtures.Catalog();
|
||||
var roster = Fixtures.Generate(Fixtures.Classrooms(11));
|
||||
|
||||
foreach (var person in roster.People)
|
||||
{
|
||||
foreach (var item in person.Items.Where(row => row.Location == ItemLocations.Worn))
|
||||
{
|
||||
Assert.True(catalog.Things.TryGetValue(item.Def, out var def));
|
||||
if (!person.Female)
|
||||
{
|
||||
Assert.False(
|
||||
def.Sex is not null && def.Sex.Equals("female", StringComparison.OrdinalIgnoreCase),
|
||||
$"{person.Id} wears {item.Def}.");
|
||||
}
|
||||
|
||||
if (item.Color is { } color
|
||||
&& catalog.Colors.TryGetValue(color, out var colorDef))
|
||||
{
|
||||
Assert.DoesNotContain(ColorTags.Bright, colorDef.Tags, StringComparer.Ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PupilInAMathematicsYear_HasAMathematicsTextbook()
|
||||
{
|
||||
var roster = Fixtures.Generate(Fixtures.Classrooms(11));
|
||||
var years = roster.Classes.ToDictionary(row => row.Id, row => row.Year, StringComparer.Ordinal);
|
||||
var pupil = roster.People.First(person =>
|
||||
person.IsStudent
|
||||
&& person.ClassId is { } classId
|
||||
&& years[classId] >= 5);
|
||||
|
||||
Assert.Contains(
|
||||
pupil.Items,
|
||||
item => item.Def.Equals("Textbook", StringComparison.Ordinal)
|
||||
&& item.Subject is not null
|
||||
&& item.Subject.Equals("Mathematics", StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParentsAndApplicants_AreDressed()
|
||||
{
|
||||
var catalog = Fixtures.Catalog();
|
||||
var roster = Fixtures.Generate(Fixtures.VanillaMap());
|
||||
var pool = ApplicantPool.Create(catalog, roster, Fixtures.SchoolSeed, "Russia", Fixtures.AsOf);
|
||||
|
||||
Assert.Contains(roster.People, person => person.IsParent);
|
||||
Assert.All(
|
||||
roster.People.Where(person => person.IsParent),
|
||||
parent => Assert.Contains(parent.Items, item => item.Location == ItemLocations.Worn));
|
||||
Assert.NotEmpty(pool.Applicants);
|
||||
Assert.All(
|
||||
pool.Applicants,
|
||||
applicant => Assert.Contains(applicant.Person.Items, item => item.Location == ItemLocations.Worn));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BagMass_DoesNotExceedCapacity()
|
||||
{
|
||||
var catalog = Fixtures.Catalog();
|
||||
var roster = Fixtures.Generate(Fixtures.Classrooms(11));
|
||||
var pool = ApplicantPool.Create(catalog, roster, Fixtures.SchoolSeed, "Russia", Fixtures.AsOf);
|
||||
|
||||
foreach (var person in roster.People.Concat(pool.Applicants.Select(row => row.Person)))
|
||||
{
|
||||
var held = CarryMass.Held(catalog, person.Items);
|
||||
var cap = CarryMass.Capacity(catalog, person.Skills);
|
||||
Assert.True(held <= cap, $"{person.Id} carries {held} over {cap}.");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PeopleJsonWithoutInventory_IsDressedOnEnsure()
|
||||
{
|
||||
var catalog = Fixtures.Catalog();
|
||||
var roster = Fixtures.Generate(Fixtures.Classrooms(4));
|
||||
var stripped = new Roster(
|
||||
roster.People.Select(person => person with { Items = [] }).ToArray(),
|
||||
roster.Families,
|
||||
roster.Classes);
|
||||
|
||||
Assert.True(DressGenerator.NeedsDressing(stripped, ApplicantPool.Empty));
|
||||
var dressed = DressGenerator.EnsureRoster(catalog, stripped, Fixtures.SchoolSeed, Fixtures.AsOf);
|
||||
Assert.False(DressGenerator.NeedsDressing(dressed, ApplicantPool.Empty));
|
||||
Assert.Equal(ItemsSnapshot(roster), ItemsSnapshot(dressed));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EveryoneHasHauling()
|
||||
{
|
||||
var roster = Fixtures.Generate(Fixtures.Classrooms(4));
|
||||
Assert.All(roster.People, person => Assert.True(person.Skills.ContainsKey("Hauling")));
|
||||
}
|
||||
|
||||
private static string ItemsSnapshot(Roster roster) =>
|
||||
string.Join(
|
||||
'\n',
|
||||
roster.People.OrderBy(person => person.Id, StringComparer.Ordinal).Select(person =>
|
||||
$"{person.Id}|" + string.Join(
|
||||
',',
|
||||
person.Items.Select(item =>
|
||||
$"{item.Def}:{item.Color ?? "-"}:{item.Location}:{item.Subject ?? "-"}:{item.Condition}"))));
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public class GoldenSaveDump
|
||||
Write(Path.Combine(root, "current", "1.json"), current);
|
||||
Write(Path.Combine(root, "current", "1.people.json"), people);
|
||||
Write(Path.Combine(root, "legacy-no-native", "1.json"), legacy);
|
||||
Write(Path.Combine(root, "legacy-no-native", "1.people.json"), people);
|
||||
// people.json in legacy-no-native stays the historic undressed file: load must dress it.
|
||||
}
|
||||
|
||||
internal static MapLayout TwoClassrooms() =>
|
||||
|
||||
@@ -198,7 +198,8 @@ public class ReviewFixTests
|
||||
seat,
|
||||
new DateTime(2011, 9, 1, 0, 0, 0, DateTimeKind.Utc),
|
||||
Fixtures.AsOf,
|
||||
motherOnly.NextChildIndex);
|
||||
motherOnly.NextChildIndex,
|
||||
Fixtures.SchoolSeed);
|
||||
|
||||
// Boys need the male form of a surname no living member of this household carries.
|
||||
var entry = names.Surnames.Single(candidate => candidate.Male == motherOnly.Surname);
|
||||
|
||||
@@ -54,8 +54,12 @@ internal static class RosterFingerprint
|
||||
var skills = string.Join(
|
||||
',',
|
||||
person.Skills.OrderBy(pair => pair.Key, StringComparer.Ordinal).Select(pair => $"{pair.Key}={pair.Value}"));
|
||||
var items = string.Join(
|
||||
',',
|
||||
person.Items.Select(item =>
|
||||
$"{item.Def}:{item.Color ?? "-"}:{item.Location}{(item.Subject is { } subject ? $":{subject}" : "")}"));
|
||||
return
|
||||
$"person {person.Id} {person.Name.Full} female={person.Female} roles={roles} class={person.ClassId ?? "-"} born={person.BirthDate:yyyy-MM-dd} traits={traits} skills={skills}";
|
||||
$"person {person.Id} {person.Name.Full} female={person.Female} roles={roles} class={person.ClassId ?? "-"} born={person.BirthDate:yyyy-MM-dd} traits={traits} skills={skills} items={items}";
|
||||
}
|
||||
|
||||
private static IEnumerable<string> Roles(Person person)
|
||||
|
||||
@@ -15,6 +15,7 @@ public class SkillGrantTests
|
||||
Assert.True(person.Skills.ContainsKey("Communication"));
|
||||
Assert.True(person.Skills.ContainsKey("RussianLanguage"));
|
||||
Assert.True(person.Skills.ContainsKey("Agility"));
|
||||
Assert.True(person.Skills.ContainsKey("Hauling"));
|
||||
Assert.True(person.Skills.ContainsKey("Mathematics"));
|
||||
Assert.False(person.Skills.ContainsKey("Chemistry"));
|
||||
Assert.False(person.Skills.ContainsKey("Physics"));
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
# Golden roster
|
||||
|
||||
`roster.txt` is the fingerprint of `RosterGenerator` for a fixed seed, four classrooms, Slavic
|
||||
names and Russian as the native language.
|
||||
`roster.txt` is the fingerprint of `RosterGenerator` for a fixed seed, four classrooms, country
|
||||
Russia and Russian as the native language.
|
||||
|
||||
Phase 31 changed this file on purpose: everyone now has `Hauling` (an `always` skill, extra
|
||||
rolls on the shared family stream, so later members' traits/skills shift) and an `items=`
|
||||
column (wardrobe from a separate apparel stream). Names and birth dates of the first child
|
||||
in a family stay; clothes are new.
|
||||
|
||||
Update it **in the same commit that changes generation**, and say in the commit message what
|
||||
changed (a new skill, a related-language roll, a different birth window). A red golden test is
|
||||
|
||||
@@ -3,133 +3,133 @@ class class-classroom-00 year=1 letter=А room=classroom-00 capacity=16 pupils=f
|
||||
class class-classroom-01 year=2 letter=А room=classroom-01 capacity=16 pupils=f0.c1,f12.c0,f12.c1,f12.c2,f13.c1,f13.c2,f14.c2,f20.c0,f23.c1,f26.c0,f27.c0,f29.c0,f31.c0,f4.c0,f7.c0,f9.c0
|
||||
class class-classroom-02 year=3 letter=А room=classroom-02 capacity=16 pupils=f10.c0,f14.c0,f16.c0,f17.c1,f2.c0,f21.c0,f22.c1,f23.c0,f25.c0,f28.c0,f3.c0,f3.c1,f32.c0,f32.c2,f5.c0,f6.c1
|
||||
class class-classroom-03 year=4 letter=А room=classroom-03 capacity=16 pupils=f0.c0,f1.c0,f11.c0,f14.c1,f15.c0,f17.c0,f17.c2,f20.c1,f22.c0,f24.c0,f28.c1,f30.c0,f30.c1,f8.c1,f9.c1,f9.c2
|
||||
person f0.c0 Андреев Сергей Валериевич female=False roles=student class=class-classroom-03 born=2000-10-23 traits=Quiet skills=Agility=23,BelarusianLanguage=6,Biology=57,Communication=29,Endurance=51,Literature=20,Mathematics=14,PhysicalEducation=77,RussianLanguage=32,Strength=43,UkrainianLanguage=24
|
||||
person f0.c1 Андреев Александр Валериевич female=False roles=student class=class-classroom-01 born=2002-11-09 traits=Curious,Quiet skills=Agility=47,BelarusianLanguage=14,Biology=56,Communication=42,Endurance=51,Literature=40,Mathematics=35,PhysicalEducation=41,RussianLanguage=45,Strength=45,UkrainianLanguage=40
|
||||
person f0.p0 Андреев Валерий Николаевич female=False roles=parent class=- born=1971-06-03 traits=Diligent,Quiet skills=Agility=43,Communication=58,Endurance=61,English=62,RussianLanguage=46,Strength=63,UkrainianLanguage=37
|
||||
person f0.p1 Андреева Марина Артемовна female=True roles=parent class=- born=1971-09-30 traits= skills=Agility=30,Communication=35,Endurance=46,English=58,Informatics=59,Librarianship=63,Medicine=73,PhysicalEducation=45,RussianLanguage=68,Strength=52
|
||||
person f1.c0 Александрова Людмила Борисовна female=True roles=student class=class-classroom-03 born=2001-01-26 traits= skills=Agility=72,Biology=49,Communication=37,Endurance=39,Literature=69,Mathematics=66,PhysicalEducation=65,RussianLanguage=41,Strength=45,UkrainianLanguage=27
|
||||
person f1.c1 Александров Евгений Борисович female=False roles=student class=class-classroom-00 born=2004-04-01 traits=Diligent,Kind skills=Agility=59,BelarusianLanguage=40,Biology=62,Communication=16,Endurance=56,Literature=83,Mathematics=36,PhysicalEducation=45,RussianLanguage=46,Strength=45
|
||||
person f1.c2 Александров Юрий Борисович female=False roles=student class=class-classroom-00 born=2003-10-28 traits= skills=Agility=44,BelarusianLanguage=27,Biology=73,Communication=24,Endurance=67,Literature=70,Mathematics=24,PhysicalEducation=54,RussianLanguage=15,Strength=45
|
||||
person f1.p0 Александров Борис Ильич female=False roles=parent class=- born=1968-10-25 traits= skills=Agility=45,Communication=74,Endurance=34,English=63,Librarianship=51,Mathematics=66,RussianLanguage=59,Strength=68,UkrainianLanguage=24
|
||||
person f1.p1 Александрова Елизавета Романовна female=True roles=parent class=- born=1972-01-25 traits=Diligent skills=Agility=61,BelarusianLanguage=29,Communication=35,Endurance=39,English=52,Mathematics=72,RussianLanguage=61,Strength=45,UkrainianLanguage=21
|
||||
person f10.c0 Захаров Пётр Виталиевич female=False roles=student class=class-classroom-02 born=2001-11-08 traits= skills=Agility=64,BelarusianLanguage=27,Biology=49,Communication=37,Endurance=47,Literature=51,Mathematics=30,PhysicalEducation=42,RussianLanguage=35,Strength=37,UkrainianLanguage=24
|
||||
person f10.p0 Захаров Виталий Борисович female=False roles=parent class=- born=1976-09-07 traits=HotTempered,Leader skills=Agility=44,Chemistry=93,Communication=66,Endurance=82,English=31,RussianLanguage=60,Strength=40
|
||||
person f10.p1 Захарова Любовь Валериевна female=True roles=parent class=- born=1978-11-03 traits=AbsentMinded,Neat skills=Administration=66,Agility=36,BelarusianLanguage=38,Communication=64,Endurance=79,Informatics=51,Medicine=64,RussianLanguage=63,Strength=80,UkrainianLanguage=40
|
||||
person f11.c0 Андреева Дарья Ивановна female=True roles=student class=class-classroom-03 born=2001-05-20 traits= skills=Agility=60,BelarusianLanguage=22,Biology=60,Communication=36,Endurance=54,Literature=42,Mathematics=54,PhysicalEducation=48,RussianLanguage=35,Strength=45,UkrainianLanguage=22
|
||||
person f11.p0 Андреев Иван Алексеевич female=False roles=parent class=- born=1976-06-01 traits= skills=Agility=38,BelarusianLanguage=27,Communication=52,Endurance=82,RussianLanguage=72,Strength=30
|
||||
person f11.p1 Андреева София Александровна female=True roles=parent class=- born=1978-04-24 traits= skills=Agility=39,BelarusianLanguage=18,Communication=41,Endurance=50,English=55,Geography=59,Informatics=47,RussianLanguage=62,Strength=45
|
||||
person f12.c0 Кузьмин Олег Владиславович female=False roles=student class=class-classroom-01 born=2003-03-20 traits=AbsentMinded,Bully skills=Agility=51,BelarusianLanguage=30,Biology=64,Communication=54,Endurance=40,Literature=54,Mathematics=32,PhysicalEducation=54,RussianLanguage=40,Strength=70,UkrainianLanguage=18
|
||||
person f12.c1 Кузьмин Егор Владиславович female=False roles=student class=class-classroom-01 born=2003-05-31 traits=HotTempered,Kind skills=Agility=19,BelarusianLanguage=10,Biology=45,Communication=43,Endurance=42,Literature=60,Mathematics=24,PhysicalEducation=50,RussianLanguage=38,Strength=45
|
||||
person f12.c2 Кузьмина Дарья Владиславовна female=True roles=student class=class-classroom-01 born=2002-10-29 traits=Curious skills=Agility=43,Biology=42,Communication=37,Endurance=34,Literature=44,Mathematics=25,PhysicalEducation=57,RussianLanguage=38,Strength=45,UkrainianLanguage=18
|
||||
person f12.p0 Кузьмин Владислав Александрович female=False roles=parent class=- born=1975-01-17 traits= skills=Agility=25,BelarusianLanguage=27,Communication=68,Endurance=35,Literature=53,Mathematics=41,RussianLanguage=43,Strength=65,UkrainianLanguage=14
|
||||
person f12.p1 Кузьмина Ольга Кирилловна female=True roles=parent class=- born=1979-10-15 traits=Kind,Lazy skills=Administration=58,Agility=54,BelarusianLanguage=15,Communication=65,Endurance=40,English=50,Physics=34,RussianLanguage=52,Strength=63,UkrainianLanguage=16
|
||||
person f13.c0 Яковлев Константин Владиславович female=False roles=student class=class-classroom-00 born=2004-06-16 traits=HotTempered skills=Agility=67,Biology=45,Communication=21,Endurance=49,Literature=60,Mathematics=14,PhysicalEducation=63,RussianLanguage=30,Strength=39,UkrainianLanguage=18
|
||||
person f13.c1 Яковлев Юрий Владиславович female=False roles=student class=class-classroom-01 born=2003-07-23 traits=Kind skills=Agility=77,Biology=69,Communication=26,Endurance=55,Literature=54,Mathematics=27,PhysicalEducation=41,RussianLanguage=48,Strength=45
|
||||
person f13.c2 Яковлева Алина Владиславовна female=True roles=student class=class-classroom-01 born=2003-02-01 traits=Lazy,Neat skills=Agility=42,BelarusianLanguage=22,Biology=66,Communication=43,Endurance=59,Literature=42,Mathematics=38,PhysicalEducation=72,RussianLanguage=40,Strength=54
|
||||
person f13.p0 Яковлев Владислав Андреевич female=False roles=parent class=- born=1974-09-23 traits=AbsentMinded,Kind skills=Administration=61,Agility=25,Communication=42,Endurance=35,Geography=31,German=44,History=68,RussianLanguage=44,Strength=52
|
||||
person f14.c0 Александров Степан Денисович female=False roles=student class=class-classroom-02 born=2002-01-03 traits=Bully,Lazy skills=Agility=26,BelarusianLanguage=20,Biology=42,Communication=45,Endurance=58,Literature=54,Mathematics=5,PhysicalEducation=51,RussianLanguage=29,Strength=49,UkrainianLanguage=17
|
||||
person f14.c1 Александрова Вероника Денисовна female=True roles=student class=class-classroom-03 born=2001-08-11 traits=AbsentMinded skills=Agility=52,BelarusianLanguage=22,Biology=59,Communication=38,Endurance=40,Literature=52,Mathematics=9,PhysicalEducation=62,RussianLanguage=53,Strength=43
|
||||
person f14.c2 Александров Константин Денисович female=False roles=student class=class-classroom-01 born=2003-08-21 traits= skills=Agility=45,BelarusianLanguage=22,Biology=35,Communication=16,Endurance=36,Literature=62,Mathematics=47,PhysicalEducation=65,RussianLanguage=26,Strength=51
|
||||
person f14.p1 Александрова Виктория Викторовна female=True roles=parent class=- born=1973-07-23 traits= skills=Agility=45,BelarusianLanguage=23,Communication=72,Cooking=33,Endurance=64,English=36,PhysicalEducation=61,RussianLanguage=55,Strength=42
|
||||
person f15.c0 Воробьёв Игорь Сергеевич female=False roles=student class=class-classroom-03 born=2000-09-20 traits=Diligent skills=Agility=40,BelarusianLanguage=12,Biology=42,Communication=51,Endurance=51,Literature=37,Mathematics=16,PhysicalEducation=31,RussianLanguage=11,Strength=51,UkrainianLanguage=11
|
||||
person f15.p0 Воробьёв Сергей Никитич female=False roles=parent class=- born=1974-10-22 traits=Neat,Quiet skills=Agility=45,BelarusianLanguage=28,Communication=54,Endurance=45,English=62,RussianLanguage=70,Strength=33,UkrainianLanguage=16
|
||||
person f15.p1 Воробьёва Вера Виталиевна female=True roles=parent class=- born=1972-09-07 traits=Curious skills=Agility=60,Communication=60,Endurance=52,Geography=42,History=40,RussianLanguage=40,Strength=64,UkrainianLanguage=25
|
||||
person f16.c0 Фролова Елизавета Игоревна female=True roles=student class=class-classroom-02 born=2002-06-29 traits=Lazy,Quiet skills=Agility=65,BelarusianLanguage=14,Biology=19,Communication=30,Endurance=34,Literature=33,Mathematics=27,PhysicalEducation=42,RussianLanguage=17,Strength=67
|
||||
person f16.p0 Фролов Игорь Виталиевич female=False roles=parent class=- born=1968-07-25 traits= skills=Agility=57,BelarusianLanguage=37,Communication=58,Endurance=63,English=52,RussianLanguage=52,Strength=49,UkrainianLanguage=20
|
||||
person f16.p1 Фролова Татьяна Олеговна female=True roles=parent class=- born=1970-06-17 traits=Curious,Diligent skills=Agility=80,BelarusianLanguage=5,Communication=63,Endurance=71,RussianLanguage=71,Strength=52
|
||||
person f17.c0 Иванов Андрей Александрович female=False roles=student class=class-classroom-03 born=2001-06-27 traits= skills=Agility=44,BelarusianLanguage=13,Biology=29,Communication=39,Endurance=60,Literature=49,Mathematics=34,PhysicalEducation=60,RussianLanguage=24,Strength=55
|
||||
person f17.c1 Иванова Ксения Александровна female=True roles=student class=class-classroom-02 born=2001-09-10 traits= skills=Agility=45,BelarusianLanguage=21,Biology=25,Communication=28,Endurance=64,Literature=66,Mathematics=37,PhysicalEducation=59,RussianLanguage=58,Strength=45
|
||||
person f17.c2 Иванова Полина Александровна female=True roles=student class=class-classroom-03 born=2001-05-21 traits=HotTempered,Kind skills=Agility=36,Biology=53,Communication=45,Endurance=45,Literature=43,Mathematics=29,PhysicalEducation=51,RussianLanguage=42,Strength=45,UkrainianLanguage=23
|
||||
person f17.p0 Иванов Александр Владимирович female=False roles=parent class=- born=1967-12-24 traits=Diligent,HotTempered skills=Agility=47,Communication=74,Cooking=58,Endurance=52,English=20,RussianLanguage=61,Strength=55
|
||||
person f17.p1 Иванова Александра Ивановна female=True roles=parent class=- born=1967-04-25 traits= skills=Agility=40,BelarusianLanguage=7,Communication=69,Endurance=63,Geography=64,Literature=72,RussianLanguage=73,Strength=40
|
||||
person f18.c0 Лебедев Александр Валериевич female=False roles=student class=class-classroom-00 born=2004-02-16 traits= skills=Agility=49,BelarusianLanguage=28,Biology=36,Communication=39,Endurance=28,Literature=38,Mathematics=32,PhysicalEducation=36,RussianLanguage=37,Strength=21
|
||||
person f18.p0 Лебедев Валерий Романович female=False roles=parent class=- born=1985-03-29 traits=Neat,Quiet skills=Agility=25,Communication=59,Endurance=35,English=60,Mathematics=59,Medicine=44,Pedagogy=62,Physics=45,RussianLanguage=67,Strength=33,UkrainianLanguage=19
|
||||
person f18.p1 Лебедева Юлия Михаиловна female=True roles=parent class=- born=1981-01-26 traits=Leader skills=Agility=44,Communication=73,Endurance=86,Geography=30,Medicine=45,Pedagogy=43,RussianLanguage=57,Strength=41,UkrainianLanguage=36
|
||||
person f19.c0 Воробьёв Григорий Михаилович female=False roles=student class=class-classroom-00 born=2004-08-29 traits=Quiet skills=Agility=62,Biology=45,Communication=36,Endurance=50,Literature=42,Mathematics=12,PhysicalEducation=56,RussianLanguage=54,Strength=37
|
||||
person f19.p0 Воробьёв Михаил Егорович female=False roles=parent class=- born=1978-11-03 traits=Lazy skills=Agility=40,BelarusianLanguage=34,Communication=56,Cooking=54,Endurance=46,History=51,RussianLanguage=61,Strength=40
|
||||
person f19.p1 Воробьёва Вера Алексеевна female=True roles=parent class=- born=1982-08-29 traits=HotTempered skills=Administration=50,Agility=45,BelarusianLanguage=20,Communication=67,Cooking=21,Endurance=57,Geography=41,PhysicalEducation=46,RussianLanguage=36,Strength=40,UkrainianLanguage=25
|
||||
person f2.c0 Алексеев Григорий Константинович female=False roles=student class=class-classroom-02 born=2002-07-24 traits=AbsentMinded,Curious skills=Agility=35,BelarusianLanguage=27,Biology=50,Communication=30,Endurance=68,Literature=50,Mathematics=8,PhysicalEducation=72,RussianLanguage=9,Strength=45,UkrainianLanguage=17
|
||||
person f2.p0 Алексеев Константин Романович female=False roles=parent class=- born=1974-12-11 traits=Neat skills=Administration=52,Agility=36,Communication=60,Cooking=55,Endurance=49,English=30,Geography=52,Mathematics=65,RussianLanguage=64,Strength=47,UkrainianLanguage=9
|
||||
person f2.p1 Алексеева Ольга Романовна female=True roles=parent class=- born=1970-07-22 traits=HotTempered skills=Administration=45,Agility=45,BelarusianLanguage=22,Communication=82,Endurance=54,English=46,History=43,Librarianship=65,RussianLanguage=65,Strength=64
|
||||
person f20.c0 Павлова Елена Игоревна female=True roles=student class=class-classroom-01 born=2002-11-09 traits= skills=Agility=48,Biology=38,Communication=37,Endurance=34,Literature=70,Mathematics=48,PhysicalEducation=51,RussianLanguage=26,Strength=40,UkrainianLanguage=21
|
||||
person f20.c1 Павлова Валентина Игоревна female=True roles=student class=class-classroom-03 born=2001-01-24 traits= skills=Agility=46,BelarusianLanguage=19,Biology=50,Communication=32,Endurance=50,Literature=44,Mathematics=19,PhysicalEducation=52,RussianLanguage=39,Strength=38,UkrainianLanguage=27
|
||||
person f20.p0 Павлов Игорь Никитич female=False roles=parent class=- born=1968-08-01 traits=HotTempered,Leader skills=Agility=72,Communication=57,Endurance=43,Informatics=54,Physics=43,RussianLanguage=49,Strength=43
|
||||
person f20.p1 Павлова Людмила Дмитриевна female=True roles=parent class=- born=1970-01-17 traits= skills=Agility=60,BelarusianLanguage=28,Communication=48,Cooking=71,Endurance=56,RussianLanguage=63,Strength=46
|
||||
person f21.c0 Ильин Андрей Константинович female=False roles=student class=class-classroom-02 born=2002-05-12 traits= skills=Agility=31,BelarusianLanguage=28,Biology=59,Communication=61,Endurance=48,Literature=47,Mathematics=34,PhysicalEducation=60,RussianLanguage=22,Strength=54
|
||||
person f21.p0 Ильин Константин Никитич female=False roles=parent class=- born=1971-01-21 traits=Diligent,Quiet skills=Agility=45,BelarusianLanguage=30,Communication=53,Endurance=40,Medicine=40,Pedagogy=74,PhysicalEducation=48,Physics=57,RussianLanguage=45,Strength=44,UkrainianLanguage=19
|
||||
person f21.p1 Ильина Яна Борисовна female=True roles=parent class=- born=1975-04-20 traits=Curious skills=Agility=35,BelarusianLanguage=13,Communication=62,Endurance=55,Informatics=60,Pedagogy=42,RussianLanguage=68,Strength=53,UkrainianLanguage=20
|
||||
person f22.c0 Захаров Никита Виталиевич female=False roles=student class=class-classroom-03 born=2000-09-14 traits=Diligent,Quiet skills=Agility=48,Biology=62,Communication=33,Endurance=59,Literature=64,Mathematics=32,PhysicalEducation=49,RussianLanguage=70,Strength=69
|
||||
person f22.c1 Захаров Денис Виталиевич female=False roles=student class=class-classroom-02 born=2001-09-11 traits=AbsentMinded skills=Agility=51,BelarusianLanguage=27,Biology=53,Communication=57,Endurance=53,Literature=74,Mathematics=18,PhysicalEducation=46,RussianLanguage=63,Strength=61
|
||||
person f22.p0 Захаров Виталий Андреевич female=False roles=parent class=- born=1966-04-08 traits= skills=Agility=29,BelarusianLanguage=2,Communication=62,Cooking=40,Endurance=82,English=62,Librarianship=50,RussianLanguage=64,Strength=30
|
||||
person f22.p1 Захарова Елизавета Егоровна female=True roles=parent class=- born=1967-09-05 traits=Diligent,HotTempered skills=Administration=51,Agility=51,BelarusianLanguage=6,Biology=40,Communication=56,Endurance=52,English=53,Librarianship=50,Literature=79,RussianLanguage=62,Strength=62
|
||||
person f23.c0 Орловская Нина Константиновна female=True roles=student class=class-classroom-02 born=2001-11-01 traits=Neat skills=Agility=55,Biology=45,Communication=40,Endurance=55,Literature=16,Mathematics=38,PhysicalEducation=57,RussianLanguage=39,Strength=45,UkrainianLanguage=15
|
||||
person f23.c1 Орловская Полина Константиновна female=True roles=student class=class-classroom-01 born=2003-03-30 traits=Leader,Neat skills=Agility=51,BelarusianLanguage=20,Biology=51,Communication=22,Endurance=42,Literature=39,Mathematics=14,PhysicalEducation=54,RussianLanguage=24,Strength=40
|
||||
person f23.p0 Орловский Константин Михаилович female=False roles=parent class=- born=1965-04-02 traits=Diligent,HotTempered skills=Agility=45,Communication=55,Endurance=50,History=57,Librarianship=42,Mathematics=40,Pedagogy=35,RussianLanguage=46,Strength=50
|
||||
person f23.p1 Орловская Яна Степановна female=True roles=parent class=- born=1965-10-22 traits= skills=Agility=42,Communication=52,Endurance=55,RussianLanguage=46,Strength=34,UkrainianLanguage=10
|
||||
person f24.c0 Орлов Фёдор Алексеевич female=False roles=student class=class-classroom-03 born=2000-12-05 traits= skills=Agility=56,Biology=45,Communication=20,Endurance=35,Literature=67,Mathematics=23,PhysicalEducation=33,RussianLanguage=65,Strength=36
|
||||
person f24.c1 Орлова Оксана Алексеевна female=True roles=student class=class-classroom-00 born=2004-03-01 traits=Neat skills=Agility=55,BelarusianLanguage=4,Biology=40,Communication=43,Endurance=43,Literature=39,Mathematics=17,PhysicalEducation=56,RussianLanguage=27,Strength=26,UkrainianLanguage=25
|
||||
person f24.p0 Орлов Алексей Денисович female=False roles=parent class=- born=1977-04-17 traits= skills=Agility=45,BelarusianLanguage=21,Communication=51,Endurance=18,English=62,Geography=46,RussianLanguage=67,Strength=46
|
||||
person f24.p1 Орлова Надежда Владиславовна female=True roles=parent class=- born=1977-12-04 traits=Quiet skills=Agility=65,Biology=64,Communication=70,Cooking=41,Endurance=45,Librarianship=49,RussianLanguage=71,Strength=65
|
||||
person f25.c0 Петрова Александра Игоревна female=True roles=student class=class-classroom-02 born=2001-12-19 traits=AbsentMinded,Lazy skills=Agility=51,BelarusianLanguage=20,Biology=58,Communication=40,Endurance=54,Literature=65,Mathematics=50,PhysicalEducation=35,RussianLanguage=32,Strength=57
|
||||
person f25.p1 Петрова Полина Юриевна female=True roles=parent class=- born=1965-12-11 traits=Kind,Neat skills=Agility=53,BelarusianLanguage=15,Communication=50,Endurance=59,RussianLanguage=54,Strength=45
|
||||
person f26.c0 Яковлев Павел Михаилович female=False roles=student class=class-classroom-01 born=2002-12-29 traits=Curious skills=Agility=59,BelarusianLanguage=27,Biology=79,Communication=32,Endurance=57,Literature=35,Mathematics=10,PhysicalEducation=64,RussianLanguage=35,Strength=45
|
||||
person f26.c1 Яковлев Вадим Михаилович female=False roles=student class=class-classroom-00 born=2004-06-28 traits=Neat skills=Agility=54,BelarusianLanguage=17,Biology=66,Communication=43,Endurance=52,Literature=40,Mathematics=18,PhysicalEducation=34,RussianLanguage=22,Strength=45
|
||||
person f26.p0 Яковлев Михаил Степанович female=False roles=parent class=- born=1975-12-27 traits=HotTempered,Neat skills=Administration=44,Agility=44,Biology=52,Communication=59,Cooking=40,Endurance=66,English=56,Mathematics=55,RussianLanguage=52,Strength=53
|
||||
person f26.p1 Яковлева Марина Кирилловна female=True roles=parent class=- born=1976-12-10 traits=HotTempered,Kind skills=Agility=37,BelarusianLanguage=21,Communication=47,Cooking=44,Endurance=31,Pedagogy=40,RussianLanguage=68,Strength=48,UkrainianLanguage=27
|
||||
person f27.c0 Иванов Виктор Константинович female=False roles=student class=class-classroom-01 born=2002-12-27 traits=AbsentMinded,Curious skills=Agility=35,Biology=50,Communication=26,Endurance=35,Literature=60,Mathematics=1,PhysicalEducation=46,RussianLanguage=57,Strength=38
|
||||
person f27.c1 Иванов Владислав Константинович female=False roles=student class=class-classroom-00 born=2004-07-04 traits= skills=Agility=50,BelarusianLanguage=24,Biology=61,Communication=24,Endurance=76,Literature=72,Mathematics=25,PhysicalEducation=46,RussianLanguage=34,Strength=45,UkrainianLanguage=17
|
||||
person f27.c2 Иванов Александр Константинович female=False roles=student class=class-classroom-00 born=2004-05-25 traits=Kind,Neat skills=Agility=65,BelarusianLanguage=28,Biology=49,Communication=43,Endurance=68,Literature=42,Mathematics=46,PhysicalEducation=52,RussianLanguage=35,Strength=45,UkrainianLanguage=32
|
||||
person f27.p0 Иванов Константин Иванович female=False roles=parent class=- born=1974-08-25 traits=Neat skills=Administration=49,Agility=44,BelarusianLanguage=34,Communication=77,Endurance=42,English=55,RussianLanguage=36,Strength=64,UkrainianLanguage=26
|
||||
person f27.p1 Иванова Марина Константиновна female=True roles=parent class=- born=1969-11-29 traits=Quiet skills=Agility=46,BelarusianLanguage=21,Communication=61,Endurance=32,English=46,Librarianship=53,RussianLanguage=54,Strength=37
|
||||
person f28.c0 Иванов Пётр Петрович female=False roles=student class=class-classroom-02 born=2002-08-02 traits=AbsentMinded,Neat skills=Agility=73,Biology=62,Communication=42,Endurance=43,Literature=59,Mathematics=48,PhysicalEducation=39,RussianLanguage=11,Strength=45
|
||||
person f28.c1 Иванова Наталья Петровна female=True roles=student class=class-classroom-03 born=2000-12-07 traits=Bully,Lazy skills=Agility=64,BelarusianLanguage=30,Biology=46,Communication=27,Endurance=59,Literature=34,Mathematics=67,PhysicalEducation=69,RussianLanguage=51,Strength=45,UkrainianLanguage=23
|
||||
person f28.c2 Иванов Максим Петрович female=False roles=student class=class-classroom-00 born=2004-04-05 traits=Lazy skills=Agility=67,BelarusianLanguage=13,Biology=59,Communication=26,Endurance=54,Literature=31,Mathematics=29,PhysicalEducation=63,RussianLanguage=55,Strength=51,UkrainianLanguage=25
|
||||
person f28.p0 Иванов Пётр Олегович female=False roles=parent class=- born=1965-06-23 traits=AbsentMinded,Kind skills=Agility=75,BelarusianLanguage=26,Communication=60,Endurance=74,Informatics=60,Literature=57,Pedagogy=56,RussianLanguage=39,Strength=48
|
||||
person f28.p1 Иванова Полина Алексеевна female=True roles=parent class=- born=1965-11-18 traits= skills=Agility=17,BelarusianLanguage=24,Chemistry=40,Communication=52,Endurance=35,Librarianship=59,Medicine=69,Physics=42,RussianLanguage=50,Strength=61,UkrainianLanguage=21
|
||||
person f29.c0 Макарова Ксения Александровна female=True roles=student class=class-classroom-01 born=2002-11-08 traits=Bully skills=Agility=52,BelarusianLanguage=27,Biology=62,Communication=35,Endurance=53,Literature=71,Mathematics=48,PhysicalEducation=35,RussianLanguage=41,Strength=45
|
||||
person f29.p0 Макаров Александр Николаевич female=False roles=parent class=- born=1981-11-08 traits=AbsentMinded skills=Administration=40,Agility=50,BelarusianLanguage=25,Chemistry=42,Communication=44,Endurance=55,Geography=56,Librarianship=66,RussianLanguage=69,Strength=40,UkrainianLanguage=19
|
||||
person f29.p1 Макарова Мария Владиславовна female=True roles=parent class=- born=1977-10-31 traits=HotTempered skills=Agility=45,BelarusianLanguage=23,Chemistry=42,Communication=37,Endurance=70,Literature=20,RussianLanguage=54,Strength=44,UkrainianLanguage=25
|
||||
person f3.c0 Макарова Вероника Петровна female=True roles=student class=class-classroom-02 born=2002-05-15 traits=Curious,Diligent skills=Agility=37,BelarusianLanguage=32,Biology=32,Communication=61,Endurance=71,Literature=63,Mathematics=27,PhysicalEducation=60,RussianLanguage=66,Strength=81
|
||||
person f3.c1 Макаров Роман Петрович female=False roles=student class=class-classroom-02 born=2002-04-16 traits= skills=Agility=40,BelarusianLanguage=28,Biology=55,Communication=32,Endurance=34,Literature=51,Mathematics=41,PhysicalEducation=49,RussianLanguage=44,Strength=37
|
||||
person f3.p0 Макаров Пётр Егорович female=False roles=parent class=- born=1977-02-28 traits=Diligent,Neat skills=Agility=67,Communication=28,Endurance=53,English=57,Librarianship=39,RussianLanguage=45,Strength=42,UkrainianLanguage=26
|
||||
person f3.p1 Макарова Алина Антоновна female=True roles=parent class=- born=1978-04-05 traits= skills=Agility=62,BelarusianLanguage=26,Communication=63,Endurance=39,RussianLanguage=64,Strength=45
|
||||
person f30.c0 Иванова Светлана Владимировна female=True roles=student class=class-classroom-03 born=2000-10-08 traits= skills=Agility=38,Biology=51,Communication=37,Endurance=48,Literature=46,Mathematics=39,PhysicalEducation=44,RussianLanguage=33,Strength=45,UkrainianLanguage=38
|
||||
person f30.c1 Иванова Надежда Владимировна female=True roles=student class=class-classroom-03 born=2000-12-10 traits=Bully skills=Agility=27,Biology=46,Communication=49,Endurance=61,Literature=36,Mathematics=38,PhysicalEducation=72,RussianLanguage=39,Strength=45,UkrainianLanguage=27
|
||||
person f30.p0 Иванов Владимир Денисович female=False roles=parent class=- born=1974-06-12 traits=Lazy skills=Agility=40,BelarusianLanguage=26,Biology=37,Communication=72,Endurance=50,Librarianship=45,Physics=66,RussianLanguage=46,Strength=40
|
||||
person f30.p1 Иванова Мария Андреевна female=True roles=parent class=- born=1973-09-24 traits= skills=Administration=44,Agility=52,Communication=61,Endurance=62,RussianLanguage=46,Strength=45,UkrainianLanguage=30
|
||||
person f31.c0 Иванов Николай Вадимович female=False roles=student class=class-classroom-01 born=2003-08-29 traits= skills=Agility=41,Biology=43,Communication=32,Endurance=44,Literature=45,Mathematics=53,PhysicalEducation=47,RussianLanguage=7,Strength=45,UkrainianLanguage=21
|
||||
person f31.p0 Иванов Вадим Андреевич female=False roles=parent class=- born=1985-06-23 traits=Diligent,Quiet skills=Agility=45,BelarusianLanguage=25,Communication=54,Endurance=71,Medicine=57,PhysicalEducation=60,RussianLanguage=56,Strength=53,UkrainianLanguage=25
|
||||
person f31.p1 Иванова Александра Юриевна female=True roles=parent class=- born=1980-08-20 traits=Diligent skills=Administration=54,Agility=75,BelarusianLanguage=19,Chemistry=43,Communication=65,Cooking=53,Endurance=50,PhysicalEducation=67,RussianLanguage=36,Strength=48,UkrainianLanguage=37
|
||||
person f32.c0 Петров Артём Евгениевич female=False roles=student class=class-classroom-02 born=2002-07-14 traits=Quiet skills=Agility=31,BelarusianLanguage=34,Biology=33,Communication=5,Endurance=20,Literature=45,Mathematics=21,PhysicalEducation=64,RussianLanguage=42,Strength=80,UkrainianLanguage=25
|
||||
person f32.c1 Петрова Елена Евгениевна female=True roles=student class=class-classroom-00 born=2003-10-27 traits=Quiet skills=Agility=47,BelarusianLanguage=30,Biology=51,Communication=68,Endurance=48,Literature=46,Mathematics=37,PhysicalEducation=59,RussianLanguage=25,Strength=38,UkrainianLanguage=22
|
||||
person f32.c2 Петрова Ирина Евгениевна female=True roles=student class=class-classroom-02 born=2001-09-18 traits=HotTempered,Kind skills=Agility=54,BelarusianLanguage=29,Biology=54,Communication=28,Endurance=49,Literature=31,Mathematics=41,PhysicalEducation=67,RussianLanguage=50,Strength=52
|
||||
person f32.p0 Петров Евгений Станиславович female=False roles=parent class=- born=1963-05-02 traits= skills=Agility=45,BelarusianLanguage=23,Chemistry=61,Communication=66,Endurance=43,Mathematics=49,Pedagogy=34,RussianLanguage=58,Strength=41,UkrainianLanguage=29
|
||||
person f33.c0 Морозова Елизавета Григориевна female=True roles=student class=class-classroom-00 born=2003-11-04 traits=Diligent,Quiet skills=Agility=21,BelarusianLanguage=25,Biology=38,Communication=41,Endurance=55,Literature=54,Mathematics=53,PhysicalEducation=66,RussianLanguage=42,Strength=45
|
||||
person f33.p0 Морозов Григорий Михаилович female=False roles=parent class=- born=1968-05-01 traits= skills=Administration=71,Agility=28,BelarusianLanguage=22,Communication=68,Endurance=62,English=53,Librarianship=36,RussianLanguage=52,Strength=51,UkrainianLanguage=14
|
||||
person f33.p1 Морозова Марина Владимировна female=True roles=parent class=- born=1972-10-24 traits=HotTempered skills=Agility=65,BelarusianLanguage=23,Communication=28,Endurance=40,Pedagogy=57,RussianLanguage=56,Strength=40,UkrainianLanguage=11
|
||||
person f34.c0 Кузнецова Валентина Ивановна female=True roles=student class=class-classroom-00 born=2004-03-25 traits=Curious,Kind skills=Agility=29,BelarusianLanguage=22,Biology=48,Communication=21,Endurance=69,Literature=30,Mathematics=39,PhysicalEducation=35,RussianLanguage=28,Strength=45,UkrainianLanguage=24
|
||||
person f34.p0 Кузнецов Иван Сергеевич female=False roles=parent class=- born=1970-02-02 traits= skills=Agility=44,Communication=43,Endurance=58,English=73,Geography=37,Physics=49,RussianLanguage=77,Strength=40
|
||||
person f34.p1 Кузнецова Дарья Валериевна female=True roles=parent class=- born=1967-03-25 traits=Lazy skills=Administration=60,Agility=69,BelarusianLanguage=23,Communication=67,Cooking=44,Endurance=47,German=38,RussianLanguage=70,Strength=48,UkrainianLanguage=15
|
||||
person f4.c0 Васильев Денис Федорович female=False roles=student class=class-classroom-01 born=2003-02-01 traits=Neat skills=Agility=50,BelarusianLanguage=6,Biology=39,Communication=27,Endurance=35,Literature=59,Mathematics=36,PhysicalEducation=88,RussianLanguage=47,Strength=21,UkrainianLanguage=13
|
||||
person f4.p0 Васильев Фёдор Игоревич female=False roles=parent class=- born=1970-05-21 traits=AbsentMinded skills=Agility=66,BelarusianLanguage=31,Communication=49,Cooking=45,Endurance=44,English=36,Literature=48,Pedagogy=62,RussianLanguage=54,Strength=44
|
||||
person f4.p1 Васильева Анастасия Федоровна female=True roles=parent class=- born=1975-01-20 traits=AbsentMinded skills=Agility=45,BelarusianLanguage=22,Communication=70,Endurance=53,English=43,Librarianship=49,Medicine=75,RussianLanguage=49,Strength=73,UkrainianLanguage=13
|
||||
person f5.c0 Захарова Екатерина Борисовна female=True roles=student class=class-classroom-02 born=2002-07-13 traits=Kind skills=Agility=43,Biology=46,Communication=44,Endurance=43,Literature=38,Mathematics=52,PhysicalEducation=52,RussianLanguage=45,Strength=32
|
||||
person f5.p0 Захаров Борис Николаевич female=False roles=parent class=- born=1980-04-15 traits= skills=Agility=45,Communication=37,Endurance=51,English=44,RussianLanguage=57,Strength=29
|
||||
person f5.p1 Захарова Вероника Григориевна female=True roles=parent class=- born=1979-06-22 traits= skills=Agility=27,Communication=47,Endurance=76,English=24,RussianLanguage=63,Strength=45,UkrainianLanguage=31
|
||||
person f6.c0 Козловская Юлия Олеговна female=True roles=student class=class-classroom-00 born=2004-08-15 traits= skills=Agility=45,BelarusianLanguage=20,Biology=36,Communication=42,Endurance=61,Literature=49,Mathematics=27,PhysicalEducation=45,RussianLanguage=40,Strength=70
|
||||
person f6.c1 Козловская Светлана Олеговна female=True roles=student class=class-classroom-02 born=2001-12-31 traits=HotTempered,Leader skills=Agility=53,Biology=47,Communication=36,Endurance=40,Literature=59,Mathematics=52,PhysicalEducation=70,RussianLanguage=36,Strength=40
|
||||
person f6.c2 Козловская Вероника Олеговна female=True roles=student class=class-classroom-00 born=2003-09-29 traits= skills=Agility=17,BelarusianLanguage=17,Biology=38,Communication=36,Endurance=27,Literature=54,Mathematics=10,PhysicalEducation=51,RussianLanguage=16,Strength=29,UkrainianLanguage=40
|
||||
person f6.p0 Козловский Олег Станиславович female=False roles=parent class=- born=1967-12-18 traits=Kind skills=Agility=42,Biology=44,Communication=82,Endurance=64,Mathematics=33,RussianLanguage=29,Strength=52
|
||||
person f6.p1 Козловская Ирина Кирилловна female=True roles=parent class=- born=1963-12-28 traits= skills=Administration=90,Agility=48,BelarusianLanguage=11,Communication=29,Endurance=57,English=48,Librarianship=57,RussianLanguage=48,Strength=61
|
||||
person f7.c0 Андреев Виктор Степанович female=False roles=student class=class-classroom-01 born=2003-07-19 traits=Bully,Leader skills=Agility=20,Biology=38,Communication=31,Endurance=75,Literature=54,Mathematics=40,PhysicalEducation=60,RussianLanguage=8,Strength=45,UkrainianLanguage=7
|
||||
person f7.p0 Андреев Степан Андреевич female=False roles=parent class=- born=1973-08-21 traits= skills=Administration=51,Agility=64,BelarusianLanguage=35,Chemistry=42,Communication=76,Endurance=36,Medicine=23,Physics=30,RussianLanguage=67,Strength=46,UkrainianLanguage=27
|
||||
person f7.p1 Андреева Мария Алексеевна female=True roles=parent class=- born=1977-07-16 traits= skills=Agility=59,Communication=68,Cooking=41,Endurance=49,History=47,Mathematics=54,Medicine=44,RussianLanguage=63,Strength=35,UkrainianLanguage=40
|
||||
person f8.c0 Фролов Евгений Павелович female=False roles=student class=class-classroom-00 born=2003-12-20 traits=Bully skills=Agility=52,Biology=45,Communication=20,Endurance=78,Literature=61,Mathematics=33,PhysicalEducation=64,RussianLanguage=31,Strength=45,UkrainianLanguage=19
|
||||
person f8.c1 Фролов Станислав Павелович female=False roles=student class=class-classroom-03 born=2000-10-11 traits=Curious skills=Agility=58,BelarusianLanguage=24,Biology=57,Communication=18,Endurance=69,Literature=55,Mathematics=33,PhysicalEducation=48,RussianLanguage=42,Strength=67,UkrainianLanguage=28
|
||||
person f8.p0 Фролов Павел Егорович female=False roles=parent class=- born=1968-06-07 traits=Leader skills=Agility=71,BelarusianLanguage=22,Communication=87,Endurance=39,RussianLanguage=64,Strength=44
|
||||
person f8.p1 Фролова Виктория Степановна female=True roles=parent class=- born=1963-10-04 traits= skills=Agility=59,BelarusianLanguage=25,Communication=51,Endurance=55,Geography=48,Pedagogy=58,RussianLanguage=25,Strength=63
|
||||
person f9.c0 Кузьмина Любовь Александровна female=True roles=student class=class-classroom-01 born=2003-06-13 traits=Kind skills=Agility=45,BelarusianLanguage=23,Biology=43,Communication=31,Endurance=32,Literature=46,Mathematics=44,PhysicalEducation=62,RussianLanguage=29,Strength=39,UkrainianLanguage=5
|
||||
person f9.c1 Кузьмин Сергей Александрович female=False roles=student class=class-classroom-03 born=2001-08-20 traits=Curious,Quiet skills=Agility=11,BelarusianLanguage=18,Biology=37,Communication=41,Endurance=59,Literature=59,Mathematics=25,PhysicalEducation=67,RussianLanguage=41,Strength=38
|
||||
person f9.c2 Кузьмина Алина Александровна female=True roles=student class=class-classroom-03 born=2001-01-22 traits= skills=Agility=52,Biology=50,Communication=29,Endurance=53,Literature=38,Mathematics=52,PhysicalEducation=56,RussianLanguage=54,Strength=31
|
||||
person f9.p0 Кузьмин Александр Денисович female=False roles=parent class=- born=1981-12-09 traits= skills=Agility=40,Communication=58,Cooking=58,Endurance=78,Literature=42,Medicine=65,Physics=58,RussianLanguage=68,Strength=42
|
||||
person f9.p1 Кузьмина Анастасия Сергеевна female=True roles=parent class=- born=1977-01-01 traits=AbsentMinded skills=Agility=68,BelarusianLanguage=27,Communication=96,Endurance=46,Librarianship=43,Pedagogy=48,RussianLanguage=61,Strength=40,UkrainianLanguage=21
|
||||
person f0.c0 Андреев Сергей Валериевич female=False roles=student class=class-classroom-03 born=2000-10-23 traits=Lazy skills=Agility=33,Biology=57,Communication=47,Endurance=46,Hauling=56,Literature=22,Mathematics=12,PhysicalEducation=65,RussianLanguage=47,Strength=64,UkrainianLanguage=31 items=Underwear:Black:worn,Socks:Gray:worn,Jeans:Black:worn,TShirt:Black:worn,Shoes:Gray:worn,Sweater:Gray:worn,Scarf:Black:worn,Coat:Black:home,PeShirt:Gray:home,PeShorts:Gray:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f0.c1 Андреев Александр Валериевич female=False roles=student class=class-classroom-01 born=2002-11-09 traits=Kind,Quiet skills=Agility=13,Biology=46,Communication=20,Endurance=52,Hauling=24,Literature=35,Mathematics=49,PhysicalEducation=57,RussianLanguage=47,Strength=45 items=Underwear:Black:worn,Socks:Gray:worn,Jeans:Blue:worn,TShirt:LightBlue:worn,Shoes:Gray:worn,Sweater:Black:worn,Coat:Beige:worn,Scarf:Gray:worn,PeShirt:Gray:home,PeShorts:Black:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f0.p0 Андреев Валерий Николаевич female=False roles=parent class=- born=1971-06-03 traits=Diligent,Quiet skills=Agility=43,Communication=58,Cooking=82,Endurance=61,Hauling=61,Pedagogy=50,RussianLanguage=89,Strength=33 items=Underwear:Black:worn,Socks:White:worn,Jeans:Black:worn,TShirt:LightBlue:worn,WinterBoots:Beige:worn,Jacket:Gray:worn,Bottle:Green:bag
|
||||
person f0.p1 Андреева Марина Артемовна female=True roles=parent class=- born=1971-09-30 traits=Quiet skills=Agility=25,BelarusianLanguage=26,Communication=38,Endurance=35,Hauling=46,History=61,Mathematics=75,RussianLanguage=65,Strength=40,UkrainianLanguage=23 items=Underwear:Gray:worn,Socks:White:worn,Pants:Beige:worn,Shirt:Blue:worn,WinterBoots:Gray:worn,Sweater:Beige:worn,Jacket:Blue:home,Bottle:White:bag,Phone:Black:bag
|
||||
person f1.c0 Александрова Людмила Борисовна female=True roles=student class=class-classroom-03 born=2001-01-26 traits=AbsentMinded skills=Agility=72,BelarusianLanguage=36,Biology=67,Communication=37,Endurance=39,Hauling=56,Literature=77,Mathematics=29,PhysicalEducation=54,RussianLanguage=51,Strength=45,UkrainianLanguage=28 items=Underwear:Black:worn,Socks:White:worn,Dress:Black:worn,Shoes:White:worn,Belt:Beige:worn,Jacket:Black:home,PeShirt:Blue:home,PeShorts:Blue:home,Bottle:Blue:bag,Phone:Black:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f1.c1 Александров Евгений Борисович female=False roles=student class=class-classroom-00 born=2004-04-01 traits= skills=Agility=31,BelarusianLanguage=27,Biology=50,Communication=38,Endurance=54,Hauling=58,Literature=65,Mathematics=30,PhysicalEducation=88,RussianLanguage=44,Strength=40 items=Underwear:White:worn,Socks:Black:worn,Jeans:Black:worn,TShirt:Blue:worn,WinterBoots:Black:worn,Hat:Black:worn,Coat:Gray:home,PeShirt:Blue:home,PeShorts:Blue:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f1.c2 Александров Юрий Борисович female=False roles=student class=class-classroom-00 born=2003-10-28 traits= skills=Agility=45,Biology=68,Communication=31,Endurance=30,Hauling=49,Literature=60,Mathematics=29,PhysicalEducation=49,RussianLanguage=53,Strength=74,UkrainianLanguage=23 items=Underwear:Black:worn,Socks:Gray:worn,Pants:Blue:worn,TShirt:LightBlue:worn,Shoes:Black:worn,Sweater:Blue:worn,Scarf:Black:worn,Coat:Beige:home,PeShirt:Red:home,PeShorts:Gray:home,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f1.p0 Александров Борис Ильич female=False roles=parent class=- born=1968-10-25 traits= skills=Agility=45,Communication=74,Endurance=34,Hauling=65,RussianLanguage=53,Strength=53,UkrainianLanguage=14 items=Underwear:Black:worn,Socks:White:worn,Trousers:Gray:worn,TShirt:Blue:worn,WinterBoots:Gray:worn,Hat:Beige:worn,Scarf:Gray:worn,FurCoat:Beige:home
|
||||
person f1.p1 Александрова Елизавета Романовна female=True roles=parent class=- born=1972-01-25 traits= skills=Administration=71,Agility=45,BelarusianLanguage=26,Communication=76,Cooking=59,Endurance=35,English=58,Hauling=48,Mathematics=30,RussianLanguage=42,Strength=66 items=Underwear:Black:worn,Socks:Black:worn,Skirt:Beige:worn,Shirt:Blue:worn,WinterBoots:Beige:worn,Sweater:Beige:worn,Coat:Beige:home,Bottle:White:bag,Phone:White:bag
|
||||
person f10.c0 Захаров Пётр Виталиевич female=False roles=student class=class-classroom-02 born=2001-11-08 traits=Diligent skills=Agility=31,BelarusianLanguage=26,Biology=62,Communication=54,Endurance=45,Hauling=56,Literature=25,Mathematics=81,PhysicalEducation=63,RussianLanguage=46,Strength=60 items=Underwear:Black:worn,Socks:Black:worn,Pants:Gray:worn,TShirt:Black:worn,WinterBoots:Beige:worn,Jacket:Gray:home,PeShirt:Red:home,PeShorts:Red:home,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f10.p0 Захаров Виталий Борисович female=False roles=parent class=- born=1976-09-07 traits=HotTempered,Leader skills=Agility=44,BelarusianLanguage=22,Communication=66,Endurance=82,English=16,Hauling=40,RussianLanguage=69,Strength=55 items=Underwear:Gray:worn,Socks:Black:worn,Trousers:Black:worn,TShirt:White:worn,WinterBoots:Black:worn,FurCoat:Gray:worn,Hat:Blue:worn,Scarf:Blue:worn,Bottle:White:bag,Phone:Black:bag
|
||||
person f10.p1 Захарова Любовь Валериевна female=True roles=parent class=- born=1978-11-03 traits=AbsentMinded,Kind skills=Administration=43,Agility=45,BelarusianLanguage=21,Communication=61,Endurance=53,English=52,Hauling=52,Medicine=23,PhysicalEducation=42,Physics=59,RussianLanguage=66,Strength=28 items=Underwear:Gray:worn,Socks:Gray:worn,Trousers:Blue:worn,Shirt:White:worn,Shoes:Gray:worn,Sweater:Blue:worn,FurCoat:Gray:home,Bottle:White:bag,Phone:Gray:bag
|
||||
person f11.c0 Андреева Дарья Ивановна female=True roles=student class=class-classroom-03 born=2001-05-20 traits=Leader skills=Agility=47,BelarusianLanguage=13,Biology=57,Communication=43,Endurance=44,Hauling=50,Literature=59,Mathematics=24,PhysicalEducation=61,RussianLanguage=47,Strength=45,UkrainianLanguage=24 items=Underwear:Gray:worn,Socks:White:worn,Dress:Beige:worn,Shoes:White:worn,Hat:Blue:worn,Coat:Gray:home,PeShirt:Black:home,PeShorts:Black:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f11.p0 Андреев Иван Алексеевич female=False roles=parent class=- born=1976-06-01 traits= skills=Agility=38,BelarusianLanguage=16,Communication=52,Endurance=82,Hauling=33,Medicine=48,Pedagogy=61,PhysicalEducation=54,RussianLanguage=82,Strength=67,UkrainianLanguage=22 items=Underwear:White:worn,Socks:White:worn,Jeans:Black:worn,Shirt:Gray:worn,WinterBoots:Gray:worn,Sweater:Beige:worn,FurCoat:Beige:worn,Phone:Gray:bag
|
||||
person f11.p1 Андреева София Александровна female=True roles=parent class=- born=1978-04-24 traits=Diligent,HotTempered skills=Agility=61,Communication=74,Endurance=55,English=61,Hauling=31,History=29,RussianLanguage=54,Strength=43 items=Underwear:Gray:worn,Socks:Black:worn,Trousers:Blue:worn,Shirt:Black:worn,WinterBoots:Black:worn,Coat:Gray:worn,Bottle:White:bag
|
||||
person f12.c0 Кузьмин Олег Владиславович female=False roles=student class=class-classroom-01 born=2003-03-20 traits=Bully,Lazy skills=Agility=49,Biology=58,Communication=48,Endurance=57,Hauling=54,Literature=50,Mathematics=33,PhysicalEducation=39,RussianLanguage=9,Strength=44,UkrainianLanguage=31 items=Underwear:White:worn,Socks:Gray:worn,Pants:Blue:worn,TShirt:LightBlue:worn,WinterBoots:Black:worn,Hat:Black:worn,Belt:Black:worn,FurCoat:Gray:home,PeShirt:Red:home,PeShorts:Red:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f12.c1 Кузьмин Егор Владиславович female=False roles=student class=class-classroom-01 born=2003-05-31 traits=Lazy,Leader skills=Agility=45,Biology=45,Communication=30,Endurance=59,Hauling=44,Literature=39,Mathematics=30,PhysicalEducation=59,RussianLanguage=49,Strength=35,UkrainianLanguage=23 items=Underwear:Gray:worn,Socks:Gray:worn,Pants:Black:worn,TShirt:Beige:worn,Shoes:Black:worn,Sweater:Black:worn,Coat:Black:worn,Belt:Beige:worn,PeShirt:Black:home,PeShorts:Black:home,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f12.c2 Кузьмина Дарья Владиславовна female=True roles=student class=class-classroom-01 born=2002-10-29 traits=Curious,Leader skills=Agility=42,BelarusianLanguage=20,Biology=56,Communication=39,Endurance=58,Hauling=59,Literature=35,Mathematics=22,PhysicalEducation=81,RussianLanguage=58,Strength=34,UkrainianLanguage=28 items=Underwear:Black:worn,Socks:Gray:worn,Skirt:Blue:worn,Shirt:Black:worn,Shoes:Black:worn,Sweater:Beige:worn,Coat:Beige:worn,PeShirt:Green:home,PeShorts:Black:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f12.p0 Кузьмин Владислав Александрович female=False roles=parent class=- born=1975-01-17 traits= skills=Administration=56,Agility=25,BelarusianLanguage=10,Communication=68,Endurance=35,English=36,Hauling=63,Informatics=56,Medicine=59,RussianLanguage=54,Strength=36 items=Underwear:Gray:worn,Socks:Gray:worn,Jeans:Blue:worn,Shirt:Blue:worn,Shoes:Gray:worn,Jacket:Blue:worn,Bottle:Blue:bag
|
||||
person f12.p1 Кузьмина Ольга Кирилловна female=True roles=parent class=- born=1979-10-15 traits=AbsentMinded,Kind skills=Administration=38,Agility=39,BelarusianLanguage=25,Chemistry=48,Communication=32,Endurance=41,English=42,Geography=41,Hauling=46,RussianLanguage=32,Strength=34,UkrainianLanguage=40 items=Underwear:Gray:worn,Socks:Gray:worn,Pants:Gray:worn,Shirt:Gray:worn,WinterBoots:Gray:worn,Sweater:Gray:worn,FurCoat:Gray:home
|
||||
person f13.c0 Яковлев Константин Владиславович female=False roles=student class=class-classroom-00 born=2004-06-16 traits= skills=Agility=53,BelarusianLanguage=24,Biology=48,Communication=29,Endurance=37,Hauling=64,Literature=58,Mathematics=22,PhysicalEducation=44,RussianLanguage=31,Strength=37 items=Underwear:Gray:worn,Socks:Black:worn,Trousers:Gray:worn,Shirt:Blue:worn,WinterBoots:Gray:worn,Jacket:Blue:home,PeShirt:Gray:home,PeShorts:Red:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f13.c1 Яковлев Юрий Владиславович female=False roles=student class=class-classroom-01 born=2003-07-23 traits=Diligent,Quiet skills=Agility=36,BelarusianLanguage=22,Biology=56,Communication=43,Endurance=44,Hauling=57,Literature=56,Mathematics=26,PhysicalEducation=51,RussianLanguage=37,Strength=68,UkrainianLanguage=8 items=Underwear:Black:worn,Socks:Gray:worn,Pants:Blue:worn,Shirt:Black:worn,WinterBoots:Gray:worn,Sweater:Gray:worn,FurCoat:Black:worn,PeShirt:Gray:home,PeShorts:Blue:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f13.c2 Яковлева Алина Владиславовна female=True roles=student class=class-classroom-01 born=2003-02-01 traits=Diligent skills=Agility=58,BelarusianLanguage=20,Biology=60,Communication=45,Endurance=54,Hauling=53,Literature=66,Mathematics=34,PhysicalEducation=47,RussianLanguage=59,Strength=45 items=Underwear:White:worn,Socks:White:worn,Trousers:Black:worn,Shirt:Blue:worn,Shoes:Gray:worn,Hat:Gray:worn,Scarf:Blue:worn,Coat:Beige:home,PeShirt:Red:home,PeShorts:Red:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f13.p0 Яковлев Владислав Андреевич female=False roles=parent class=- born=1974-09-23 traits=AbsentMinded,Kind skills=Agility=25,BelarusianLanguage=28,Communication=42,Endurance=35,English=26,Hauling=52,RussianLanguage=54,Strength=38 items=Underwear:Black:worn,Socks:White:worn,Trousers:Black:worn,TShirt:White:worn,Shoes:Beige:worn,Hat:Beige:worn,Coat:Beige:home,Bottle:Green:bag,Phone:White:bag
|
||||
person f14.c0 Александров Степан Денисович female=False roles=student class=class-classroom-02 born=2002-01-03 traits= skills=Agility=57,BelarusianLanguage=17,Biology=53,Communication=18,Endurance=60,Hauling=64,Literature=34,Mathematics=33,PhysicalEducation=55,RussianLanguage=32,Strength=41 items=Underwear:Gray:worn,Socks:Gray:worn,Pants:Blue:worn,TShirt:Gray:worn,Shoes:Black:worn,Sweater:Beige:worn,Jacket:Gray:worn,Hat:Blue:worn,Scarf:Blue:worn,PeShirt:Gray:home,PeShorts:Red:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f14.c1 Александрова Вероника Денисовна female=True roles=student class=class-classroom-03 born=2001-08-11 traits= skills=Agility=45,BelarusianLanguage=15,Biology=52,Communication=38,Endurance=37,Hauling=44,Literature=29,Mathematics=18,PhysicalEducation=65,RussianLanguage=46,Strength=64 items=Underwear:Black:worn,Socks:Gray:worn,Trousers:Gray:worn,TShirt:Black:worn,WinterBoots:Gray:worn,Belt:Gray:worn,FurCoat:Beige:home,PeShirt:Red:home,PeShorts:Gray:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f14.c2 Александров Константин Денисович female=False roles=student class=class-classroom-01 born=2003-08-21 traits= skills=Agility=29,BelarusianLanguage=21,Biology=66,Communication=21,Endurance=51,Hauling=42,Literature=64,Mathematics=27,PhysicalEducation=67,RussianLanguage=20,Strength=45 items=Underwear:White:worn,Socks:Gray:worn,Jeans:Gray:worn,TShirt:Gray:worn,Shoes:Gray:worn,Scarf:Blue:worn,Coat:Black:home,PeShirt:Blue:home,PeShorts:Red:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f14.p1 Александрова Виктория Викторовна female=True roles=parent class=- born=1973-07-23 traits= skills=Agility=45,Communication=72,Cooking=68,Endurance=64,Geography=58,Hauling=44,Physics=38,RussianLanguage=61,Strength=49,UkrainianLanguage=18 items=Underwear:Gray:worn,Socks:Gray:worn,Dress:Gray:worn,WinterBoots:Beige:worn,Hat:Black:worn,Coat:Black:home,Phone:Black:bag
|
||||
person f15.c0 Воробьёв Игорь Сергеевич female=False roles=student class=class-classroom-03 born=2000-09-20 traits= skills=Agility=45,BelarusianLanguage=24,Biology=33,Communication=61,Endurance=58,Hauling=42,Literature=45,Mathematics=32,PhysicalEducation=40,RussianLanguage=55,Strength=38 items=Underwear:Black:worn,Socks:White:worn,Trousers:Blue:worn,TShirt:Black:worn,Shoes:Beige:worn,Sweater:Black:worn,Hat:Gray:worn,FurCoat:Black:home,PeShirt:Green:home,PeShorts:Blue:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f15.p0 Воробьёв Сергей Никитич female=False roles=parent class=- born=1974-10-22 traits=Neat,Quiet skills=Agility=45,Communication=54,Endurance=45,Hauling=36,Librarianship=67,Pedagogy=38,RussianLanguage=71,Strength=65,UkrainianLanguage=32 items=Underwear:White:worn,Socks:Black:worn,Pants:Blue:worn,TShirt:Gray:worn,Shoes:Black:worn,Sweater:Black:worn,FurCoat:Beige:home,Bottle:Blue:bag
|
||||
person f15.p1 Воробьёва Вера Виталиевна female=True roles=parent class=- born=1972-09-07 traits=Leader,Neat skills=Agility=42,BelarusianLanguage=40,Communication=30,Endurance=52,Hauling=46,Pedagogy=55,RussianLanguage=46,Strength=45,UkrainianLanguage=25 items=Underwear:Black:worn,Socks:Gray:worn,Pants:Black:worn,TShirt:Black:worn,WinterBoots:Black:worn,Coat:Gray:worn,Hat:Gray:worn,Scarf:Black:worn,Bottle:Blue:bag,Phone:White:bag
|
||||
person f16.c0 Фролова Елизавета Игоревна female=True roles=student class=class-classroom-02 born=2002-06-29 traits=Quiet skills=Agility=29,BelarusianLanguage=17,Biology=43,Communication=32,Endurance=19,Hauling=36,Literature=51,Mathematics=51,PhysicalEducation=68,RussianLanguage=24,Strength=45 items=Underwear:Gray:worn,Socks:Black:worn,Jeans:Blue:worn,Shirt:Blue:worn,WinterBoots:Beige:worn,Sweater:Beige:worn,FurCoat:Black:home,PeShirt:Red:home,PeShorts:Gray:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f16.p0 Фролов Игорь Виталиевич female=False roles=parent class=- born=1968-07-25 traits= skills=Administration=51,Agility=57,BelarusianLanguage=25,Communication=58,Endurance=63,Hauling=49,Medicine=53,RussianLanguage=53,Strength=46 items=Underwear:White:worn,Socks:White:worn,Pants:Gray:worn,Shirt:Gray:worn,Shoes:Gray:worn,Hat:Blue:worn,Jacket:Beige:home
|
||||
person f16.p1 Фролова Татьяна Олеговна female=True roles=parent class=- born=1970-06-17 traits=Leader,Neat skills=Agility=45,BelarusianLanguage=23,Communication=59,Endurance=59,Hauling=62,Literature=51,RussianLanguage=72,Strength=44 items=Underwear:White:worn,Socks:Black:worn,Skirt:Blue:worn,Shirt:Blue:worn,Shoes:Beige:worn,Sweater:Blue:worn,Coat:Beige:home,Bottle:Blue:bag,Phone:Black:bag
|
||||
person f17.c0 Иванов Андрей Александрович female=False roles=student class=class-classroom-03 born=2001-06-27 traits=Leader skills=Agility=60,Biology=53,Communication=54,Endurance=35,Hauling=41,Literature=65,Mathematics=38,PhysicalEducation=55,RussianLanguage=35,Strength=45,UkrainianLanguage=13 items=Underwear:White:worn,Socks:Gray:worn,Jeans:Gray:worn,Shirt:White:worn,WinterBoots:Gray:worn,Coat:Black:home,PeShirt:Green:home,PeShorts:Blue:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f17.c1 Иванова Ксения Александровна female=True roles=student class=class-classroom-02 born=2001-09-10 traits=Bully skills=Agility=45,Biology=64,Communication=28,Endurance=64,Hauling=48,Literature=47,Mathematics=37,PhysicalEducation=28,RussianLanguage=43,Strength=45 items=Underwear:White:worn,Socks:Black:worn,Pants:Black:worn,Shirt:Gray:worn,WinterBoots:Gray:worn,FurCoat:Beige:worn,Hat:Black:worn,PeShirt:Blue:home,PeShorts:Green:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f17.c2 Иванова Полина Александровна female=True roles=student class=class-classroom-03 born=2001-05-21 traits=HotTempered,Kind skills=Agility=36,Biology=43,Communication=45,Endurance=45,Hauling=47,Literature=43,Mathematics=33,PhysicalEducation=58,RussianLanguage=36,Strength=45,UkrainianLanguage=15 items=Underwear:Gray:worn,Socks:Black:worn,Pants:Black:worn,TShirt:Beige:worn,WinterBoots:Gray:worn,Sweater:Gray:worn,Coat:Beige:worn,Belt:Beige:worn,PeShirt:Red:home,PeShorts:Gray:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f17.p0 Иванов Александр Владимирович female=False roles=parent class=- born=1967-12-24 traits=Diligent,HotTempered skills=Agility=47,Communication=74,Endurance=52,Hauling=55,Physics=39,RussianLanguage=27,Strength=49 items=Underwear:Black:worn,Socks:Gray:worn,Jeans:Blue:worn,TShirt:Blue:worn,WinterBoots:Black:worn,Belt:Beige:worn,FurCoat:Black:home
|
||||
person f17.p1 Иванова Александра Ивановна female=True roles=parent class=- born=1967-04-25 traits= skills=Agility=40,Communication=69,Endurance=63,Hauling=35,RussianLanguage=56,Strength=68,UkrainianLanguage=19 items=Underwear:White:worn,Socks:White:worn,Pants:Beige:worn,Shirt:Blue:worn,Shoes:Beige:worn,FurCoat:Gray:home,Phone:White:bag
|
||||
person f18.c0 Лебедев Александр Валериевич female=False roles=student class=class-classroom-00 born=2004-02-16 traits=Curious skills=Agility=26,Biology=50,Communication=9,Endurance=53,Hauling=33,Literature=55,Mathematics=20,PhysicalEducation=56,RussianLanguage=23,Strength=35 items=Underwear:Black:worn,Socks:Black:worn,Pants:Black:worn,Shirt:White:worn,WinterBoots:Beige:worn,Sweater:Beige:worn,Jacket:Blue:worn,Belt:Gray:worn,PeShirt:Blue:home,PeShorts:Green:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f18.p0 Лебедев Валерий Романович female=False roles=parent class=- born=1985-03-29 traits=Neat,Quiet skills=Agility=25,Chemistry=56,Communication=59,Endurance=35,English=49,Geography=50,Hauling=35,Pedagogy=51,RussianLanguage=67,Strength=62 items=Underwear:Gray:worn,Socks:Black:worn,Pants:Black:worn,Shirt:Gray:worn,Shoes:Beige:worn,FurCoat:Gray:worn,Belt:Beige:worn,Bottle:Green:bag
|
||||
person f18.p1 Лебедева Юлия Михаиловна female=True roles=parent class=- born=1981-01-26 traits= skills=Administration=54,Agility=59,BelarusianLanguage=36,Biology=68,Communication=52,Endurance=44,Hauling=67,Mathematics=47,Medicine=37,RussianLanguage=48,Strength=45,UkrainianLanguage=22 items=Underwear:Gray:worn,Socks:White:worn,Dress:Black:worn,Shoes:Gray:worn,Sweater:Gray:worn,Hat:Black:worn,Belt:Black:worn,Jacket:Gray:home,Phone:Black:bag
|
||||
person f19.c0 Воробьёв Григорий Михаилович female=False roles=student class=class-classroom-00 born=2004-08-29 traits=Quiet skills=Agility=62,BelarusianLanguage=31,Biology=42,Communication=36,Endurance=50,Hauling=39,Literature=34,Mathematics=37,PhysicalEducation=50,RussianLanguage=33,Strength=45,UkrainianLanguage=23 items=Underwear:Black:worn,Socks:White:worn,Pants:Blue:worn,Shirt:Blue:worn,Shoes:Gray:worn,Sweater:Black:worn,Coat:Gray:worn,PeShirt:Blue:home,PeShorts:Black:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f19.p0 Воробьёв Михаил Егорович female=False roles=parent class=- born=1978-11-03 traits=Lazy skills=Administration=53,Agility=40,Communication=56,Endurance=46,Hauling=41,Librarianship=66,Mathematics=36,RussianLanguage=45,Strength=55 items=Underwear:Black:worn,Socks:Black:worn,Pants:Black:worn,Shirt:Black:worn,Shoes:Beige:worn,Hat:Black:worn,Jacket:Green:home,Bottle:Blue:bag
|
||||
person f19.p1 Воробьёва Вера Алексеевна female=True roles=parent class=- born=1982-08-29 traits=AbsentMinded,Lazy skills=Administration=50,Agility=58,BelarusianLanguage=20,Communication=46,Endurance=30,Hauling=50,PhysicalEducation=66,RussianLanguage=49,Strength=40,UkrainianLanguage=25 items=Underwear:Gray:worn,Socks:Gray:worn,Dress:Black:worn,WinterBoots:Black:worn,Jacket:Red:home
|
||||
person f2.c0 Алексеев Григорий Константинович female=False roles=student class=class-classroom-02 born=2002-07-24 traits=Neat skills=Agility=40,BelarusianLanguage=36,Biology=64,Communication=34,Endurance=57,Hauling=38,Literature=58,Mathematics=41,PhysicalEducation=47,RussianLanguage=28,Strength=45,UkrainianLanguage=23 items=Underwear:White:worn,Socks:Gray:worn,Jeans:Blue:worn,TShirt:Black:worn,Shoes:Black:worn,FurCoat:Gray:home,PeShirt:Red:home,PeShorts:Red:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f2.p0 Алексеев Константин Романович female=False roles=parent class=- born=1974-12-11 traits=Neat skills=Agility=36,BelarusianLanguage=23,Communication=60,Endurance=49,English=34,Hauling=47,Mathematics=63,Medicine=81,Pedagogy=74,RussianLanguage=56,Strength=59,UkrainianLanguage=22 items=Underwear:Gray:worn,Socks:White:worn,Pants:Beige:worn,Shirt:Black:worn,WinterBoots:Beige:worn,Sweater:Black:worn,Hat:Black:worn,FurCoat:Gray:home
|
||||
person f2.p1 Алексеева Ольга Романовна female=True roles=parent class=- born=1970-07-22 traits=Neat skills=Agility=50,Communication=58,Cooking=51,Endurance=43,English=55,Hauling=54,Literature=35,Medicine=76,PhysicalEducation=32,RussianLanguage=38,Strength=42 items=Underwear:Black:worn,Socks:White:worn,Skirt:Gray:worn,TShirt:Blue:worn,Shoes:Beige:worn,Sweater:Gray:worn,Coat:Beige:home,Bottle:White:bag
|
||||
person f20.c0 Павлова Елена Игоревна female=True roles=student class=class-classroom-01 born=2002-11-09 traits= skills=Agility=55,Biology=47,Communication=19,Endurance=51,Hauling=38,Literature=41,Mathematics=34,PhysicalEducation=49,RussianLanguage=44,Strength=42,UkrainianLanguage=20 items=Underwear:White:worn,Socks:Gray:worn,Pants:Black:worn,TShirt:Blue:worn,WinterBoots:Beige:worn,Hat:Beige:worn,Belt:Gray:worn,Coat:Gray:home,PeShirt:Red:home,PeShorts:Gray:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f20.c1 Павлова Валентина Игоревна female=True roles=student class=class-classroom-03 born=2001-01-24 traits=Kind skills=Agility=68,BelarusianLanguage=12,Biology=41,Communication=31,Endurance=58,Hauling=46,Literature=42,Mathematics=19,PhysicalEducation=50,RussianLanguage=45,Strength=42,UkrainianLanguage=9 items=Underwear:White:worn,Socks:Black:worn,Trousers:Gray:worn,TShirt:Blue:worn,Shoes:Black:worn,Sweater:Blue:worn,FurCoat:Beige:home,PeShirt:Green:home,PeShorts:Blue:home,Bottle:Green:bag,Phone:Black:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f20.p0 Павлов Игорь Никитич female=False roles=parent class=- born=1968-08-01 traits=HotTempered,Leader skills=Administration=61,Agility=72,Communication=57,Endurance=43,Geography=61,German=73,Hauling=44,Pedagogy=56,RussianLanguage=66,Strength=42,UkrainianLanguage=28 items=Underwear:Black:worn,Socks:White:worn,Trousers:Black:worn,TShirt:Blue:worn,WinterBoots:Gray:worn,FurCoat:Black:home,Bottle:White:bag
|
||||
person f20.p1 Павлова Людмила Дмитриевна female=True roles=parent class=- born=1970-01-17 traits=Curious,Quiet skills=Agility=46,BelarusianLanguage=26,Communication=71,Endurance=39,English=31,Hauling=36,Physics=48,RussianLanguage=53,Strength=56 items=Underwear:White:worn,Socks:Gray:worn,Dress:Beige:worn,WinterBoots:Beige:worn,Hat:Black:worn,Belt:Beige:worn,Coat:Gray:home,Bottle:White:bag
|
||||
person f21.c0 Ильин Андрей Константинович female=False roles=student class=class-classroom-02 born=2002-05-12 traits= skills=Agility=54,BelarusianLanguage=15,Biology=72,Communication=22,Endurance=54,Hauling=58,Literature=58,Mathematics=45,PhysicalEducation=52,RussianLanguage=38,Strength=45,UkrainianLanguage=25 items=Underwear:Black:worn,Socks:Black:worn,Jeans:Black:worn,TShirt:White:worn,WinterBoots:Black:worn,Sweater:Black:worn,Jacket:Black:worn,PeShirt:Gray:home,PeShorts:Blue:home,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f21.p0 Ильин Константин Никитич female=False roles=parent class=- born=1971-01-21 traits=Diligent,Quiet skills=Agility=45,Biology=50,Communication=53,Endurance=40,English=46,Hauling=45,History=42,Librarianship=57,RussianLanguage=68,Strength=40,UkrainianLanguage=9 items=Underwear:Gray:worn,Socks:Black:worn,Trousers:Black:worn,Shirt:Black:worn,Shoes:White:worn,Scarf:Black:worn,FurCoat:Beige:home,Bottle:Blue:bag
|
||||
person f21.p1 Ильина Яна Борисовна female=True roles=parent class=- born=1975-04-20 traits=Lazy skills=Agility=74,BelarusianLanguage=26,Biology=41,Communication=54,Endurance=55,English=77,Hauling=35,Librarianship=44,Medicine=57,RussianLanguage=35,Strength=50,UkrainianLanguage=23 items=Underwear:Black:worn,Socks:White:worn,Jeans:Gray:worn,Shirt:Gray:worn,WinterBoots:Gray:worn,Coat:Gray:worn,Bottle:Blue:bag
|
||||
person f22.c0 Захаров Никита Виталиевич female=False roles=student class=class-classroom-03 born=2000-09-14 traits= skills=Agility=62,BelarusianLanguage=19,Biology=50,Communication=42,Endurance=39,Hauling=47,Literature=68,Mathematics=65,PhysicalEducation=60,RussianLanguage=59,Strength=45,UkrainianLanguage=31 items=Underwear:Gray:worn,Socks:White:worn,Jeans:Gray:worn,TShirt:Beige:worn,Shoes:Beige:worn,FurCoat:Gray:home,PeShirt:Black:home,PeShorts:Blue:home,Bottle:White:bag,Phone:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f22.c1 Захаров Денис Виталиевич female=False roles=student class=class-classroom-02 born=2001-09-11 traits=Kind,Leader skills=Agility=51,Biology=42,Communication=55,Endurance=51,Hauling=69,Literature=53,Mathematics=60,PhysicalEducation=80,RussianLanguage=50,Strength=53,UkrainianLanguage=16 items=Underwear:White:worn,Socks:White:worn,Trousers:Blue:worn,TShirt:Blue:worn,Shoes:White:worn,Hat:Blue:worn,Coat:Beige:home,PeShirt:Red:home,PeShorts:Red:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f22.p0 Захаров Виталий Андреевич female=False roles=parent class=- born=1966-04-08 traits= skills=Agility=29,Communication=62,Endurance=82,Hauling=33,RussianLanguage=65,Strength=58,UkrainianLanguage=18 items=Underwear:Black:worn,Socks:Black:worn,Pants:Beige:worn,TShirt:LightBlue:worn,Shoes:Black:worn,Coat:Black:worn,Hat:Gray:worn,Bottle:White:bag,Phone:Black:bag
|
||||
person f22.p1 Захарова Елизавета Егоровна female=True roles=parent class=- born=1967-09-05 traits= skills=Administration=37,Agility=42,BelarusianLanguage=28,Communication=82,Cooking=65,Endurance=60,English=52,Hauling=37,Mathematics=67,RussianLanguage=54,Strength=51 items=Underwear:Gray:worn,Socks:White:worn,Dress:Gray:worn,WinterBoots:Gray:worn,FurCoat:Gray:home,Bottle:Green:bag
|
||||
person f23.c0 Орловская Нина Константиновна female=True roles=student class=class-classroom-02 born=2001-11-01 traits=AbsentMinded,Quiet skills=Agility=44,BelarusianLanguage=13,Biology=42,Communication=9,Endurance=51,Hauling=45,Literature=53,Mathematics=34,PhysicalEducation=70,RussianLanguage=46,Strength=38 items=Underwear:White:worn,Socks:White:worn,Trousers:Blue:worn,TShirt:Blue:worn,Shoes:Beige:worn,Sweater:Blue:worn,Coat:Beige:worn,Hat:Gray:worn,PeShirt:Blue:home,PeShorts:Red:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f23.c1 Орловская Полина Константиновна female=True roles=student class=class-classroom-01 born=2003-03-30 traits=Curious,Quiet skills=Agility=39,BelarusianLanguage=20,Biology=70,Communication=19,Endurance=53,Hauling=54,Literature=73,Mathematics=46,PhysicalEducation=55,RussianLanguage=47,Strength=67 items=Underwear:White:worn,Socks:Black:worn,Dress:Blue:worn,Shoes:Black:worn,Sweater:Beige:worn,Jacket:Red:home,PeShirt:Black:home,PeShorts:Gray:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f23.p0 Орловский Константин Михаилович female=False roles=parent class=- born=1965-04-02 traits=Diligent,HotTempered skills=Agility=45,BelarusianLanguage=23,Communication=55,Endurance=50,Hauling=50,History=40,Librarianship=56,Physics=61,RussianLanguage=52,Strength=32,UkrainianLanguage=17 items=Underwear:Gray:worn,Socks:White:worn,Jeans:Gray:worn,Shirt:Blue:worn,WinterBoots:Beige:worn,FurCoat:Black:worn,Hat:Beige:worn
|
||||
person f23.p1 Орловская Яна Степановна female=True roles=parent class=- born=1965-10-22 traits=Lazy skills=Agility=56,BelarusianLanguage=28,Communication=44,Endurance=40,Hauling=81,Pedagogy=45,RussianLanguage=62,Strength=56,UkrainianLanguage=26 items=Underwear:Gray:worn,Socks:Gray:worn,Pants:Gray:worn,TShirt:Blue:worn,Shoes:White:worn,Hat:Blue:worn,Coat:Black:home
|
||||
person f24.c0 Орлов Фёдор Алексеевич female=False roles=student class=class-classroom-03 born=2000-12-05 traits=Neat skills=Agility=40,BelarusianLanguage=8,Biology=54,Communication=6,Endurance=40,Hauling=45,Literature=41,Mathematics=10,PhysicalEducation=46,RussianLanguage=52,Strength=63 items=Underwear:Black:worn,Socks:Black:worn,Jeans:Gray:worn,Shirt:Black:worn,Shoes:Gray:worn,Sweater:Black:worn,Jacket:Blue:worn,PeShirt:Blue:home,PeShorts:Blue:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f24.c1 Орлова Оксана Алексеевна female=True roles=student class=class-classroom-00 born=2004-03-01 traits=Kind,Lazy skills=Agility=75,Biology=30,Communication=23,Endurance=54,Hauling=35,Literature=62,Mathematics=43,PhysicalEducation=50,RussianLanguage=26,Strength=41,UkrainianLanguage=31 items=Underwear:Black:worn,Socks:White:worn,Pants:Beige:worn,TShirt:White:worn,WinterBoots:Black:worn,Scarf:Beige:worn,Jacket:Red:home,PeShirt:Black:home,PeShorts:Red:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f24.p0 Орлов Алексей Денисович female=False roles=parent class=- born=1977-04-17 traits= skills=Agility=45,BelarusianLanguage=17,Communication=51,Endurance=18,English=61,Hauling=46,Literature=56,Mathematics=60,RussianLanguage=55,Strength=62,UkrainianLanguage=16 items=Underwear:Black:worn,Socks:Black:worn,Trousers:Gray:worn,Shirt:Gray:worn,WinterBoots:Black:worn,Sweater:Black:worn,Hat:Gray:worn,Jacket:Black:home
|
||||
person f24.p1 Орлова Надежда Владиславовна female=True roles=parent class=- born=1977-12-04 traits=Kind skills=Agility=25,BelarusianLanguage=25,Communication=52,Endurance=22,English=70,Hauling=52,Librarianship=51,Medicine=10,RussianLanguage=50,Strength=52,UkrainianLanguage=19 items=Underwear:Black:worn,Socks:Gray:worn,Trousers:Blue:worn,TShirt:LightBlue:worn,WinterBoots:Gray:worn,Sweater:Black:worn,FurCoat:Black:worn,Belt:Black:worn,Bottle:Blue:bag,Phone:Black:bag
|
||||
person f25.c0 Петрова Александра Игоревна female=True roles=student class=class-classroom-02 born=2001-12-19 traits= skills=Agility=57,BelarusianLanguage=29,Biology=64,Communication=32,Endurance=40,Hauling=58,Literature=47,Mathematics=40,PhysicalEducation=79,RussianLanguage=64,Strength=65,UkrainianLanguage=7 items=Underwear:White:worn,Socks:White:worn,Trousers:Black:worn,TShirt:Blue:worn,WinterBoots:Black:worn,Sweater:Gray:worn,Coat:Beige:worn,Hat:Beige:worn,Scarf:Beige:worn,PeShirt:Red:home,PeShorts:Blue:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f25.p1 Петрова Полина Юриевна female=True roles=parent class=- born=1965-12-11 traits=Kind,Neat skills=Agility=53,Communication=50,Endurance=59,English=70,Geography=41,Hauling=56,Medicine=42,RussianLanguage=72,Strength=45 items=Underwear:Gray:worn,Socks:White:worn,Pants:Beige:worn,TShirt:LightBlue:worn,WinterBoots:Beige:worn,Coat:Beige:worn,Hat:Black:worn,Bottle:White:bag
|
||||
person f26.c0 Яковлев Павел Михаилович female=False roles=student class=class-classroom-01 born=2002-12-29 traits=Kind,Neat skills=Agility=45,BelarusianLanguage=30,Biology=59,Communication=8,Endurance=59,Hauling=53,Literature=60,Mathematics=47,PhysicalEducation=43,RussianLanguage=43,Strength=45,UkrainianLanguage=23 items=Underwear:White:worn,Socks:White:worn,Pants:Beige:worn,TShirt:LightBlue:worn,Shoes:Black:worn,Sweater:Blue:worn,Coat:Beige:worn,PeShirt:Gray:home,PeShorts:Red:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f26.c1 Яковлев Вадим Михаилович female=False roles=student class=class-classroom-00 born=2004-06-28 traits= skills=Agility=40,BelarusianLanguage=24,Biology=36,Communication=14,Endurance=66,Hauling=41,Literature=71,Mathematics=26,PhysicalEducation=55,RussianLanguage=25,Strength=40,UkrainianLanguage=18 items=Underwear:Black:worn,Socks:Black:worn,Jeans:Blue:worn,TShirt:Black:worn,Shoes:Black:worn,FurCoat:Black:home,PeShirt:Blue:home,PeShorts:Red:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f26.p0 Яковлев Михаил Степанович female=False roles=parent class=- born=1975-12-27 traits=HotTempered,Neat skills=Agility=44,Communication=59,Endurance=66,Hauling=52,Mathematics=44,Medicine=71,PhysicalEducation=53,RussianLanguage=55,Strength=45,UkrainianLanguage=28 items=Underwear:Black:worn,Socks:Black:worn,Jeans:Blue:worn,TShirt:Black:worn,Shoes:Gray:worn,Scarf:Blue:worn,Jacket:Blue:home,Phone:Gray:bag
|
||||
person f26.p1 Яковлева Марина Кирилловна female=True roles=parent class=- born=1976-12-10 traits=Diligent,Neat skills=Agility=36,BelarusianLanguage=22,Communication=53,Endurance=66,English=40,Hauling=47,History=43,Medicine=66,PhysicalEducation=45,RussianLanguage=65,Strength=43 items=Underwear:White:worn,Socks:White:worn,Jeans:Black:worn,TShirt:Gray:worn,WinterBoots:Black:worn,FurCoat:Gray:worn,Bottle:Blue:bag,Phone:Gray:bag
|
||||
person f27.c0 Иванов Виктор Константинович female=False roles=student class=class-classroom-01 born=2002-12-27 traits=Bully skills=Agility=29,BelarusianLanguage=19,Biology=56,Communication=26,Endurance=46,Hauling=65,Literature=45,Mathematics=53,PhysicalEducation=58,RussianLanguage=27,Strength=45,UkrainianLanguage=22 items=Underwear:Black:worn,Socks:Gray:worn,Pants:Gray:worn,TShirt:Gray:worn,Shoes:Beige:worn,FurCoat:Black:worn,PeShirt:Gray:home,PeShorts:Red:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f27.c1 Иванов Владислав Константинович female=False roles=student class=class-classroom-00 born=2004-07-04 traits=Diligent,Neat skills=Agility=38,BelarusianLanguage=23,Biology=27,Communication=31,Endurance=53,Hauling=65,Literature=62,Mathematics=33,PhysicalEducation=64,RussianLanguage=49,Strength=53 items=Underwear:White:worn,Socks:White:worn,Trousers:Black:worn,Shirt:Gray:worn,WinterBoots:Black:worn,Sweater:Blue:worn,Jacket:Gray:worn,Hat:Gray:worn,Scarf:Blue:worn,PeShirt:Blue:home,PeShorts:Green:home,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f27.c2 Иванов Александр Константинович female=False roles=student class=class-classroom-00 born=2004-05-25 traits= skills=Agility=58,Biology=51,Communication=37,Endurance=60,Hauling=37,Literature=65,Mathematics=35,PhysicalEducation=33,RussianLanguage=42,Strength=45,UkrainianLanguage=38 items=Underwear:Black:worn,Socks:Black:worn,Pants:Black:worn,TShirt:White:worn,WinterBoots:Beige:worn,Sweater:Black:worn,Hat:Beige:worn,Scarf:Blue:worn,FurCoat:Gray:home,PeShirt:Blue:home,PeShorts:Black:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f27.p0 Иванов Константин Иванович female=False roles=parent class=- born=1974-08-25 traits=Neat skills=Agility=44,BelarusianLanguage=27,Communication=77,Endurance=42,English=53,Hauling=62,Medicine=52,Pedagogy=40,RussianLanguage=32,Strength=28 items=Underwear:Black:worn,Socks:Black:worn,Trousers:Blue:worn,Shirt:Blue:worn,Shoes:Gray:worn,Sweater:Blue:worn,Scarf:Beige:worn,Jacket:Green:home,Bottle:White:bag,Phone:White:bag
|
||||
person f27.p1 Иванова Марина Константиновна female=True roles=parent class=- born=1969-11-29 traits=Curious skills=Agility=43,BelarusianLanguage=16,Communication=71,Endurance=63,English=50,Hauling=59,RussianLanguage=56,Strength=35,UkrainianLanguage=21 items=Underwear:Black:worn,Socks:Gray:worn,Skirt:Beige:worn,TShirt:Black:worn,WinterBoots:Beige:worn,Sweater:Black:worn,FurCoat:Beige:worn,Bottle:Green:bag,Phone:Black:bag
|
||||
person f28.c0 Иванов Пётр Петрович female=False roles=student class=class-classroom-02 born=2002-08-02 traits= skills=Agility=43,BelarusianLanguage=34,Biology=36,Communication=42,Endurance=50,Hauling=36,Literature=33,Mathematics=4,PhysicalEducation=78,RussianLanguage=46,Strength=44 items=Underwear:Gray:worn,Socks:White:worn,Pants:Beige:worn,Shirt:Gray:worn,WinterBoots:Black:worn,Sweater:Blue:worn,Jacket:Red:home,PeShirt:Green:home,PeShorts:Green:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f28.c1 Иванова Наталья Петровна female=True roles=student class=class-classroom-03 born=2000-12-07 traits=Quiet skills=Agility=58,BelarusianLanguage=30,Biology=46,Communication=52,Endurance=36,Hauling=58,Literature=38,Mathematics=73,PhysicalEducation=77,RussianLanguage=51,Strength=45,UkrainianLanguage=23 items=Underwear:White:worn,Socks:Gray:worn,Pants:Beige:worn,TShirt:Gray:worn,Shoes:Beige:worn,Hat:Black:worn,Coat:Beige:home,PeShirt:Green:home,PeShorts:Gray:home,Phone:Black:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f28.c2 Иванов Максим Петрович female=False roles=student class=class-classroom-00 born=2004-04-05 traits=Lazy skills=Agility=67,BelarusianLanguage=23,Biology=32,Communication=26,Endurance=54,Hauling=51,Literature=57,Mathematics=10,PhysicalEducation=57,RussianLanguage=47,Strength=75,UkrainianLanguage=35 items=Underwear:Black:worn,Socks:Gray:worn,Pants:Beige:worn,TShirt:Black:worn,Shoes:Gray:worn,Sweater:Gray:worn,Scarf:Black:worn,Coat:Black:home,PeShirt:Black:home,PeShorts:Red:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f28.p0 Иванов Пётр Олегович female=False roles=parent class=- born=1965-06-23 traits=AbsentMinded,Kind skills=Agility=75,BelarusianLanguage=24,Biology=51,Communication=60,Cooking=51,Endurance=74,English=57,Geography=66,Hauling=48,RussianLanguage=45,Strength=40,UkrainianLanguage=36 items=Underwear:Black:worn,Socks:Gray:worn,Trousers:Black:worn,Shirt:White:worn,Shoes:White:worn,Sweater:Black:worn,Coat:Gray:worn,Hat:Black:worn,Scarf:Black:worn
|
||||
person f28.p1 Иванова Полина Алексеевна female=True roles=parent class=- born=1965-11-18 traits=AbsentMinded,Leader skills=Agility=43,Communication=61,Cooking=49,Endurance=43,Hauling=60,RussianLanguage=46,Strength=45 items=Underwear:White:worn,Socks:White:worn,Dress:Beige:worn,WinterBoots:Gray:worn,Hat:Beige:worn,Belt:Black:worn,FurCoat:Gray:home,Bottle:Green:bag,Phone:Black:bag
|
||||
person f29.c0 Макарова Ксения Александровна female=True roles=student class=class-classroom-01 born=2002-11-08 traits=AbsentMinded,HotTempered skills=Agility=52,Biology=73,Communication=35,Endurance=53,Hauling=68,Literature=64,Mathematics=28,PhysicalEducation=67,RussianLanguage=18,Strength=45 items=Underwear:Gray:worn,Socks:White:worn,Pants:Blue:worn,TShirt:Gray:worn,WinterBoots:Black:worn,Jacket:Black:worn,Hat:Blue:worn,Belt:Beige:worn,PeShirt:Gray:home,PeShorts:Blue:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f29.p0 Макаров Александр Николаевич female=False roles=parent class=- born=1981-11-08 traits=AbsentMinded skills=Agility=50,BelarusianLanguage=34,Communication=44,Endurance=55,Hauling=42,Informatics=34,PhysicalEducation=74,RussianLanguage=54,Strength=64,UkrainianLanguage=10 items=Underwear:Black:worn,Socks:White:worn,Jeans:Blue:worn,Shirt:Blue:worn,WinterBoots:Black:worn,Sweater:Gray:worn,Coat:Black:worn,Hat:Gray:worn,Scarf:Black:worn,Bottle:Blue:bag,Phone:Black:bag
|
||||
person f29.p1 Макарова Мария Владиславовна female=True roles=parent class=- born=1977-10-31 traits=Curious,Diligent skills=Administration=44,Agility=44,BelarusianLanguage=8,Communication=56,Endurance=62,English=40,Hauling=44,Medicine=15,RussianLanguage=41,Strength=52 items=Underwear:White:worn,Socks:Black:worn,Trousers:Black:worn,Shirt:Blue:worn,Shoes:Beige:worn,Sweater:Black:worn,Hat:Blue:worn,Coat:Black:home,Bottle:White:bag,Phone:White:bag
|
||||
person f3.c0 Макарова Вероника Петровна female=True roles=student class=class-classroom-02 born=2002-05-15 traits= skills=Agility=68,BelarusianLanguage=24,Biology=34,Communication=45,Endurance=50,Hauling=48,Literature=37,Mathematics=41,PhysicalEducation=50,RussianLanguage=28,Strength=45,UkrainianLanguage=23 items=Underwear:Gray:worn,Socks:Black:worn,Trousers:Blue:worn,Shirt:Gray:worn,WinterBoots:Gray:worn,Jacket:Black:home,PeShirt:Gray:home,PeShorts:Blue:home,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f3.c1 Макаров Роман Петрович female=False roles=student class=class-classroom-02 born=2002-04-16 traits=Lazy skills=Agility=50,BelarusianLanguage=22,Biology=59,Communication=22,Endurance=46,Hauling=51,Literature=39,Mathematics=17,PhysicalEducation=37,RussianLanguage=31,Strength=45,UkrainianLanguage=23 items=Underwear:Gray:worn,Socks:Black:worn,Jeans:Blue:worn,Shirt:White:worn,WinterBoots:Black:worn,Hat:Beige:worn,Coat:Black:home,PeShirt:Black:home,PeShorts:Black:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f3.p0 Макаров Пётр Егорович female=False roles=parent class=- born=1977-02-28 traits=Diligent,Neat skills=Agility=67,Communication=28,Endurance=53,English=57,Hauling=43,History=43,Pedagogy=54,RussianLanguage=43,Strength=40 items=Underwear:Black:worn,Socks:White:worn,Pants:Gray:worn,Shirt:Blue:worn,WinterBoots:Black:worn,Sweater:Beige:worn,Hat:Beige:worn,Coat:Black:home
|
||||
person f3.p1 Макарова Алина Антоновна female=True roles=parent class=- born=1978-04-05 traits=Kind,Neat skills=Agility=45,BelarusianLanguage=20,Biology=41,Communication=45,Cooking=68,Endurance=51,English=54,Hauling=52,History=69,Medicine=78,RussianLanguage=63,Strength=44 items=Underwear:Black:worn,Socks:Black:worn,Jeans:Black:worn,TShirt:Gray:worn,WinterBoots:Gray:worn,Sweater:Gray:worn,Hat:Beige:worn,FurCoat:Beige:home,Phone:Black:bag
|
||||
person f30.c0 Иванова Светлана Владимировна female=True roles=student class=class-classroom-03 born=2000-10-08 traits=Leader skills=Agility=43,Biology=53,Communication=26,Endurance=44,Hauling=49,Literature=68,Mathematics=39,PhysicalEducation=73,RussianLanguage=51,Strength=36,UkrainianLanguage=21 items=Underwear:White:worn,Socks:Black:worn,Pants:Blue:worn,Shirt:Gray:worn,Shoes:Gray:worn,Coat:Black:worn,Hat:Blue:worn,Scarf:Gray:worn,PeShirt:Gray:home,PeShorts:Black:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f30.c1 Иванова Надежда Владимировна female=True roles=student class=class-classroom-03 born=2000-12-10 traits=AbsentMinded,Lazy skills=Agility=43,BelarusianLanguage=19,Biology=57,Communication=38,Endurance=66,Hauling=46,Literature=70,Mathematics=17,PhysicalEducation=48,RussianLanguage=41,Strength=40,UkrainianLanguage=10 items=Underwear:White:worn,Socks:Black:worn,Pants:Black:worn,Shirt:White:worn,Shoes:Black:worn,Scarf:Beige:worn,Jacket:Blue:home,PeShirt:Blue:home,PeShorts:Red:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f30.p0 Иванов Владимир Денисович female=False roles=parent class=- born=1974-06-12 traits=Lazy skills=Agility=40,Biology=17,Communication=72,Cooking=61,Endurance=50,Hauling=32,RussianLanguage=58,Strength=40,UkrainianLanguage=26 items=Underwear:Black:worn,Socks:Black:worn,Trousers:Black:worn,Shirt:Gray:worn,WinterBoots:Gray:worn,Coat:Beige:home,Bottle:Blue:bag
|
||||
person f30.p1 Иванова Мария Андреевна female=True roles=parent class=- born=1973-09-24 traits=Diligent skills=Agility=52,BelarusianLanguage=40,Communication=61,Endurance=62,Hauling=65,Medicine=47,RussianLanguage=43,Strength=39 items=Underwear:White:worn,Socks:Gray:worn,Skirt:Black:worn,Shirt:Blue:worn,Shoes:Gray:worn,Hat:Beige:worn,Jacket:Blue:home,Phone:Gray:bag
|
||||
person f31.c0 Иванов Николай Вадимович female=False roles=student class=class-classroom-01 born=2003-08-29 traits= skills=Agility=20,BelarusianLanguage=24,Biology=40,Communication=27,Endurance=43,Hauling=46,Literature=36,Mathematics=40,PhysicalEducation=53,RussianLanguage=32,Strength=73,UkrainianLanguage=20 items=Underwear:Gray:worn,Socks:White:worn,Jeans:Black:worn,TShirt:Beige:worn,WinterBoots:Beige:worn,FurCoat:Black:home,PeShirt:Blue:home,PeShorts:Black:home,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f31.p0 Иванов Вадим Андреевич female=False roles=parent class=- born=1985-06-23 traits=Diligent,Quiet skills=Administration=28,Agility=45,BelarusianLanguage=32,Communication=54,Endurance=71,English=55,German=47,Hauling=53,PhysicalEducation=44,RussianLanguage=70,Strength=44,UkrainianLanguage=17 items=Underwear:White:worn,Socks:White:worn,Jeans:Black:worn,Shirt:Black:worn,Shoes:Black:worn,Hat:Blue:worn,Coat:Gray:home,Bottle:Blue:bag,Phone:Gray:bag
|
||||
person f31.p1 Иванова Александра Юриевна female=True roles=parent class=- born=1980-08-20 traits=Diligent,HotTempered skills=Agility=70,BelarusianLanguage=29,Communication=50,Endurance=41,English=50,Hauling=51,Librarianship=35,PhysicalEducation=73,Physics=54,RussianLanguage=59,Strength=62,UkrainianLanguage=23 items=Underwear:Black:worn,Socks:Black:worn,Pants:Black:worn,TShirt:Gray:worn,Shoes:Black:worn,Jacket:Black:worn,Hat:Black:worn,Scarf:Blue:worn,Phone:Gray:bag
|
||||
person f32.c0 Петров Артём Евгениевич female=False roles=student class=class-classroom-02 born=2002-07-14 traits=Neat skills=Agility=78,Biology=58,Communication=47,Endurance=32,Hauling=19,Literature=31,Mathematics=29,PhysicalEducation=60,RussianLanguage=65,Strength=18,UkrainianLanguage=18 items=Underwear:Black:worn,Socks:Black:worn,Trousers:Blue:worn,Shirt:Gray:worn,Shoes:Beige:worn,Sweater:Black:worn,FurCoat:Black:worn,PeShirt:Gray:home,PeShorts:Gray:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f32.c1 Петрова Елена Евгениевна female=True roles=student class=class-classroom-00 born=2003-10-27 traits=AbsentMinded,HotTempered skills=Agility=37,Biology=54,Communication=39,Endurance=60,Hauling=53,Literature=58,Mathematics=33,PhysicalEducation=75,RussianLanguage=34,Strength=42,UkrainianLanguage=30 items=Underwear:Gray:worn,Socks:Black:worn,Pants:Blue:worn,TShirt:White:worn,Shoes:Gray:worn,Coat:Black:worn,Hat:Gray:worn,Belt:Gray:worn,PeShirt:Blue:home,PeShorts:Green:home,Bottle:Green:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f32.c2 Петрова Ирина Евгениевна female=True roles=student class=class-classroom-02 born=2001-09-18 traits=Kind,Quiet skills=Agility=41,BelarusianLanguage=32,Biology=80,Communication=32,Endurance=42,Hauling=67,Literature=51,Mathematics=26,PhysicalEducation=33,RussianLanguage=32,Strength=45 items=Underwear:White:worn,Socks:White:worn,Dress:Beige:worn,WinterBoots:Black:worn,Sweater:Black:worn,Jacket:Beige:worn,Belt:Gray:worn,PeShirt:Black:home,PeShorts:Blue:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f32.p0 Петров Евгений Станиславович female=False roles=parent class=- born=1963-05-02 traits= skills=Agility=45,Communication=66,Endurance=43,English=53,Hauling=42,PhysicalEducation=51,RussianLanguage=62,Strength=52,UkrainianLanguage=26 items=Underwear:Black:worn,Socks:White:worn,Jeans:Black:worn,Shirt:Black:worn,Shoes:White:worn,Sweater:Black:worn,Belt:Beige:worn,Coat:Beige:home,Bottle:Blue:bag
|
||||
person f33.c0 Морозова Елизавета Григориевна female=True roles=student class=class-classroom-00 born=2003-11-04 traits=AbsentMinded,Lazy skills=Agility=59,BelarusianLanguage=25,Biology=55,Communication=45,Endurance=48,Hauling=50,Literature=58,Mathematics=0,PhysicalEducation=54,RussianLanguage=28,Strength=38,UkrainianLanguage=26 items=Underwear:Gray:worn,Socks:Black:worn,Skirt:Gray:worn,TShirt:White:worn,Shoes:Beige:worn,Sweater:Blue:worn,Hat:Blue:worn,Scarf:Gray:worn,Coat:Gray:home,PeShirt:Gray:home,PeShorts:Green:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f33.p0 Морозов Григорий Михаилович female=False roles=parent class=- born=1968-05-01 traits= skills=Agility=28,BelarusianLanguage=8,Communication=68,Endurance=62,Hauling=51,Pedagogy=72,RussianLanguage=56,Strength=46,UkrainianLanguage=22 items=Underwear:Gray:worn,Socks:White:worn,Trousers:Gray:worn,TShirt:Blue:worn,WinterBoots:Beige:worn,Sweater:Blue:worn,Coat:Gray:home,Phone:Black:bag
|
||||
person f33.p1 Морозова Марина Владимировна female=True roles=parent class=- born=1972-10-24 traits=Leader skills=Administration=54,Agility=41,BelarusianLanguage=28,Communication=42,Endurance=80,English=30,Geography=60,Hauling=41,PhysicalEducation=76,RussianLanguage=74,Strength=37 items=Underwear:Black:worn,Socks:White:worn,Pants:Beige:worn,Shirt:Gray:worn,WinterBoots:Black:worn,Hat:Beige:worn,Belt:Gray:worn,Jacket:Beige:home
|
||||
person f34.c0 Кузнецова Валентина Ивановна female=True roles=student class=class-classroom-00 born=2004-03-25 traits=Curious,Kind skills=Agility=29,Biology=32,Communication=21,Endurance=69,Hauling=54,Literature=58,Mathematics=28,PhysicalEducation=53,RussianLanguage=16,Strength=43,UkrainianLanguage=24 items=Underwear:Black:worn,Socks:Black:worn,Pants:Black:worn,Shirt:White:worn,Shoes:Black:worn,Sweater:Gray:worn,Jacket:Black:worn,PeShirt:Green:home,PeShorts:Red:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f34.p0 Кузнецов Иван Сергеевич female=False roles=parent class=- born=1970-02-02 traits= skills=Agility=44,Communication=43,Endurance=58,English=45,German=55,Hauling=31,Literature=54,RussianLanguage=55,Strength=72 items=Underwear:Black:worn,Socks:Black:worn,Pants:Beige:worn,Shirt:Gray:worn,WinterBoots:Gray:worn,Hat:Black:worn,Scarf:Beige:worn,Coat:Black:home
|
||||
person f34.p1 Кузнецова Дарья Валериевна female=True roles=parent class=- born=1967-03-25 traits=HotTempered skills=Agility=47,BelarusianLanguage=23,Communication=52,Endurance=52,German=38,Hauling=32,Informatics=21,RussianLanguage=56,Strength=67,UkrainianLanguage=15 items=Underwear:Black:worn,Socks:Gray:worn,Jeans:Blue:worn,Shirt:Black:worn,Shoes:Black:worn,Sweater:Gray:worn,Jacket:Blue:home,Bottle:Blue:bag,Phone:Gray:bag
|
||||
person f4.c0 Васильев Денис Федорович female=False roles=student class=class-classroom-01 born=2003-02-01 traits=Neat skills=Agility=50,BelarusianLanguage=9,Biology=58,Communication=27,Endurance=35,Hauling=25,Literature=52,Mathematics=53,PhysicalEducation=43,RussianLanguage=68,Strength=45,UkrainianLanguage=27 items=Underwear:Gray:worn,Socks:White:worn,Trousers:Black:worn,TShirt:Gray:worn,Shoes:Gray:worn,Sweater:Gray:worn,Jacket:Red:home,PeShirt:Black:home,PeShorts:Black:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f4.p0 Васильев Фёдор Игоревич female=False roles=parent class=- born=1970-05-21 traits=AbsentMinded skills=Agility=66,Communication=49,Endurance=44,English=25,Geography=47,Hauling=45,Medicine=44,RussianLanguage=45,Strength=47,UkrainianLanguage=31 items=Underwear:Black:worn,Socks:Black:worn,Jeans:Gray:worn,TShirt:LightBlue:worn,Shoes:Gray:worn,Coat:Beige:worn,Hat:Black:worn,Belt:Gray:worn,Phone:White:bag
|
||||
person f4.p1 Васильева Анастасия Федоровна female=True roles=parent class=- born=1975-01-20 traits= skills=Agility=64,BelarusianLanguage=22,Communication=59,Endurance=64,English=43,Hauling=53,Librarianship=49,Medicine=75,RussianLanguage=49,Strength=73,UkrainianLanguage=13 items=Underwear:Gray:worn,Socks:White:worn,Pants:Blue:worn,TShirt:Blue:worn,Shoes:Beige:worn,Sweater:Gray:worn,Hat:Black:worn,Coat:Gray:home,Bottle:White:bag
|
||||
person f5.c0 Захарова Екатерина Борисовна female=True roles=student class=class-classroom-02 born=2002-07-13 traits=Kind,Lazy skills=Agility=57,BelarusianLanguage=29,Biology=72,Communication=42,Endurance=39,Hauling=29,Literature=19,Mathematics=37,PhysicalEducation=60,RussianLanguage=28,Strength=54 items=Underwear:Gray:worn,Socks:Black:worn,Dress:Black:worn,WinterBoots:Gray:worn,Sweater:Beige:worn,Hat:Black:worn,Coat:Black:home,PeShirt:Blue:home,PeShorts:Black:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f5.p0 Захаров Борис Николаевич female=False roles=parent class=- born=1980-04-15 traits= skills=Agility=45,BelarusianLanguage=29,Communication=37,Cooking=51,Endurance=51,Hauling=32,Pedagogy=36,RussianLanguage=66,Strength=51,UkrainianLanguage=15 items=Underwear:Black:worn,Socks:Gray:worn,Jeans:Blue:worn,Shirt:White:worn,Shoes:Gray:worn,Scarf:Beige:worn,Jacket:Gray:home
|
||||
person f5.p1 Захарова Вероника Григориевна female=True roles=parent class=- born=1979-06-22 traits= skills=Administration=39,Agility=68,Communication=64,Endurance=40,English=31,Hauling=61,Informatics=35,PhysicalEducation=35,RussianLanguage=55,Strength=65 items=Underwear:Black:worn,Socks:White:worn,Skirt:Beige:worn,Shirt:Blue:worn,WinterBoots:Gray:worn,Sweater:Black:worn,Jacket:Gray:worn,Hat:Beige:worn
|
||||
person f6.c0 Козловская Юлия Олеговна female=True roles=student class=class-classroom-00 born=2004-08-15 traits= skills=Agility=45,Biology=49,Communication=42,Endurance=61,Hauling=67,Literature=49,Mathematics=54,PhysicalEducation=39,RussianLanguage=23,Strength=58 items=Underwear:Black:worn,Socks:White:worn,Jeans:Black:worn,Shirt:Black:worn,WinterBoots:Black:worn,Sweater:Gray:worn,Coat:Gray:worn,Hat:Blue:worn,Scarf:Black:worn,PeShirt:Gray:home,PeShorts:Green:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f6.c1 Козловская Светлана Олеговна female=True roles=student class=class-classroom-02 born=2001-12-31 traits=HotTempered,Leader skills=Agility=53,BelarusianLanguage=37,Biology=59,Communication=36,Endurance=40,Hauling=26,Literature=66,Mathematics=34,PhysicalEducation=51,RussianLanguage=53,Strength=47,UkrainianLanguage=10 items=Underwear:White:worn,Socks:Black:worn,Jeans:Gray:worn,Shirt:Black:worn,WinterBoots:Beige:worn,Coat:Black:worn,Hat:Beige:worn,PeShirt:Blue:home,PeShorts:Green:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f6.c2 Козловская Вероника Олеговна female=True roles=student class=class-classroom-00 born=2003-09-29 traits=Diligent skills=Agility=55,Biology=77,Communication=27,Endurance=56,Hauling=46,Literature=56,Mathematics=40,PhysicalEducation=46,RussianLanguage=26,Strength=49,UkrainianLanguage=25 items=Underwear:Gray:worn,Socks:Black:worn,Jeans:Black:worn,TShirt:White:worn,Shoes:White:worn,Coat:Gray:home,PeShirt:Blue:home,PeShorts:Red:home,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f6.p0 Козловский Олег Станиславович female=False roles=parent class=- born=1967-12-18 traits=Kind skills=Agility=42,Communication=82,Endurance=64,Hauling=52,Informatics=53,Literature=33,RussianLanguage=58,Strength=21 items=Underwear:Black:worn,Socks:Black:worn,Pants:Beige:worn,TShirt:White:worn,Shoes:White:worn,Sweater:Gray:worn,Coat:Beige:home,Bottle:Blue:bag
|
||||
person f6.p1 Козловская Ирина Кирилловна female=True roles=parent class=- born=1963-12-28 traits=AbsentMinded,Lazy skills=Agility=57,BelarusianLanguage=11,Communication=67,Endurance=42,English=48,Hauling=57,RussianLanguage=79,Strength=45 items=Underwear:Gray:worn,Socks:White:worn,Jeans:Gray:worn,TShirt:Gray:worn,WinterBoots:Beige:worn,Coat:Black:worn,Bottle:White:bag
|
||||
person f7.c0 Андреев Виктор Степанович female=False roles=student class=class-classroom-01 born=2003-07-19 traits=Diligent,Kind skills=Agility=50,BelarusianLanguage=27,Biology=78,Communication=24,Endurance=50,Hauling=73,Literature=51,Mathematics=34,PhysicalEducation=26,RussianLanguage=56,Strength=64,UkrainianLanguage=34 items=Underwear:Gray:worn,Socks:Black:worn,Jeans:Black:worn,Shirt:Black:worn,Shoes:Gray:worn,Belt:Beige:worn,Jacket:Red:home,PeShirt:Blue:home,PeShorts:Green:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f7.p0 Андреев Степан Андреевич female=False roles=parent class=- born=1973-08-21 traits= skills=Agility=64,Communication=76,Endurance=36,English=60,Hauling=46,History=47,Literature=57,RussianLanguage=64,Strength=62,UkrainianLanguage=27 items=Underwear:Black:worn,Socks:White:worn,Jeans:Gray:worn,Shirt:Black:worn,Shoes:White:worn,Sweater:Black:worn,Hat:Beige:worn,FurCoat:Gray:home
|
||||
person f7.p1 Андреева Мария Алексеевна female=True roles=parent class=- born=1977-07-16 traits=HotTempered skills=Agility=35,BelarusianLanguage=18,Communication=56,Cooking=47,Endurance=45,Hauling=56,Medicine=47,RussianLanguage=58,Strength=64 items=Underwear:Gray:worn,Socks:Black:worn,Trousers:Blue:worn,TShirt:Black:worn,Shoes:Gray:worn,Hat:Blue:worn,FurCoat:Beige:home,Bottle:White:bag
|
||||
person f8.c0 Фролов Евгений Павелович female=False roles=student class=class-classroom-00 born=2003-12-20 traits=AbsentMinded,Kind skills=Agility=69,BelarusianLanguage=26,Biology=50,Communication=28,Endurance=29,Hauling=45,Literature=52,Mathematics=31,PhysicalEducation=44,RussianLanguage=43,Strength=31,UkrainianLanguage=24 items=Underwear:Gray:worn,Socks:Black:worn,Trousers:Black:worn,Shirt:White:worn,WinterBoots:Beige:worn,Sweater:Gray:worn,FurCoat:Beige:worn,PeShirt:Green:home,PeShorts:Black:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f8.c1 Фролов Станислав Павелович female=False roles=student class=class-classroom-03 born=2000-10-11 traits=AbsentMinded,Lazy skills=Agility=57,BelarusianLanguage=20,Biology=56,Communication=57,Endurance=34,Hauling=42,Literature=71,Mathematics=23,PhysicalEducation=25,RussianLanguage=39,Strength=45,UkrainianLanguage=24 items=Underwear:Black:worn,Socks:White:worn,Jeans:Black:worn,TShirt:Black:worn,Shoes:Beige:worn,Jacket:Black:worn,Hat:Black:worn,PeShirt:Red:home,PeShorts:Green:home,Bottle:White:bag,Phone:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f8.p0 Фролов Павел Егорович female=False roles=parent class=- born=1968-06-07 traits=Leader skills=Administration=51,Agility=71,Chemistry=39,Communication=87,Endurance=39,English=42,Hauling=45,Informatics=65,Librarianship=57,RussianLanguage=73,Strength=45,UkrainianLanguage=26 items=Underwear:Gray:worn,Socks:Black:worn,Trousers:Gray:worn,TShirt:White:worn,WinterBoots:Black:worn,Sweater:Gray:worn,Coat:Black:home,Phone:Black:bag
|
||||
person f8.p1 Фролова Виктория Степановна female=True roles=parent class=- born=1963-10-04 traits=Curious,Leader skills=Agility=57,Chemistry=51,Communication=77,Endurance=45,English=33,Hauling=52,Librarianship=83,RussianLanguage=58,Strength=55 items=Underwear:White:worn,Socks:White:worn,Skirt:Beige:worn,Shirt:Gray:worn,WinterBoots:Black:worn,Coat:Gray:home,Bottle:Green:bag
|
||||
person f9.c0 Кузьмина Любовь Александровна female=True roles=student class=class-classroom-01 born=2003-06-13 traits=Kind skills=Agility=45,Biology=47,Communication=31,Endurance=32,Hauling=40,Literature=63,Mathematics=46,PhysicalEducation=48,RussianLanguage=41,Strength=44,UkrainianLanguage=5 items=Underwear:Black:worn,Socks:Gray:worn,Skirt:Beige:worn,Shirt:Blue:worn,WinterBoots:Gray:worn,Sweater:Blue:worn,FurCoat:Beige:worn,PeShirt:Gray:home,PeShorts:Green:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f9.c1 Кузьмин Сергей Александрович female=False roles=student class=class-classroom-03 born=2001-08-20 traits=Curious,Quiet skills=Agility=11,Biology=58,Communication=41,Endurance=59,Hauling=40,Literature=39,Mathematics=31,PhysicalEducation=40,RussianLanguage=51,Strength=52 items=Underwear:Gray:worn,Socks:Black:worn,Trousers:Gray:worn,TShirt:Gray:worn,Shoes:Beige:worn,Sweater:Beige:worn,Hat:Beige:worn,Scarf:Beige:worn,Coat:Gray:home,PeShirt:Gray:home,PeShorts:Blue:home,Bottle:White:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f9.c2 Кузьмина Алина Александровна female=True roles=student class=class-classroom-03 born=2001-01-22 traits= skills=Agility=52,Biology=38,Communication=29,Endurance=53,Hauling=34,Literature=63,Mathematics=31,PhysicalEducation=55,RussianLanguage=42,Strength=63,UkrainianLanguage=12 items=Underwear:White:worn,Socks:Gray:worn,Trousers:Blue:worn,Shirt:Blue:worn,WinterBoots:Gray:worn,Jacket:Gray:worn,Scarf:Gray:worn,PeShirt:Blue:home,PeShorts:Black:home,Bottle:Blue:bag,SchoolBag:-:bag,Textbook:-:bag:PhysicalEducation,Textbook:-:bag:PrimarySchool
|
||||
person f9.p0 Кузьмин Александр Денисович female=False roles=parent class=- born=1981-12-09 traits= skills=Agility=40,Chemistry=55,Communication=58,Endurance=78,English=57,Hauling=43,Pedagogy=52,RussianLanguage=67,Strength=63 items=Underwear:White:worn,Socks:White:worn,Jeans:Gray:worn,Shirt:Gray:worn,Shoes:Beige:worn,FurCoat:Beige:worn,Belt:Beige:worn,Bottle:Green:bag
|
||||
person f9.p1 Кузьмина Анастасия Сергеевна female=True roles=parent class=- born=1977-01-01 traits=Diligent skills=Agility=62,BelarusianLanguage=27,Communication=72,Endurance=92,Hauling=47,Librarianship=43,Pedagogy=48,RussianLanguage=67,Strength=34,UkrainianLanguage=21 items=Underwear:Black:worn,Socks:White:worn,Skirt:Blue:worn,Shirt:Blue:worn,Shoes:Beige:worn,Hat:Black:worn,Belt:Gray:worn,Jacket:Black:home,Bottle:White:bag
|
||||
|
||||
Reference in New Issue
Block a user