Merge phase 26 school seed.
ci / server (push) Failing after 3m34s
ci / client (push) Failing after 12s

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-20 00:43:33 +03:00
co-authored by Cursor
18 changed files with 237 additions and 35 deletions
+6 -2
View File
@@ -261,10 +261,14 @@ Protocol ← Server → Simulation → People → Content
### Детерминизм
Генерация детерминирована от **сида**, сид лежит в файле школы. Один сид + одна карта + один набор
Генерация детерминирована от **сида**. Сид — своё поле школы, не её идентификатор: при создании
его бросает сервер, либо его передают в `POST /api/schools`. Он лежит в файле людей и виден в
списке школ и на экране школы, чтобы им можно было поделиться. Один сид + одна карта + один набор
имён + один родной язык = одна и та же школа, всегда. Если родной язык при создании не указан,
его выбирает тот же сид — повтор без поля даёт тот же язык.
Существующие школы не перебрасываются: они продолжают жить с числом, уже записанным в файле людей.
Сид у каждой семьи свой, выведенный из школьного: добавление тринадцатой семьи не должно менять
первые двенадцать. Иначе тест на генератор ломается от любой правки порядка.
@@ -389,7 +393,7 @@ Protocol ← Server → Simulation → People → Content
| Падежи | Правило по умолчанию (код), явная таблица как исключение (данные) |
| Имена и язык UI | Независимы |
| Библиотека | `HSchool.People`: зависит от Content, не знает Arch и ASP.NET |
| Детерминизм | Сид в сейве, свой сид на семью; родной язык — часть входа |
| Детерминизм | Свой сид школы (не id), в сейве и в API; свой сид на семью; родной язык — часть входа |
| Просмотр | Панель в оболочке менеджера, вкладкой рядом с картой; не отдельный экран |
| Список | Фильтры, сортировки, пейджинг; в строке — только лёгкие поля |
| Транспорт списка | HTTP по опубликованному снимку ростера |
+10 -10
View File
@@ -15,20 +15,20 @@
## Задачи
- [ ] При создании школы сид берётся из генератора случайных чисел сервера, а не из id
- [ ] `POST /api/schools` принимает необязательный `seed`; передали — берётся он, нет — бросается
- [ ] Сид виден: в ответе `GET /api/schools` и на экране школы, чтобы его можно было переслать
- [ ] Существующие школы не меняются: сид читается из файла людей, как и сейчас
- [ ] Тесты хоста, которым нужен предсказуемый состав, передают сид явно, а не полагаются на
- [x] При создании школы сид берётся из генератора случайных чисел сервера, а не из id
- [x] `POST /api/schools` принимает необязательный `seed`; передали — берётся он, нет — бросается
- [x] Сид виден: в ответе `GET /api/schools` и на экране школы, чтобы его можно было переслать
- [x] Существующие школы не меняются: сид читается из файла людей, как и сейчас
- [x] Тесты хоста, которым нужен предсказуемый состав, передают сид явно, а не полагаются на
порядок создания
- [ ] `docs/protocol.md` и [`../design/people.md`](../design/people.md) правятся тем же коммитом
- [x] `docs/protocol.md` и [`../design/people.md`](../design/people.md) правятся тем же коммитом
## Тесты, без которых фаза не закрыта
- [ ] Две школы, созданные с одним сидом, населены одинаково; с разными — по-разному
- [ ] Школа, созданная без сида, после перезапуска поднимает тот же состав
- [ ] Старый сейв, где сид совпадал с id, грузится и состав не меняется
- [ ] Переданный сид виден в списке школ
- [x] Две школы, созданные с одним сидом, населены одинаково; с разными — по-разному
- [x] Школа, созданная без сида, после перезапуска поднимает тот же состав
- [x] Старый сейв, где сид совпадал с id, грузится и состав не меняется
- [x] Переданный сид виден в списке школ
## Критерий готовности
+1 -1
View File
@@ -110,6 +110,6 @@
| [23. Пример мода](23-example-pack.md) | ⬜ | Настоящая папка вместо документов в памяти |
| [24. Числа поведения](24-behavior-numbers.md) | ✅ | Веса целей в `BehaviorDef`, а не в коде |
| [25. Золотые файлы](25-golden-fixtures.md) | ✅ | Отпечаток ростера, старый сейв, кривая голода, нехватка учителей |
| [26. Свой сид](26-school-seed.md) | 🔄 | Состав школы перестаёт зависеть от порядка создания |
| [26. Свой сид](26-school-seed.md) | | Состав школы перестаёт зависеть от порядка создания |
| [27. Версия сейва и дамп](27-serviceability.md) | ✅ | Формат читается, внутрь школы можно заглянуть |
| [28. Тесты экранов](28-screen-tests.md) | ⬜ | DOM-окружение и логика клиента под тестом |
+7 -2
View File
@@ -32,6 +32,8 @@ the wire format is unambiguous, and the client formats it back in UTC.
Everything the main menu needs in one request. `schoolWeekDays` is 57 working days counted
from Monday (five is MonFri; six adds Saturday). It is a school rule, not a catalog def.
`seed` is the roster generator seed: it is not the school id. Share it to recreate the same
people; it does not change on a living school.
```json
{
@@ -40,7 +42,7 @@ from Monday (five is MonFri; six adds Saturday). It is a school rule, not a c
"gameMinutesPerRealSecond": 5,
"schoolWeekDays": 5,
"schools": [
{ "id": 1, "name": "Гимназия №14", "gameTime": "2012-03-31T07:35:00Z", "running": false, "speedIndex": 1, "modIds": ["core"] }
{ "id": 1, "name": "Гимназия №14", "gameTime": "2012-03-31T07:35:00Z", "running": false, "speedIndex": 1, "modIds": ["core"], "seed": 1847291 }
]
}
```
@@ -117,7 +119,8 @@ Body:
"modIds": [],
"map": null,
"nameSetId": "Slavic",
"nativeLanguage": null
"nativeLanguage": null,
"seed": null
}
```
@@ -129,6 +132,8 @@ the same catalog. Omit `map` (or send `null`) to use that pack set's default lay
`Slavic`). Unknown ids return `400` `unknown-name-set`.
`nativeLanguage` is a skill from that set's `nativeLanguages`. Omit it (or send `null`) to pick
one from the school seed. An id that is not in the set returns `400` `unknown-native-language`.
`seed` is an optional integer. Send it to reproduce a known school; omit it (or send `null`) and
the server rolls one. Existing saves keep the seed already stored in the people file.
| Status | Meaning |
| --- | --- |