Enhance SwarmUI settings by adding a scheduler property and updating the client to send clip stop at layer instead of clip skip. Added tests to verify the new behavior.
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
# Фаза 38. Сессия
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 1](01-manager-shell.md)
|
||||
- [Фаза 2](02-school-worker.md)
|
||||
- [Фаза 28](28-screen-tests.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
В клиент не пускает без пароля альфы и имени. Имя запоминается. Сокет открывается только после
|
||||
сессии. Школы пока общие — хозяин в фазе 39.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [ ] `HSchool:AlphaPassword` в конфиге; пустая строка — процесс не стартует. В `appsettings.json`
|
||||
заглушка для локальной игры; headless AppHost задаёт тестовый пароль окружением
|
||||
- [ ] `POST /api/session` `{ password, userName }`: неверный пароль — `401` `bad-password`;
|
||||
кривое имя — `400` `invalid-name` (те же правила, что у школы); имя с живым сокетом —
|
||||
`409` `name-online`. Успех ставит HttpOnly-куку и при первом разе пишет имя в
|
||||
`saves/users.json` (занятость без учёта регистра)
|
||||
- [ ] `GET /api/session` — текущее имя или `401`. `DELETE /api/session` снимает куку
|
||||
- [ ] Все игровые HTTP без куки — `401`. Живут без неё: `/health` и три ручки сессии
|
||||
- [ ] WebSocket без куки не шлёт Welcome, закрывается. Hello по-прежнему версия + локаль
|
||||
- [ ] Клиент: шаг пароля, шаг имени; при живой куке оба пропускаются. Сокет — после сессии.
|
||||
Кнопка выхода на меню
|
||||
- [ ] Хостовые тесты логинятся в общем месте (`ResetAsync` или рядом), не в каждом факте
|
||||
- [ ] `docs/protocol.md` — HTTP сессии в том же коммите. Раскладку сокета и версию не трогать
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [ ] Без сессии `GET /api/schools` — `401`; после `POST /api/session` — `200`
|
||||
- [ ] Верный пароль и новое имя пишут `users.json`; повтор с тем же именем (другой регистр) —
|
||||
тот же человек, не вторая запись
|
||||
- [ ] Пока сокет имени жив, второй `POST /api/session` с ним — `409` `name-online`
|
||||
- [ ] Сокет без куки закрывается, Welcome не приходит
|
||||
- [ ] Клиентский тест: без куки виден ввод пароля, не сетка школ
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Открыть клиент, ввести пароль и имя, попасть в меню; обновить страницу — снова меню, без формы
|
||||
- `dotnet test` и `npm test` / `build` проходят
|
||||
|
||||
## Стоп
|
||||
|
||||
Не делить школы на мои/чужие. Не менять `MaxSchools`. Не трогать таблицу скоростей.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Фаза 39. Хозяин школы
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 38](38-session.md)
|
||||
- [Фаза 13](13-management-tab.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
У школы есть хозяин. Свои слоты — свои, чужие смотрят отдельно и не управляют.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [ ] `SimulationOptions.MaxSchools` — слоты **игрока**, умолчание 2.
|
||||
`MaxSchoolsTotal` — воркеры процесса, умолчание 16. Подъём с диска режет по Total, не по
|
||||
слотам игрока
|
||||
- [ ] Сейв несёт `owner`. Нет поля — бесхозная. Формат не бампить
|
||||
- [ ] Create пишет текущего пользователя; отказ: свои слоты кончились (`limit-reached`) или
|
||||
сервер полон (`server-full`)
|
||||
- [ ] `GET /api/schools`: `maxSchools` — слоты игрока, `maxSchoolsTotal`, `schools` — свои,
|
||||
`others` — чужие и бесхозные (`owner` имя или `null`). Карточка школы несёт `mine`
|
||||
- [ ] Welcome.`MaxSchools` — слоты игрока (байт тот же, смысл новый)
|
||||
- [ ] Мутации чужой — HTTP `403` `not-owner`. Бесхозную может удалить любой залогиненный.
|
||||
`OpenSchool` — всем с сессией. Пауза / скорость / пропуск от гостя до работника не доходят
|
||||
- [ ] Меню: блок «Мои» и блок «Чужие». У бесхозной в чужих — удалить, у чужой с хозяином — нет
|
||||
- [ ] Внутри чужой школы нет вкладки «Управление» и нет кнопок часов (пауза, скорость, пропуск).
|
||||
Карта и люди остаются
|
||||
- [ ] `docs/protocol.md` — списки и коды ошибок. Версию сокета не бампить
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [ ] Два пользователя: у каждого по две школы, третья своего — `limit-reached`; чужая в
|
||||
`others`, не в `schools`
|
||||
- [ ] Восьмая школа на сервере с `MaxSchoolsTotal` = 7 — `server-full`, даже если у игрока слот есть
|
||||
- [ ] Гость: `POST` найма — `403`; `SetRunning` не меняет `running` хозяина
|
||||
- [ ] Сейв без `owner` поднимается, лежит в `others`, удаляется вторым пользователем
|
||||
- [ ] Клиентский тест: чужая карточка без кнопки удаления; в чужой школе нет «Управление»
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Два браузера, два имени: каждый видит свою сетку и чужие отдельным блоком; в чужой школе
|
||||
часы чужие не нажимаются
|
||||
- `dotnet test` и `npm test` / `build` проходят
|
||||
|
||||
## Стоп
|
||||
|
||||
Не отдавать бесхозную в слот игрока. Не показывать гостю «Управление» даже чтением.
|
||||
Не менять скорости.
|
||||
@@ -0,0 +1,45 @@
|
||||
# Фаза 40. Темп часов
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 2](02-school-worker.md)
|
||||
- [Фаза 20](20-needs-actions.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
×1 можно смотреть. Высокие скорости — ×5 и ×10, без лишней работы ходьбы и нужд на каждом
|
||||
импульсе календаря.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [ ] `GameMinutesPerRealSecond` по умолчанию 1 (опции, `appsettings.json`, `GET /api/schools`)
|
||||
- [ ] `ClockSpeed.Multipliers`: `0.5, 1, 2, 5, 10`. Зеркало в `protocol.ts`. Подписи кнопок:
|
||||
×½ ×1 ×2 ×5 ×10. Стартовый индекс по-прежнему 1
|
||||
- [ ] Воркер будит мир 20 раз в секунду на любой скорости. `GameClock.Advance`, граница лога
|
||||
6:00, годовой набор, пул соискателей, погода — каждый импульс
|
||||
- [ ] На индексах ×5 и ×10 ходьба, действия, решения, нужды, тепло, обучение, износ — раз в
|
||||
4 и раз в 2 импульса соответственно, с накопленными минутами (квант — 1 игровая минута).
|
||||
На ×½ ×1 ×2 — каждый импульс, как сейчас
|
||||
- [ ] Не прыгать календарём одним жирным `Tick` вместо страйда
|
||||
- [ ] Комментарий меню про «минута за 12 секунд» привести к новой базе
|
||||
- [ ] `docs/protocol.md` — таблица множителей. Раскладку и версию сокета не трогать
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [ ] 20 шагов по 1/20 с на ×1 сдвигают календарь на 1 игровую минуту, не на 5
|
||||
- [ ] Индексы 3 и 4 за одну реальную секунду дают 5 и 10 игровых минут
|
||||
- [ ] На ×10 за 20 импульсов ходьба/нужды вызваны 10 раз, календарь — 20; накопленный аргумент
|
||||
минут на тяжёлый вызов — 1
|
||||
- [ ] Невалидный индекс 5 по-прежнему игнорируется
|
||||
- [ ] Клиентский тест: пять кнопок ×½ ×1 ×2 ×5 ×10
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- На ×1 секунда реального времени = минута в школе; ×10 не кладёт воркер, люди не телепортируются
|
||||
на десять минут за кадр
|
||||
- `dotnet test` и `npm test` / `build` проходят
|
||||
|
||||
## Стоп
|
||||
|
||||
Не менять `TickRate` и потолок догона воркера. Не урезать рассылку кадров часов. Не трогать
|
||||
сессию и хозяина.
|
||||
@@ -153,3 +153,32 @@
|
||||
|
||||
34 стоит на 31; 35 — на 32–34; 36 — на 31 и может идти параллельно с 35 в части вкладок одежды,
|
||||
история — после 35; 37 стоит на 35 и 36.
|
||||
|
||||
## Срез 8. Сессия и темп
|
||||
|
||||
Дизайн: [`../design/session.md`](../design/session.md).
|
||||
|
||||
Несколько браузеров на одном сервере: общий пароль альфы, имя игрока, свои школы и чужие
|
||||
отдельным списком. Часы становятся смотрибельными — минута за секунду, на высоких скоростях
|
||||
тяжёлые системы тикают реже. Срез можно остановить после этапа B: мультиплеер жив, даже если
|
||||
темп ещё старый.
|
||||
|
||||
**Этап A — кто вошёл.** Пароль, имя, кука.
|
||||
|
||||
| Фаза | Статус | Зачем |
|
||||
| --- | --- | --- |
|
||||
| [38. Сессия](38-session.md) | ⬜ | Пароль альфы, имя, кука, сокет после входа |
|
||||
|
||||
**Этап B — чьи школы.** Хозяин, слоты, гость только смотрит.
|
||||
|
||||
| Фаза | Статус | Зачем |
|
||||
| --- | --- | --- |
|
||||
| [39. Хозяин школы](39-school-owners.md) | ⬜ | `owner`, 2 слота на игрока, мои / чужие, гость без управления |
|
||||
|
||||
39 стоит на 38.
|
||||
|
||||
**Этап C — темп.** Не зависит от A/B, можно вести параллельно с 38.
|
||||
|
||||
| Фаза | Статус | Зачем |
|
||||
| --- | --- | --- |
|
||||
| [40. Темп часов](40-clock-tempo.md) | ⬜ | ×1 = минута/с, кнопки ×½ ×1 ×2 ×5 ×10, страйд тяжёлых систем |
|
||||
|
||||
Reference in New Issue
Block a user