Merge branch 'phase/39-school-owners'
This commit is contained in:
@@ -11,31 +11,31 @@
|
||||
|
||||
## Задачи
|
||||
|
||||
- [ ] `SimulationOptions.MaxSchools` — слоты **игрока**, умолчание 2.
|
||||
- [x] `SimulationOptions.MaxSchools` — слоты **игрока**, умолчание 2.
|
||||
`MaxSchoolsTotal` — воркеры процесса, умолчание 16. Подъём с диска режет по Total, не по
|
||||
слотам игрока
|
||||
- [ ] Сейв несёт `owner`. Нет поля — бесхозная. Формат не бампить
|
||||
- [ ] Create пишет текущего пользователя; отказ: свои слоты кончились (`limit-reached`) или
|
||||
- [x] Сейв несёт `owner`. Нет поля — бесхозная. Формат не бампить
|
||||
- [x] Create пишет текущего пользователя; отказ: свои слоты кончились (`limit-reached`) или
|
||||
сервер полон (`server-full`)
|
||||
- [ ] `GET /api/schools`: `maxSchools` — слоты игрока, `maxSchoolsTotal`, `schools` — свои,
|
||||
- [x] `GET /api/schools`: `maxSchools` — слоты игрока, `maxSchoolsTotal`, `schools` — свои,
|
||||
`others` — чужие и бесхозные (`owner` имя или `null`). Карточка школы несёт `mine`
|
||||
- [ ] Welcome.`MaxSchools` — слоты игрока (байт тот же, смысл новый)
|
||||
- [ ] Мутации чужой — HTTP `403` `not-owner`. Бесхозную может удалить любой залогиненный.
|
||||
- [x] Welcome.`MaxSchools` — слоты игрока (байт тот же, смысл новый)
|
||||
- [x] Мутации чужой — HTTP `403` `not-owner`. Бесхозную может удалить любой залогиненный.
|
||||
`OpenSchool` — всем с сессией. Пауза / скорость / пропуск от гостя до работника не доходят.
|
||||
**Исключение:** `POST .../portrait` — гость генерирует теми же пресетами школы; это не управление
|
||||
- [ ] Меню: блок «Мои» и блок «Чужие». У бесхозной в чужих — удалить, у чужой с хозяином — нет
|
||||
- [ ] Внутри чужой школы нет вкладки «Управление» и нет кнопок часов (пауза, скорость, пропуск).
|
||||
- [x] Меню: блок «Мои» и блок «Чужие». У бесхозной в чужих — удалить, у чужой с хозяином — нет
|
||||
- [x] Внутри чужой школы нет вкладки «Управление» и нет кнопок часов (пауза, скорость, пропуск).
|
||||
Карта и люди остаются
|
||||
- [ ] `docs/protocol.md` — списки и коды ошибок. Версию сокета не бампить
|
||||
- [x] `docs/protocol.md` — списки и коды ошибок. Версию сокета не бампить
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [ ] Два пользователя: у каждого по две школы, третья своего — `limit-reached`; чужая в
|
||||
- [x] Два пользователя: у каждого по две школы, третья своего — `limit-reached`; чужая в
|
||||
`others`, не в `schools`
|
||||
- [ ] Восьмая школа на сервере с `MaxSchoolsTotal` = 7 — `server-full`, даже если у игрока слот есть
|
||||
- [ ] Гость: `POST` найма — `403`; `SetRunning` не меняет `running` хозяина
|
||||
- [ ] Сейв без `owner` поднимается, лежит в `others`, удаляется вторым пользователем
|
||||
- [ ] Клиентский тест: чужая карточка без кнопки удаления; в чужой школе нет «Управление»
|
||||
- [x] Восьмая школа на сервере с `MaxSchoolsTotal` = 7 — `server-full`, даже если у игрока слот есть
|
||||
- [x] Гость: `POST` найма — `403`; `SetRunning` не меняет `running` хозяина
|
||||
- [x] Сейв без `owner` поднимается, лежит в `others`, удаляется вторым пользователем
|
||||
- [x] Клиентский тест: чужая карточка без кнопки удаления; в чужой школе нет «Управление»
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
|
||||
| Фаза | Статус | Зачем |
|
||||
| --- | --- | --- |
|
||||
| [39. Хозяин школы](39-school-owners.md) | 🔄 | `owner`, 2 слота на игрока, мои / чужие, гость без управления |
|
||||
| [39. Хозяин школы](39-school-owners.md) | ✅ | `owner`, 2 слота на игрока, мои / чужие, гость без управления |
|
||||
|
||||
39 стоит на 38.
|
||||
|
||||
|
||||
+22
-7
@@ -76,16 +76,26 @@ people; it does not change on a living school.
|
||||
|
||||
```json
|
||||
{
|
||||
"maxSchools": 6,
|
||||
"maxSchools": 2,
|
||||
"maxSchoolsTotal": 16,
|
||||
"defaultStartDate": "2012-03-31T06:00:00Z",
|
||||
"gameMinutesPerRealSecond": 1,
|
||||
"schoolWeekDays": 5,
|
||||
"schools": [
|
||||
{ "id": 1, "name": "Гимназия №14", "gameTime": "2012-03-31T07:35:00Z", "running": false, "speedIndex": 1, "modIds": ["core"], "seed": 1847291 }
|
||||
{ "id": 1, "name": "Гимназия №14", "gameTime": "2012-03-31T07:35:00Z", "running": false, "speedIndex": 1, "modIds": ["core"], "seed": 1847291, "mine": true }
|
||||
],
|
||||
"others": [
|
||||
{ "id": 2, "name": "Лицей", "gameTime": "2012-03-31T06:00:00Z", "running": true, "speedIndex": 1, "modIds": ["core"], "seed": 9912, "owner": "Leo" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`maxSchools` is how many schools **this player** may own; `maxSchoolsTotal` is how many workers the
|
||||
process runs. `schools` lists yours (`mine: true` on each card). `others` lists every other save on
|
||||
the server — `owner` is the display name, or `null` when the save has no owner (any logged-in player
|
||||
may delete an ownerless card). The WebSocket welcome frame still carries one byte for
|
||||
`maxSchools`; it now means the same per-player limit, not the process total.
|
||||
|
||||
### `GET /api/schools/random-name`
|
||||
|
||||
`{ "name": "Лицей «Северная»" }` — a suggestion that is not already taken.
|
||||
@@ -197,13 +207,15 @@ the global file, so a guest watching the school draws with the same model.
|
||||
| `400` `unknown-country` | `countryId` is not a placeable `CountryDef` in those packs. |
|
||||
| `400` `unknown-native-language` | `nativeLanguage` is not in that country's `nativeLanguages`. |
|
||||
| `400` `invalid-portrait-settings` | `portraitSettings` failed validation (empty presets, bad age rule, out of range). |
|
||||
| `409` `school-limit-reached` | `maxSchools` schools already exist. |
|
||||
| `409` `school-limit-reached` | This player already owns `maxSchools` schools. |
|
||||
| `409` `server-full` | The process already runs `maxSchoolsTotal` schools. |
|
||||
|
||||
Failures are RFC 7807 problem details with an extra `code` field — that is what the UI switches on.
|
||||
|
||||
### `DELETE /api/schools/{id}`
|
||||
|
||||
`204` when deleted, `404` when the id is unknown. Anyone watching that school over a WebSocket
|
||||
`204` when deleted, `404` when the id is unknown, `403` `not-owner` when the school belongs to
|
||||
another player. Ownerless saves may be deleted by any logged-in session. Anyone watching that school over a WebSocket
|
||||
gets a `SchoolGone` frame.
|
||||
|
||||
### `GET /api/schools/{id}/people`
|
||||
@@ -497,7 +509,8 @@ is off or unreachable, `connected` is false and the lists are empty.
|
||||
|
||||
### `GET /api/schools/{id}/dress-rules`
|
||||
|
||||
Student and staff dress-code pairs for the school. Unknown `{id}` is `404` `unknown-school`.
|
||||
Student and staff dress-code pairs for the school. Only the owner may read this (`403` `not-owner`).
|
||||
Unknown `{id}` is `404` `unknown-school`.
|
||||
|
||||
`form` is one of `regular`, `short`, `strict`. `color` is one of `noBright`, `whiteTopBlackBottom`,
|
||||
`free`. When a `POST` has been accepted but not yet applied, `pendingStudents` and/or `pendingStaff`
|
||||
@@ -515,7 +528,7 @@ not immediately.
|
||||
|
||||
### `POST /api/schools/{id}/dress-rules`
|
||||
|
||||
Queues a change for the next work morning. Either or both of `students` and `staff` may be sent;
|
||||
Queues a change for the next work morning. Only the owner may post (`403` `not-owner`). Either or both of `students` and `staff` may be sent;
|
||||
omitted sides keep their current rule. Unknown `{id}` is `404` `unknown-school`. Unknown `form` or
|
||||
`color` is `400` `unknown-form` / `400` `unknown-color`. Response body matches `GET`.
|
||||
|
||||
@@ -525,7 +538,8 @@ omitted sides keep their current rule. Unknown `{id}` is `404` `unknown-school`.
|
||||
|
||||
### `GET /api/schools/{id}/staffing`
|
||||
|
||||
Money, uncovered subjects, the applicant pool and current staff. Reads the **published**
|
||||
Money, uncovered subjects, the applicant pool and current staff. Only the owner may read this
|
||||
(`403` `not-owner`). Reads the **published**
|
||||
roster, applicant snapshot and catalog — it does not post to the worker. Unknown `{id}` is
|
||||
`404` `unknown-school`. `?lang=ru|en` labels subjects and positions.
|
||||
|
||||
@@ -619,6 +633,7 @@ of that kind.
|
||||
|
||||
| Status | `code` | When |
|
||||
| --- | --- | --- |
|
||||
| `403` | `not-owner` | The session is not the school's owner. |
|
||||
| `404` | `unknown-school` | No school with that id. |
|
||||
| `404` | `unknown-applicant` | `personId` is not in the pool. |
|
||||
| `409` | `already-hired` | That person is already staff. |
|
||||
|
||||
Reference in New Issue
Block a user